Reputation: 341
I'm working on a client-server secure protocol where I need to use RSA in Java to encrypt a SecretKey for HMAC digests because the key has to be sent to the server. The encryption has two stages; first, I need to encrypt the symmetric key with a public asymmetric key, then, that encrypted message is encrypted with a private asymmetric key.
For this purpose I generate the SecretKey as:
public SecretKey generate(){
KeyGenerator generator = KeyGenerator.getInstance("HMACSHA256");
k = generator.generateKey();
return k;
}
Later, I use this code to encrypt any byte array with a public key:
public byte[] encryptPublic(PublicKey key, byte[] array){
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(array);
return encrypted;
}
The code for encryption with a private key is the same but using a private key.
For the RSA encryption I'm using 1024 bit long asymmetric keys so I have two main questions:
Upvotes: 2
Views: 6790
Reputation: 93968
That's called wrapping:
public static byte[] wrapKey(PublicKey pubKey, SecretKey symKey)
throws InvalidKeyException, IllegalBlockSizeException {
try {
final Cipher cipher = Cipher
.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.WRAP_MODE, pubKey);
final byte[] wrapped = cipher.wrap(symKey);
return wrapped;
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new IllegalStateException(
"Java runtime does not support RSA/ECB/OAEPWithSHA1AndMGF1Padding",
e);
}
}
Note that this explicitly doesn't convert to byte[]
first. That's because the key might well be within e.g. a hardware security module. In a HSM the wrapping may be possible, but the conversion to byte[]
in local memory would usually not be possible.
You shouldn't do this and you cannot do this either. The reason that you shouldn't do it because encryption with the private key does not provide confidentiality, as anybody would have access to the public key.
Padding is required to perform secure RSA encryption. The padding overhead (of 11 bytes for PKCS#1 v1.5 style padding) is there prohibiting you to encrypt with the private key.
Note that the entire operation: encryption with a private key isn't even specified in PKCS#1 - it's not a legit operation.
Usually the much more secure ephemeral-ephemeral (EC)DH is used to establish keys in transport protocols, using the private key(s) only for authentication. You may want to take a hint from the (draft versions of) TLS 1.3. Or you may just want to use TLS or the handshake portion of it.
Upvotes: 3