8

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.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
user1792962
  • 81
  • 1
  • 1
  • 3
  • 3
    ..what is your question? – Andrew Thompson Nov 02 '12 at 00:40
  • Hex is 0123456789ABCDEF. – Ben Nov 02 '12 at 00:48
  • To implement the description you can choose any transformation that is reversible if you know the pad. byte-wise XORing is the first such operation that comes to mind, but it doesn't work for your example plaintext+pad+ciphertext – millimoose Nov 02 '12 at 01:54
  • @millimoose,what would work for my example then? :) – user1792962 Nov 02 '12 at 02:00
  • @user1792962 Well, if this were in a college course, "emailing the instructor". It's really not very easy to eyeball how a bunch of bits was transformed into another bunch of bits. – millimoose Nov 02 '12 at 02:13
  • @user1792962 Wait, I'm an idiot. I forgot to convert the number I was looking at to hex before checking against your example. Yes, the example does XOR the plaintext with the pad. – millimoose Nov 02 '12 at 02:16
  • "generate a one time pad using random number generator" It's not a one-time-pad if you use a PRNG to create it. A one-time-pad must be created using an unbiased true RNG. Why use a one-time-pad instead of a stream cipher? – CodesInChaos Nov 02 '12 at 12:09
  • @CodesInChaos I think theoretically speaking you are correct. Practically speaking it does not make much of a difference. And this is clearly something of an assignment. Learning how to do the `XOR`-ing and (character) encoding/decoding is important (I think about 50% of the questions here are about encoding alone). – Maarten Bodewes Nov 03 '12 at 12:02
  • Getting anywhere @user1792962? – Maarten Bodewes Nov 03 '12 at 12:04
  • @user1792962 You can use Random for OTP but for validating and all I think you should prefer this article so it will be more stronger and even easy I'm not able to understand your code. Here is link https://howtodoinjava.com/security/how-to-generate-secure-password-hash-md5-sha-pbkdf2-bcrypt-examples/#PBKDF2WithHmacSHA1 – Swapnil Apr 03 '20 at 14:48

6 Answers6

11

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));
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Literadix
  • 1,379
  • 1
  • 18
  • 31
3

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.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Hi, how do I use apache commons libraries? Or get it installed in eclipse. Sorry for the noobish question. – user1792962 Nov 02 '12 at 01:09
  • Download it [here](http://commons.apache.org/codec/download_codec.cgi), unzip it and put the jar in the "build path" of your project (external library) – Maarten Bodewes Nov 02 '12 at 01:10
  • Darn, that should probably be "external .jar". Sorry for that :) – Maarten Bodewes Nov 02 '12 at 01:26
  • 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. – Maarten Bodewes Nov 02 '12 at 01:33
  • 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? – user1792962 Nov 02 '12 at 01:41
  • 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. – Maarten Bodewes Nov 02 '12 at 01:46
  • 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! – user1792962 Nov 02 '12 at 02:02
  • 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. – Maarten Bodewes Nov 02 '12 at 02:08
2

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 );
}
Community
  • 1
  • 1
chubbsondubs
  • 37,646
  • 24
  • 106
  • 138
  • 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.) – millimoose Nov 02 '12 at 01:52
  • In this case he means one time pad, not one time password. – imichaelmiers Nov 04 '12 at 22:57
  • 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* – chubbsondubs Nov 06 '12 at 02:29
  • +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? –  Mar 14 '13 at 11:48
0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace one_time_pad
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("                   TRYING\n");

            Console.WriteLine("Enter : ");
            int input= int.Parse( Console.ReadLine());

            //random num generation
            Random rnd = new Random();
            int random = rnd.Next(1,10);

            //binary conversion
            string binary = Convert.ToString(random,2);
            string inbinary = Convert.ToString(input,2);

            Console.WriteLine("Data :   " +input +"   Binary :   " + inbinary);
            Console.WriteLine(" Key :   " +random + "   Binary :    " + binary);    

            // taking xor
            int Ghul = input ^ random;

            //binary conversion
            string intcon = Convert.ToString(Ghul,2);

            Console.WriteLine("Encrypted : " + intcon);

            Console.WriteLine(":)");

            Console.Read();    
        }
    }
}
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Hur Abbas
  • 115
  • 10
0

https://en.wikipedia.org/wiki/One-time_pad

public static String crypt(String string, String keyString) {
    // convert secret text to byte array
    byte[] bytes = string != null ? string.getBytes() : new byte[0];
    int size = bytes != null ? bytes.length : 0;
    final byte[] encoded = new byte[size];
    final byte[] key = keyString != null ? keyString.getBytes() : new byte[0];
    // loop on input  bytes
    for (int i = 0; i < size; i++) {
        // shift key index 
        // (we assume key can be smaller or equal if larger then adjust)
        int keyi = i >= keySize ? size % (keySize-1) : i;
        // pad
        encoded[i] = (byte) (bytes[i] ^ key[keyi]);
    }
    return new String(encoded);
}

public static void test(String string, String keyString) {
    String encrypt = crypt(string, keyString);
    String decrypt = crypt(encrypt, keyString);
    assert(string.equals(decrypt));
}
  • test("test","1234");
  • test("test","123");

ps. you can refactor method by pull strings up and replace with bytes

public static byte[] crypt(byte[] bytes, byte[] key) {
    int size = bytes != null ? bytes.length : 0;
    final byte[] encoded = new byte[size];
    int keySize = key != null ? key.length : 0;
    // loop on input bytes 
    for (int i = 0; i < size; i++) {
        // shift key index (assuming key <= bytes)
        int keyi = i >= keySize ? size % (keySize-1) : i;
        // pad 
        encoded[i] = (byte) (bytes[i] ^ key[keyi]);
    }
    return encoded;
}
ceph3us
  • 7,326
  • 3
  • 36
  • 43
0
<dependency>
    <groupId>work.eddiejamsession</groupId>
    <artifactId>jam-one-time-pad</artifactId>
    <version>0.67</version>
</dependency>
JamOneTimePad pad = new JamOneTimePad();
String heyEncrypted = pad.encrypt("hey"); //encodes additionally in base64 for url safety
String heyDecrypted = pad.decrypt(heyEncrypted);
System.out.println(heyDecrypted.equals("hey"));
Output: true
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Eddie Jamsession
  • 1,006
  • 6
  • 24