blowfish encryption with iaik pkcs7 EnvelopedData - java

I am migrating my module from bouncy castle to iaik pkcs7. I need to use blowfish,twofish and idea encryption algorithms in conjunction with iaik.pkcs.pkcs7.EnvelopedDataStream of IAIK library. Idea encryption algorithm Id is present in AlgorithmID class of IAIK but cant be implemented directly(probably because of variable key length). Blowfish is present as separate cipher class but I could not figure out a way to use it along with enveloped data(which is important because I will be using public key encryption method). I can actually encrypt using blowfish,then wrap using enveloped data and some algorithm such as aes and send this but the receiver won't have the algorithm info in that case. Secret key can be passed along with recepientInfo.
If anyone can possible show me the way een basic I may be able to proceed.
Thanks in advance
Atraya

Hi I came up with the solution
ByteArrayInputStream is = new ByteArrayInputStream(message);
AlgorithmID blowfish=new AlgorithmID("1.3.6.1.4.1.3029.1.2","BLOWFISH_CBC","Blowfish/CBC/PKCS5Padding");
byte[] iv = new byte[8];
random.nextBytes(iv);
try{
KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish", "IAIK");
secretKey = keyGen.generateKey();
AlgorithmParameterSpec params = new IvParameterSpec(iv);
keyGen.init(128);
secretKey = keyGen.generateKey();
iaik.pkcs.pkcs7.EncryptedContentInfoStream eci = new iaik.pkcs.pkcs7.EncryptedContentInfoStream(ObjectID.pkcs7_data, is);
eci.setupCipher(blowfish, secretKey, params);
return eci;
}catch(Exception e){
}
Tell me if this way is wrong or can be improved or there is another way of doing this.
thanks

Related

AES GCM key derivation swift

I'm trying to implement in swift the equivalent of my code in java. Basically is an AES implementation with GCM padding and I'm using a key derivation for that. In swift I'm using the CryptoSwift library.
My issue is that I cannot get the same encrypted text in swift.
After a very long research I couldn't find any solutions for my problem, I even saw the test code of the CryptoSwift library repository to get any ideas but with no luck
This is my java code:
GCMParameterSpec ivParameterSpec = new GCMParameterSpec(128, "ivVector".getBytes());
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec("myPassword".toCharArray(), "salt".getBytes(), 1000, 256);
SecretKey tmp = secretKeyFactory.generateSecret(keySpec);
key = new SecretKeySpec(tmp.getEncoded(), "AES");
encryptCipher = Cipher.getInstance("AES/GCM/NoPadding");
encryptCipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
byte[] encryptedWord = Base64.encode(encryptCipher.doFinal("example".getBytes("UTF-8")));
And this is my swift code:
do{
keyDerivation = try PKCS5.PBKDF2(password: "myPassword".bytes, salt: "salt".bytes, iterations: 1000, keyLength: 32, variant: .sha1).calculate()
let gcm = GCM(iv: keyDerivation, mode: .combined)
let aes = try AES(key: keyDerivation, blockMode: gcm, padding: .noPadding)
let encryptedText = try aes.encrypt("example".bytes)
}catch{
print(error)
}
Any help would be appreciated.
Your IV doesn't match in both cases. In Java you use a string, and in Swift you use the derived key in keyDerivation.
Furthermore, you should make sure that you use the same character encoding. I'd not use getBytes or similar for either language. Explicitly specifying UTF-8 is probably best.
Note that the Java PBKDF2WithHmacSHA1 may handle password encoding in a rather peculiar way, so some kind of input validation on the password is probably in order.
Needless to say, the salt should be random for each call to encrypt, not static. I presume this is just test code though.

Translating Ruby encryption code to Java

I have a legacy code in ruby that does the encryption using OpenSSL
However, I would like to translate this in Java and I am lost.
so far my biggest blocker is figuring out how to generate the IV based on this code.
Any help would be greatly appreciated
def func_enc(data, key)
cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
cipher.encrypt
cipher.pkcs5_keyivgen(key)
cipher.update(data)
encrypted_data << cipher.final
return encryptedData
end
EDIT
Just to clarify, I would like to use Java Crypto for this. This is the code I came up with so far:
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithMD5And256AES-CBC");
KeySpec spec = new PBEKeySpec("Password".toCharArray(), null, 2048, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
but "PBKDF2WithMD5And256AES-CBC" does not have any provider and I get NoSuchAlgorithm exception.
java.security.NoSuchAlgorithmException: PBKDF2WithMD5And256AES-CBC SecretKeyFactory not available
Also the salt that pkcs5_keyivgen uses by default is null!! I am not sure if Java lets me use a null salt.
How can I generate the correct IV ?
The warning on this documentation page suggests that the deprecated pkcs5_keyivgen method does something non-standard when used together with AES. First of all, it uses PBKDF1, not PBKDF2.
It might be difficult to replicate what it does, and implementing cryptographic algorithms is generally inadvisable unless you know exactly what you're doing – even experts often get it wrong.

Should I use Cipher.WRAP_MODE OR Cipher.ENCRYPT_MODE to encrypt a session key?

How should I encrypt a session key on the client side with the public key transported from server side?
Should I use Cipher.WRAP_MODE or Cipher.ENCRYPT_MODE?
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.WRAP_MODE, publicKey);
byte[] wrappedSessionKey = cipher.wrap(sessionKey);
I am not really sure how to use encrypt_mode to encrypt sessionKey. Could someone help me on this?
Wrapping and encrypting are very similar, however wrapping expresses more precisely what you are planning to do. General "encryption" operates on raw data with no semantic meaning, whereas wrapping is known to relate to keys. Hence the Cipher.unwrap() method returns a Key not a byte array.
Your code will be more portable (particular with respect to hardware security modules) if you use wrap for doing key wrapping. In some circumstances, key permissions will allow a wrapping operation but not a raw encryption of the key bytes.
Of course, since the entirety of the JCE architecture is based on a provider concept, you will need to check exactly what algorithm to specify for your chosen provider to get the output format you want. This is particularly important if you are sending the wrapped key data to a third-party.
In your particular case, the same behaviour will be exhibited by both WRAP and ENCRYPT, as demonstrated below, where I interchange the results:
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "SunJSSE");
generator.initialize(2048);
KeyPair keyPair = generator.generateKeyPair();
SecretKey sessionKey = new SecretKeySpec(new byte[16], "AES");
Cipher c = Cipher.getInstance("RSA", "SunJCE");
c.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
byte[] result1 = c.doFinal(sessionKey.getEncoded());
c.init(Cipher.WRAP_MODE, keyPair.getPublic());
byte[] result2 = c.wrap(sessionKey);
c.init(Cipher.UNWRAP_MODE, keyPair.getPrivate());
SecretKey sessionKey1 = (SecretKey) c.unwrap(result1, "AES",
Cipher.SECRET_KEY);
c.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
SecretKey sessionKey2 = new SecretKeySpec(c.doFinal(result2), "AES");
System.out.println(Arrays.equals(sessionKey1.getEncoded(),
sessionKey2.getEncoded()));
This prints: true

Secure key for android database

Is there any algorithm to generate an encrypted key in android to secure a database?
I tried this PBE algorithm:
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt,
NUM_OF_ITERATIONS, KEY_SIZE);
SecretKeyFactory factoryKey = SecretKeyFactory.getInstance(PBE_ALGORITHM);
SecretKey tempKey = factoryKey.generateSecret(pbeKeySpec);
SecretKey secretKey = new SecretKeySpec(tempKey.getEncoded(), "AES");
But it generates the same key every time. Any other good algorithms for generating a secure key?
To generate a random secret key, use the KeyGenerator class, with code something like this:
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(KEY_SIZE);
SecretKey skey = kgen.generateKey();
Note that you will obviously have to store this key securely somewhere if you wish to decrypt your database later, hence it may be worthwhile to pursue the PBE-based solution proposed in your question.
Typically to achieve what you want you use your PBE key to encrypt/decrypt a random key (that you must store, keep it separate from your data as best you can) which you use to encrypt/decrypt your data. Then your data ciphertext, by itself, has no direct relation to your password without the encrypted keys.

How to use a key generated by KeyGenerator at a later time?

I'm writing a program which does both encryption and decryption in DES. The same key used during the encryption process should be used while decrypting too right? My problem is encryption and decryption are run on different machines. This is how the key is generated during the encryption process.
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
So ,I thought I'll write the key to a file. But looks like I can typecast a SecretKey object to a String but not vice-versa! So, how do I extract the key contained in a text file? And pass as an input to this statement?
decipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
Or else is it possible to take the key as an input from the user during both the encryption and decryption process?
Do this:
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
byte[] encoded = key.getEncoded();
// save this somewhere
Then later:
byte[] encoded = // load it again
SecretKey key = new SecretKeySpec(encoded, "DES");
But please remember that DES is unsecure today (it can be relatively easily bruteforced). Strongly consider using AES instead (just replace "DES" with "AES).

Categories