I am new to AES encryption. I have created an Initialization Vector using the secure random required for AES encryption.
SecureRandom random = new SecureRandom();
byte[] iv = new byte[16];
random.nextBytes(iv);
I want to display the iv on the UI so that if a user wants they can change it. How to achieve this ?
Related
My application is acting as a switchboard to transfer very sensitive messages between two parties and I'm trying to figure out how I can do this without "looking" at the message they're trying to send.
I have a HSM, and I've generated a keypair for the sender - they're going to encrypt the message with their public key that I gave them, and I can decrypt the message using the private key I have in the HSM.
I'm going to then pass that message on by encrypting it with the public key of the ultimate receiver, which I have.
Is there any way to chain these two operations inside the HSM, without having the decrypted message anywhere near my application memory? I would like the plaintext content to never leave the boundaries of the HSM.
I know that some HSMs have a CodeSafe / SEE machine feature that lets me write embedded system code and run it inside the HSM, before I get into that I'd like to see if there's a way using the general PKCS / JCE / CNG APIs to do this safely.
If all you need is to re-encrypt the same secret under a different key, you can use C_Unwrap to create a temporal HSM object with value of the translated secret and then use C_Wrap to encrypt the value of this temporal HSM object for all the recipients.
This way the secret will never leave HSM.
Something like this (verified to be working on SafeNet Luna 7 with RSA-OAEP):
// Your private key for 'decrypting' secret. Must have key unwrapping allowed
CK_OBJECT_HANDLE hsmPrivateKey = ... ;
// Encrypted secret
byte[] wrappedKey = ... ; //
// Template for temporal generic secret key with value of the secret
CK_ATTRIBUTE[] tempTemplate = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA.CLASS, CKO.SECRET_KEY),
new CK_ATTRIBUTE(CKA.KEY_TYPE, CKK.GENERIC_SECRET),
new CK_ATTRIBUTE(CKA.TOKEN, false),
new CK_ATTRIBUTE(CKA.PRIVATE, true),
new CK_ATTRIBUTE(CKA.EXTRACTABLE, true),
new CK_ATTRIBUTE(CKA.SENSITIVE, true),
new CK_ATTRIBUTE(CKA.ENCRYPT, false),
new CK_ATTRIBUTE(CKA.DECRYPT, false),
new CK_ATTRIBUTE(CKA.WRAP, false),
new CK_ATTRIBUTE(CKA.UNWRAP, false),
new CK_ATTRIBUTE(CKA.SIGN, false),
new CK_ATTRIBUTE(CKA.VERIFY, false),
new CK_ATTRIBUTE(CKA.DERIVE, false)
};
// Unwrapping/decryption mechanism
CK_MECHANISM mechanism = ... ;
// Handle for temporal generic secret key with value of the secret
CK_OBJECT_HANDLE temporalValueHandle = new CK_OBJECT_HANDLE();
// Unwrap/decrypt the secret into temporal key
CryptokiEx.C_UnwrapKey(session, mechanism, hsmPrivateKey, wrappedKey, wrappedKey.length, tempTemplate, tempTemplate.length, temporalValueHandle);
// Wrap/encrypt the secret for recipients. Recipient public keys must have key wrapping allowed
for(CK_OBJECT_HANDLE recipientPublicKey : ... ) {
LongRef resSize = new LongRef(0);
CryptokiEx.C_WrapKey(session, mechanism, recipientPublicKey, temporalValueHandle, null, resSize);
byte[] rewrappedKey = new byte[CryptokiUtils.safeIntCast(resSize.value)];
CryptokiEx.C_WrapKey(session, mechanism, recipientPublicKey, temporalValueHandle, rewrappedKey, resSize);
System.out.println("Re-wrapped key: " + bytesToHexString(rewrappedKey));
}
// Delete temporal generic secret key
CryptokiEx.C_DestroyObject(session, temporalValueHandle);
Good luck!
I am trying to learn and implement JWE in java for a problem statement. I am trying to understand how does the Content Encryption Key is generated using a certain algorithm(let's say RSA-PKCS1_1.5).
I have knowledge on how to generate a pair of the key using the key generator, then using the public key for encryption and private key for decryption. Also, I am aware of how to create a simple JWT token by giving claims and also how to sign them.
I am trying to follow the steps:
The message encryption process is as follows:
Generate a random Content Encryption Key (CEK). The CEK MUST have a length at least equal to that of the required encryption keys and MUST be generated randomly.
Encrypt the CEK for the recipient
Generate a random IV (if required for the algorithm).
Compress the Plaintext if a zip parameter was included.
Serialize the (compressed) Plaintext into a bitstring M.
Encrypt M using the CEK and IV to form the bitstring C.
Set the Encoded JWE Ciphertext equal to the base64url encoded representation of C.
Create a JWE Header containing the encryption parameters used.
Base64url encode the bytes of the UTF-8 representation of the JWE Header to create the Encoded JWE Header.
The three encoded parts, taken together, are the result of the encryption.
public static void main(String[] args)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
//ASYMMETRIC ENCRYPTION
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keys = keyPairGenerator.generateKeyPair();
byte[] publicKey = keys.getPublic().getEncoded();
byte[] privateKey = keys.getPrivate().getEncoded();
System.out.println("PUBLIC KEY ::: " + Base64.encodeBase64String(publicKey));
System.out.println("PRIVATE KEY ::: " + Base64.encodeBase64String(privateKey));
Cipher cipher = Cipher.getInstance("RSA");
//PUBLIC KEY IS GETTING USED IN ENCRYPTING PLAIN TEXT
cipher.init(Cipher.ENCRYPT_MODE, keys.getPublic());
byte[] encryptedBytes = cipher.doFinal("Test String".getBytes());
//PRIVATE KEY IS GETTING USED IN DECRYPTING CIPHER TEXT
cipher.init(Cipher.DECRYPT_MODE, keys.getPrivate());
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
System.out.println("encrypted data ::: " + BaseEncoding.base64().encode(encryptedBytes));
System.out.println("decrypted text ::: " + new String(decryptedBytes));
}
Key Management Mode
The key management mode is used to determine the CEK. Each algorithm uses one of these modes.
Hereafter the list of available modes and algorithm associations:
Key Encryption: RSA1_5, RSA-OAEP, RSA-OAEP-256, RSA-OAEP-384, RSA-OAEP-512
Key Wrapping: A128KW, A192KW, A256KW, PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW, A128GCMKW, A192GCMKW, A256GCMKW
Direct Key Agreement: ECDH-ES
Key Agreement with Key Wrapping: ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW
Direct Encryption: dir
How to determine the CEK?
With Key Encryption, Key Wrapping and Key Agreement with Key Wrapping, the CEK is a random byte string. Its size depends on the Content Encryption Algorithm.
With Direct Key Agreement, the CEK is the agreed upon key computed using the sender and receiver keys.
With Direct Encryption, the CEK is the shared symmetric key.
I am developing a website by using ASP.NET. I want to implement login authentication for my users. I am using SALT HASH method to securely save users' passwords to the DB. By looking at various codes I wrote a code like below to generate the SALT and the Hashed passwords to store in Database.
private string hashedPassword;
private string Salt;
private string SaltPlusPassword;
private const byte saltSize = 24;
byte[] saltArray;
byte[] hashedPasswordArray;
byte[] bytes;
public void Save_Login(string passWord)
{
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
saltArray = new byte[saltSize];
rng.GetBytes(saltArray);
}
Salt = Convert.ToBase64String(saltArray);
SaltPlusPassword = String.Format("{0}{1}", Salt, passWord);
using (SHA256 sha = SHA256.Create())
{
bytes = Encoding.UTF8.GetBytes(SaltPlusPassword);
hashedPasswordArray = sha.ComputeHash(bytes);
}
hashedPassword = Convert.ToBase64String(hashedPasswordArray);
}
//Salt will be save to DB
//hashedPassword will be save to DB.
So I have few questions.
1) I read in an article that saying "make your salt is at least as long as the hash function's output" ok. What are the sizes for saltArray, hashedPasswordArray and bytes arrays which are declared in my code? I used saltArray size as 24. Is it ok?
2) What will happen if I use ?
bytes = Encoding.Unicode.GetBytes(SaltPlusPassword);
instead of
bytes = Encoding.UTF8.GetBytes(SaltPlusPassword);
3) What is the datatype should I use to store salt and the hashed password in the DB? ( My db is MYSQL )
4) Is there any performance difference if I use SHA256Managed instead of SHA256? Which is best?
5) Finally am I doing this in the right way? What are the weaknesses in above code? What are your suggestions?
Rather than deal with all these issues, why not use the built in identity management tools provided by ASP.NET. See here
http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity
Much more common and robust.
I have to send a username and password from my iphone app to a ASP server page, and I will encrypt them using: http://iphonedevelopment.blogspot.com/2009/02/strong-encryption-for-cocoa-cocoa-touch.html. What is the best way to decrypt these strings on the ASP page? I found some examples, but since the encryption will happen on two completely unrelated sides, I think I need to hard code the key in on both sides, and I can't find any examples that don't have use generated keys.
Thanks!
Yes, key management is a big problem. You will have to have the keys on both sides, on iOS you can save the key in the Keychain, that is secure but the process to get it there securely is more difficult.
The other main issue is getting all the parameters the same on both sides. Of particular interest are
encryption key value and size
mode: CBC, ECB, etc. (you should probably be using CBC)
initialization vector (iv) is needed for most modes
padding method: PKCS7, etc. (AES is a block cypher and needs input
in a multiple of block size)
Why not store the passwords in the database with SHA1, then use HMAC with a client specified key for the communication?
Have the server generate a random key and send it with the login request. The client computes the SHA1 hash of the password, then computes the HMAC SHA1 hash of that using the server-specified key. The server then verifies that the result is correct.
On the client end:
// password is the plaintext password
// keyb64 is a random key specified by the server, encoded in base64.
string ComputeSecureHash(string password, string keyb64)
{
byte[] data = Encoding.UTF8.GetBytes(password);
byte[] key = Convert.FromBase64String(keyb64);
byte[] hash;
byte[] machash;
// compute a plain SHA1 hash of the specified data
using (SHA1Managed sha1 = new SHA1Managed())
{
hash = sha1.ComputeHash(data);
}
// now compute a HMAC hash of that hash, using the random key.
using (HMACSHA1 sha1mac = new HMACSHA1(key))
{
machash = sha1mac.ComputeHash(hash);
}
return Convert.ToBase64String(machash);
}
On the server end:
// hash is the string produced by the function above
// realHash is the SHA1 hash of the real password, which you've fetched from the db
// key is the key you generated for this login session
bool VerifyHash(string hash, byte[] realHash, byte[] key)
{
byte[] machash;
using (HMACSHA1 sha1mac = new HMACSHA1(key))
{
machash = sha1mac.ComputeHash(realHash);
}
return (Convert.ToBase64String(machash) == hash);
}
This allows you to authenticate over a plaintext medium without having the password cracked.
I've created an encryption key by the following code:
SecretKeyFactory skFactory = SecretKeyFactory.getInstance("PBEWithSHA1AndDESede");
SecretKey key = skFactory.generateSecret(new PBEKeySpec("<some password>".toCharArray()));
Then I've used the key to encrypt some text.
I've stored this key inside a java key store and saved in on FS:
KeyStore ks = KeyStore.getInstance("JCEKS");
ks.setKeyEntry(keyAlias, key ,keyPassword.toCharArray(), null);
FileOutputStream fileOutputStream = new FileOutputStream (keyStorePath);
keyStore.store(fileOutputStream , keyStorePassword.toCharArray());
fileOutputStream.close();
In a different process I open the key store and try to decrypt some text:
KeyStore ks2 = KeyStore.getInstance("JCEKS");
ks2.load(new java.io.FileInputStream(keyStorePath), ksPassword.toCharArray());
SecretKeyFactory skFactory2 = SecretKeyFactory.getInstance("PBEWithSHA1AndDESede");
String passForTheKey = ks2.getKey(keyAlias, keyPass.toCharArray()).toString();
KeySpec key = new PBEKeySpec(passForTheKey.toCharArray());
SecretKey sKey2 = skFactory.generateSecret(key);
When trying to decrypt the text I get the error:
java.security.InvalidKeyException: Given final block not properly padded
If I try to use the key without storing it in the key store immediately after creating it, the decription proccess is working great.
Any ideas?
You're storing the actual secret key in your keystore (which is normal). However, you seem to be trying to read it as a password, for a new key you're generating later.
Instead of this:
String passForTheKey = ks2.getKey(keyAlias, keyPass.toCharArray()).toString();
KeySpec key = new PBEKeySpec(passForTheKey.toCharArray());
SecretKey sKey2 = skFactory.generateSecret(key);
use this:
SecretKey sKey2 = (SecretKey) ks2.getKey(keyAlias, keyPassword.toCharArray());
What you're reading from the keystore is the key itself (as you've stored it), not some password. (generateSecret will just generate a new key.)