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
<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
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();
}
}
}
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;
}
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.
http://tools.ietf.org/html/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 );
}
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));
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.