Use RSA/ECB/PKCS1Padding for asym cipher, use WRAP_MODE/UNWRAP_MODE instead ENCRYPT_MODE/DECRYPT_MODE

This commit is contained in:
Manfred Karrer 2016-03-30 02:40:40 +02:00
parent 4d1a07c531
commit 9ac0740e33

View file

@ -26,23 +26,20 @@ import javax.crypto.Cipher;
import javax.crypto.KeyGenerator; import javax.crypto.KeyGenerator;
import javax.crypto.Mac; import javax.crypto.Mac;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.security.*; import java.security.*;
import java.util.Arrays; import java.util.Arrays;
// TODO: which counter modes and paddings should we use?
// TODO is Hmac needed/make sense? // TODO is Hmac needed/make sense?
// https://security.stackexchange.com/questions/52665/which-is-the-best-cipher-mode-and-padding-mode-for-aes-encryption
public class Encryption { public class Encryption {
private static final Logger log = LoggerFactory.getLogger(Encryption.class); private static final Logger log = LoggerFactory.getLogger(Encryption.class);
public static final String ASYM_KEY_ALGO = "RSA"; // RSA/NONE/OAEPWithSHA256AndMGF1Padding public static final String ASYM_KEY_ALGO = "RSA";
private static final String ASYM_CIPHER = "RSA"; private static final String ASYM_CIPHER = "RSA/ECB/PKCS1Padding";
private static final String SYM_KEY_ALGO = "AES"; // AES/CTR/NoPadding private static final String SYM_KEY_ALGO = "AES";
private static final String SYM_CIPHER = "AES"; private static final String SYM_CIPHER = "AES";
private static final String HMAC = "HmacSHA256"; private static final String HMAC = "HmacSHA256";
@ -173,22 +170,22 @@ public class Encryption {
// Asymmetric // Asymmetric
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private static byte[] encrypt(byte[] payload, PublicKey publicKey) throws CryptoException { private static byte[] encryptSecretKey(SecretKey secretKey, PublicKey publicKey) throws CryptoException {
try { try {
Cipher cipher = Cipher.getInstance(ASYM_CIPHER, "BC"); Cipher cipher = Cipher.getInstance(ASYM_CIPHER, "BC");
cipher.init(Cipher.ENCRYPT_MODE, publicKey); cipher.init(Cipher.WRAP_MODE, publicKey);
return cipher.doFinal(payload); return cipher.wrap(secretKey);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
throw new CryptoException("Couldn't encrypt payload"); throw new CryptoException("Couldn't encrypt payload");
} }
} }
private static byte[] decrypt(byte[] encryptedPayload, PrivateKey privateKey) throws CryptoException { private static SecretKey decryptSecretKey(byte[] encryptedSecretKey, PrivateKey privateKey) throws CryptoException {
try { try {
Cipher cipher = Cipher.getInstance(ASYM_CIPHER, "BC"); Cipher cipher = Cipher.getInstance(ASYM_CIPHER, "BC");
cipher.init(Cipher.DECRYPT_MODE, privateKey); cipher.init(Cipher.UNWRAP_MODE, privateKey);
return cipher.doFinal(encryptedPayload); return (SecretKey) cipher.unwrap(encryptedSecretKey, "AES", Cipher.SECRET_KEY);
} catch (Throwable e) { } catch (Throwable e) {
// errors when trying to decrypt foreign messages are normal // errors when trying to decrypt foreign messages are normal
throw new CryptoException(e); throw new CryptoException(e);
@ -214,7 +211,7 @@ public class Encryption {
SecretKey secretKey = generateSecretKey(); SecretKey secretKey = generateSecretKey();
// Encrypt secretKey with receivers publicKey // Encrypt secretKey with receivers publicKey
byte[] encryptedSecretKey = encrypt(secretKey.getEncoded(), encryptionPublicKey); byte[] encryptedSecretKey = encryptSecretKey(secretKey, encryptionPublicKey);
// Encrypt with sym key payload with appended hmac // Encrypt with sym key payload with appended hmac
byte[] encryptedPayloadWithHmac = encryptPayloadWithHmac(payload, secretKey); byte[] encryptedPayloadWithHmac = encryptPayloadWithHmac(payload, secretKey);
@ -234,7 +231,7 @@ public class Encryption {
* @throws CryptoException * @throws CryptoException
*/ */
public static DecryptedDataTuple decryptHybridWithSignature(SealedAndSigned sealedAndSigned, PrivateKey privateKey) throws CryptoException { public static DecryptedDataTuple decryptHybridWithSignature(SealedAndSigned sealedAndSigned, PrivateKey privateKey) throws CryptoException {
SecretKey secretKey = getSecretKeyFromBytes(decrypt(sealedAndSigned.encryptedSecretKey, privateKey)); SecretKey secretKey = decryptSecretKey(sealedAndSigned.encryptedSecretKey, privateKey);
boolean isValid = Sig.verify(sealedAndSigned.sigPublicKey, boolean isValid = Sig.verify(sealedAndSigned.sigPublicKey,
Hash.getHash(sealedAndSigned.encryptedPayloadWithHmac), Hash.getHash(sealedAndSigned.encryptedPayloadWithHmac),
sealedAndSigned.signature); sealedAndSigned.signature);
@ -250,13 +247,9 @@ public class Encryption {
// Private // Private
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private static SecretKey getSecretKeyFromBytes(byte[] encodedKey) {
return new SecretKeySpec(encodedKey, SYM_KEY_ALGO);
}
private static SecretKey generateSecretKey() { private static SecretKey generateSecretKey() {
try { try {
KeyGenerator keyPairGenerator = KeyGenerator.getInstance(SYM_CIPHER, "BC"); KeyGenerator keyPairGenerator = KeyGenerator.getInstance(SYM_KEY_ALGO, "BC");
keyPairGenerator.init(256); keyPairGenerator.init(256);
return keyPairGenerator.generateKey(); return keyPairGenerator.generateKey();
} catch (Throwable e) { } catch (Throwable e) {