One time pad, encryption and decryption

16,274

Solution 1

Here you have a full working example:

    // convert secret text to byte array
    final byte[] secret = "secret".getBytes()

    final byte[] encoded = new byte[secret.length];
    final byte[] decoded = new byte[secret.length];

    // Generate random key (has to be exchanged)
    final byte[] key = new byte[secret.length];
    new SecureRandom().nextBytes(key);

    // Encrypt
    for (int i = 0; i < secret.length; i++) {
        encoded[i] = (byte) (secret[i] ^ key[i]);
    }

    // Decrypt
    for (int i = 0; i < encoded.length; i++) {
        decoded[i] = (byte) (encoded[i] ^ key[i]);
    }

    assertTrue(Arrays.equals(secret, decoded));

Solution 2

For the one time pad you need a byte array, not hexadecimals. The hexadecimals are only required for displaying data (we tend to have trouble reading bits). You can use the Apache Commons libraries (codec package) to create hexadecimals from byte arrays, or back if you want to decode the test vectors from hexadecimals to bytes.

You should use a secure random number generator, not Random. So use new SecureRandom() instead. To generate random data, first create a byte array, then call nextBytes() on the random number generator. There is not need to generate integers.

Solution 3

First here is a OTP algorithm specified called HOTP which is a standard RFC. Almost all other OTP are propriety and we don't know the algorithm for those.

https://www.rfc-editor.org/rfc/rfc4226

There is some java code in there you can use to learn how its done. Second if you are going to do encryption don't use Random. Random is nice for psuedo random, but if you really want a good source of random data you need to adopt SecureRandom. That's a much better source of random numbers that are suitable for cryto algorithms.

For converting things to Hex you can easily use

http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigInteger.html#toString(int)

Or any of the varieties Long.toString(value,radix), Integer.toString(value,radix), or Byte.toString(value,radix).

byte[] bytes = ...;
for( int i = 0; i < bytes.length; i++ ) {
    System.out.println( Integer.toString( bytes[i], 16 );
}
Share:
16,274
user1792962
Author by

user1792962

Updated on June 13, 2022

Comments

  • user1792962
    user1792962 almost 2 years

    I am trying to pick up cryptography and had been trying this exercise

    Write a program (preferably Java) to generate a one-time pad, which is a relatively large file of all random data (say 1 MB). The program should also be able to encrypt/decrypt files based on the generated one time pad.

    Tip: use the following test vector to check if your program does encryption correctly.

    Plaintext (ASCII): Every cloud has a silver lining
    OTP (HEX): 6dc72fc595e35dcd38c05dca2a0d2dbd8e2df20b129b2cfa29ad17972922a2
    ciphertext (HEX): 28b14ab7ecc33ea157b539ea426c5e9def0d81627eed498809c17ef9404cc5

    I have tried to generate a one time pad using random number generator as I need to convert them to HEX form. and I am pretty sure I am confused or not tackling it the right way

    public static void oneTimePad()
    {
        Random ran = new Random();
        String s = "0123456789ABCDEF";
        for(int i = 0; i < 100; i++)
        {   
            System.out.print(s.charAt(ran.nextInt(s.length())));
        }
    }
    

    Above would be my one time pad, and I was wondering how any idea how I could implement the encryption using the one time pad and decrypting it.

  • user1792962
    user1792962 over 11 years
    Hi, how do I use apache commons libraries? Or get it installed in eclipse. Sorry for the noobish question.
  • Maarten Bodewes
    Maarten Bodewes over 11 years
    Download it here, unzip it and put the jar in the "build path" of your project (external library)
  • Maarten Bodewes
    Maarten Bodewes over 11 years
    Darn, that should probably be "external .jar". Sorry for that :)
  • Maarten Bodewes
    Maarten Bodewes over 11 years
    PS you don't need to generate random numbers from 0..15, you need to generate a byte, which is then encoded in hex as values between '00'h and 'FF'h.
  • user1792962
    user1792962 over 11 years
    Hi, cause i need to use the OTP which would be the code above, generating random hexidecimal character...but my question is on the encryption bit, could you shed some light for me?
  • Maarten Bodewes
    Maarten Bodewes over 11 years
    You don't need the hexadecimals for the encryption. Encryption is performed on bits, or, because it is the minimal number of bits a computer handles, on bytes. You only need the hexadecimals for displaying the bytes.
  • Montre
    Montre over 11 years
    HOTP isn't a one-time-pad encryption scheme, it's an algorithm to generate one-time-passwords. (For stuff like bank transactions; it's related to what the battle.net authenticator does.)
  • user1792962
    user1792962 over 11 years
    thanks. not sure that I grasp what you're trying to tell me, I don't really understand the bits and bytes part for java... :S sorry!
  • Maarten Bodewes
    Maarten Bodewes over 11 years
    Last try before sleeping: bytes is the data, e.g. the OTP key stream. Hexadecimals is the representation of that data for human eyes. The computer does not "know" hexadecimals, it cannot use XOR on them. It can only XOR bits and bytes.
  • imichaelmiers
    imichaelmiers over 11 years
    In this case he means one time pad, not one time password.
  • chubbsondubs
    chubbsondubs over 11 years
    Yea I was a bit confused about OTP and him saying one time pad so I assumed, incorrectly, he wanted One Time Passwords, but I kept the answer because the other two answers are still valid. Shrug
  • Admin
    Admin about 11 years
    +1 for mentioning most OTP are proprietary. I was going to ask a question for review of a possible OTP algorithm, now I'm thinking I may not just based on that... Then again... what have I got to lose?