I want to generate a secret key (128 bit) based upon some predefined seed value .
Currently i am using javax.crypto.KeyGenerator (AES) to generate key using secureRandom .
How can i pass my own seen rather than using secureRandom object .
code i am currently using :
//
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128,SecureRandom random); // 128 bits key size
key = kgen.generateKey();
//
Thank You ..
You can set the seed of the SecureRandom.
SecureRandom random = new SecureRandom();
random.setSeed(1000L);
When testing this i did notice that to get consistant results you had to recreate the KeyGenerator if you changed the seed at any time.
Related
Im new to cryptography in Java and I am trying to write a program to encrypt and decrypt a phrase using DES symmetric cipher, based on CBC mode of operation.
Can anyone tell me how to go about creating an 8-byte initialization vector and how to cast the new IV into AlgorithmParameterSpec class?
Also, which packages should I import?
Edit: Right now I have these lines:SecureRandom sr = new SecureRandom(); //create new secure random
byte [] iv = new byte[8]; //create an array of 8 bytes
sr.nextBytes(iv); //create random bytes to be used for the IV (?) Not too sure.
IvParameterSpec IV = new IvParameterSpec(iv); //creating the IV
Is my above approach correct?
Thanks.
Yes. Till Now You are right.
the Class IvParameterSpec is used to pass Initial Vector to Class Cipher
After this create a Cipher as below
Cipher cipherInstance = Cipher.getInstance("DES/CBC/NoPadding");
here DES/CBC/NoPadding is used because you are useing DES encryption in CBC mode.
Next is initializing it.
cipherInstance.init(Cipher.DECRYPT_MODE, Key, ivParameterSpec);
Parameters are:
1st is mode of encryption either Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE
2nd is Secret Key You have generated using Class SecretKey
3rd is generated ivParameterSpec
and last line is
outData = cipherInstance.doFinal(input);
if mode is Decrypt it will return decrypted data and if mode is Encrypt it will return encrypted data.
Last but important catch all the Exceptions properly.
And you are done
I have the following decryption algorithm implemented in Java. Is information "AES128" enough for other people to implement it in other languages or a more accurate definition is required?
// input data
byte[] secretKey = { ... };
byte[] encryptedData = { ... };
// decryption
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(secretKey);
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128, random);
SecretKey sk = keyGen.generateKey();
SecretKeySpec keySpec = new SecretKeySpec(sk.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec IV16 = new IvParameterSpec(keySpec.getEncoded());
cipher.init(Cipher.DECRYPT_MODE, keySpec, IV16);
byte[] decrypted = cipher.doFinal(encryptedData);
The name of the encryption algorithm itself is AES-128. It's being used in the cipher block chaining mode (this describes how to connect the encryption of multiple sequential blocks), with PKCS #5 padding (this describes how to pad messages up to the size of a full block). Other languages might have different techniques for specifying mode and padding.
AES is the algo, and 128bit the key size. I would say it's pretty clear ...
Essential properties of that algorithm are:
AES
128-bit key
CBC blocks
PKCS-5 aka PKCS-7
Also the following custom tactics used:
custom IV generation from a pass phrase used (bad style)
custom key generation from a pass phrase
Changing any point, changes everything: bytes generated and decryption code.
When encrypting data in java as following:
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(rawKeyData);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key, sr);
// why the sr is necessary to init a Cipher object?
byte data[] = str.getBytes();
byte[] encryptedData = cipher.doFinal(data);
Why the a SecureRandom object sr is necessary to init a Cipher object? As for the decryption side there is also need an SecureRandom object which is not the same as the one generated in the encryption size. Is theseSecureRandom objects just for parity digit?
The SecureRandom object is optional. If you don't select one, Java will use a default source of randomness. See the documentation of this method to understand how one is selected.
The Cipher Javadocs explains the purpose of this argument:
If this cipher (including its underlying feedback or padding scheme) requires any random bytes (e.g., for parameter generation), it will get them from random.
So, in your particular case, you are probably not making use of this item at all. Nothing in your DES usage will require random data (since you appear to be using ECB mode). If you were using CBC-mode, then I assume the IV would be randomly generated from the SecureRandom object.
I would like to know how i could decipher a random number DES/CBC-enciphered with a specific Key.
My protocol states the following:
I am sending a KeyNo (eg. 0x00)
After the KeyNo is sent i get a 8byte (DES) random number. This random number is enciphered with the selected key.
My question would be how do i decipher the data i receive, to find the random number using Cipher
Thank you.
To decrypt a DES encrypted stream, simply do :
Key key = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(bytesOfThe Key)); // bytesOfTheKey should be 8 bytes long
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
return new CipherInputStream(inputStream, cipher);
You may also be interested in the doFinal method which works on byteBuffers.
AES key may be generate by this code
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
but
If I have a "very reliable" method of generating random numbers can I use it in such a way
SecureRandom rnd = new SecureRandom();
byte[] key = new byte[16];
rnd.nextBytes(key);
is key obtained by this method reliable ?
or it ONLY must generated by some SPECIAL algorithm
The AES key can be any 128 bits. It should be be practically unguessable, whatever the method of creating it.
For Example:
SecureRandom sr = new SecureRandom()
key = new byte[16];
iv = new byte[16];
sr.nextBytes(key);
sr.nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key,"AES"), new IvParameterSpec(IV));
SecretKeySpec, by the way, is just a thin wrapper around a byte[] --- it does not transform the key in any way. No "special algorithm".
To add to the other answers ... I believe that the reason that the basic Random functions aren't secure are two reasons:
Slight statistical biases that are acceptable for non-security related situations, but narrow the distributions unacceptably for security applications.
They are seeded by the system DATETIME. Even knowing WHEN you generated your key - to a poor accuracy of +/- 6 months - would significantly reduce the brute force search space.
You can add a random algorithm using SecureRandom :
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecureRandom random = new SecureRandom(); // cryptograph. secure random
keyGen.init(random);
SecretKey secretKey = keyGen.generateKey();
It sounds like you're trying to generate an AES key based on a password.
If this is the case, you can use javax.crypto.SecretKeyFactory's generateSecret method, passing in a javax.crypto.spec.PBEKeySpec as the parameter. The PBEKeySpec allows to to specify the password as an argument to its constructor.