Reputation: 53
I want to ask you some question about security on key in java. My code using RSA and AES for encrypt and decrypt a plainText. And I want to use my own password as a private key(AES) for verifies key(RSA). Because RSA are generate public and private key random. (In real case: private key is input by user and public key store in database for verification.)
This code is work find, but I want to know this code is correct or not? Please advice! Thank you.
My process:
1. generate a symmetric key
2. Encrypt the data with the symmetric key
3. Encrypt the symmetric key with rsa
4. send the encrypted key and the data
5. Decrypt the encrypted symmetric key with rsa
6. decrypt the data with the symmetric key
7. done
import java.io.UnsupportedEncodingException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AES_RSA {
private static byte[] key;
private static SecretKeySpec secretKey;
public static void main(String[] args){
try {
//1. Generate Symmetric Key (AES with 128 bits)
String password = "123456";
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128); // The AES key size in number of bits
setKey(password);
//2. Encrypt plain text using AES
String plainText = "Please encrypt me urgently...";
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] byteCipherText = aesCipher.doFinal(plainText.getBytes());
//3. Encrypt the key using RSA public key
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair keyPair = kpg.generateKeyPair();
PublicKey puKey = keyPair.getPublic();
PrivateKey prKey = keyPair.getPrivate();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.PUBLIC_KEY, puKey);
byte[] encryptedKey = cipher.doFinal(secretKey.getEncoded()/*Seceret Key From Step 1*/);
//4. Send encrypted data (byteCipherText) + encrypted AES Key (encryptedKey)
//5. On the client side, decrypt symmetric key using RSA private key
cipher.init(Cipher.PRIVATE_KEY, prKey);
byte[] decryptedKey = cipher.doFinal(encryptedKey);
//6. Decrypt the cipher using decrypted symmetric key
SecretKey originalKey = new SecretKeySpec(decryptedKey , 0, decryptedKey.length, "AES");
Cipher aesCipher1 = Cipher.getInstance("AES/ECB/PKCS5PADDING");
aesCipher1.init(Cipher.DECRYPT_MODE, originalKey);
byte[] bytePlainText = aesCipher1.doFinal(byteCipherText);
String plainText1 = new String(bytePlainText);
//7. Done! 'Please encrypt me urgently...'
System.out.println(plainText1);
}catch (Exception e) {}
}
public static void setKey(String myKey)
{
MessageDigest sha = null;
try {
key = myKey.getBytes("UTF-8");
sha = MessageDigest.getInstance("SHA-256");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
secretKey = new SecretKeySpec(key, "AES");
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
Upvotes: 1
Views: 4125
Reputation: 9173
You pseudo-steps are correct, but your description not. For example, you normally keep RSA
private key and distribute RSA
public key.
But a few suggestions for creating better code.
I suggest to use PKCS5
for creating password-based secret keys rather than a simple hash. Java's PBEKeySpec
is a class for generating such secret keys. Here is a small sample code which you can use for your setKey()
routine (adjust it as you prefer):
SecretKeyFactory skf = SecretKeyFactory.getInstance("AES");
SecretKey key = skf.generateSecret(new PBEKeySpec(password.getBytes("UTF-8"), salt, 10000));
Never use ECB
mode of operation for encrypting data. In worse case, use CBC
with randomized IV
.
RSA
private key is kept private on server, but RSA
public key is distributed freely between clients(normally). You are doing this in the other way.RSA/ECB/OAEPWithSHA-256AndMGF1Padding
rather than RSA/ECB/PKCS1Padding
for RSA
padding. But I think it is not necessary.HMAC
for authenticating your encrypted data too. But you don't have any authenticating mechanism right now. Update: Based on design of your mechanism, you cannot securely add an authentication method for detecting active attacks(such as man-in-the-middle). Check comments from Maarten too.
These are the problems that I found. The most important one is just using RSA
key-pair in an incorrect way.
Upvotes: 1