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.
Related
I have a java application that encrypts and decrypts strings. It generates one key for encryption and one for decryption.
Key Generation:
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
char[] passwordChars = password.toCharArray();
KeySpec spec = new PBEKeySpec(passwordChars, salt.getBytes(), iterations, 256);
SecretKey key = keyFactory.generateSecret(spec);
byte[] passwordHash = key.getEncoded();
SecretKey secretKey = new SecretKeySpec(key.getEncoded(), "AES");
My goal is to have the password stay the same for both the encryption and decryption key. But have a different salt for each of them. Is this possible or do I need to have the same salt for both keys?
Whenever I try to change the salt for the decryption key, I get this error:
javax.crypto.AEADBadTagException: Tag mismatch!
at java.base/com.sun.crypto.provider.GaloisCounterMode.decryptFinal(GaloisCounterMode.java:623)
at java.base/com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1118)
at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1055)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:855)
at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2207)
https://crackstation.net/hashing-security.htm - the salt should be different for each piece of encrypted information. I believe its often derivable from the user's other details... so dob + last name (for example) are used as the salt for encrypting passwords so that each password is encrypted to a different value, even when two users share the same password.
Edit: the salt should be the same for the encryption and decryption key, but unique for the individual passwords being encrypted/decrypted. Please read the information at the URL for a better understanding
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
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
I'm making a project about security in Java. The Server receives a password and with this password is supposed to insert in MAC to verify the consistency of one specific file.
Mac m;
SecretKey sk;
sk = KeyGenerator.getInstance( "AES" ).keygenerator();/* what i don't want to use */
byte[]mac=null;
Mac m = Mac.getInstance("HmacSHA1");
m.init( password ); /* it's wrong */
m.update("work of security".getBytes());
mac = m.doFinal();
What I can understand is how to define a SecretKey to MAC init...
The two typical methods use to derive an AES key from a password are:
Using the raw bytes of the password. This option is not very strong (subject to trivial dictionary attacks) and relies on the password being exactly 128/192/256 bits.
Deriving the key using a function, such as PBKDF2.
You need to find out how the key is derived. The two options in code are:
Raw Bytes
SecretKey aesKey = new SecretKeySpec(password.getBytes(someCharset), "AES");
Derivation Function
Example PBKDF2:
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey aesKey = factory.generateSecret(new PBEKeySpec(password, salt,
iterations, 256));
The salt value is a random byte array (i.e. perhaps eight bytes). The iterations can be increased to improve security at the expense of performance.
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).