Skip to content

Instantly share code, notes, and snippets.

@marcelmaatkamp
Last active September 13, 2022 21:06
Show Gist options
  • Select an option

  • Save marcelmaatkamp/15bb8949ff145aa9f376 to your computer and use it in GitHub Desktop.

Select an option

Save marcelmaatkamp/15bb8949ff145aa9f376 to your computer and use it in GitHub Desktop.
AES(256) wrapped in RSA(2048) example
import java.io.Serializable;
/**
* Created by marcelmaatkamp (m.maatkamp@gmail.com)
*/
public class Data implements Serializable {
public String msg;
public Data(String s) {
this.msg = s;
}
}
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.bouncycastle.util.encoders.Base64;
import java.io.Serializable;
import java.lang.reflect.Field;
/**
* Created by marcelmaatkamp (m.maatkamp@gmail.com)
*/
public class EncryptedData implements Serializable {
public byte[] signature;
public byte[] encryptedKey;
public byte[] encryptedData;
public byte[] iv;
public String toString() {
return (new ReflectionToStringBuilder(this) {
protected Object getValue(Field f) throws IllegalAccessException {
if ("signature".equals(f.getName())) {
return Base64.toBase64String(signature);
} else if ("encryptedKey".equals(f.getName())) {
return Base64.toBase64String(encryptedKey);
} else if ("encryptedData".equals(f.getName())) {
return Base64.toBase64String(encryptedData);
} else if ("iv".equals(f.getName())) {
return Base64.toBase64String(encryptedData);
} else {
return super.getValue(f);
}
}
}).toString();
}
}
package security;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.SerializationUtils;
import security.model.Data;
import security.model.EncryptedData;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
/**
* Created by marcelmaatkamp (m.maatkamp@gmail.com)
*/
public class RSAWithAESAndCBCWithIVsAndDigestTest {
/**
* AES(256) wrapped in RSA(2048) example
* sends data encrypted from client to server
*/
@Test
public void testRSAWithAESAndCBCWithIVs() throws InvalidKeyException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, SignatureException, NoSuchProviderException, InvalidKeySpecException, NoSuchPaddingException, IOException, InvalidAlgorithmParameterException {
Security.addProvider(new BouncyCastleProvider());
String ALGORITHM_SIGNATURE = "SHA1withRSA";
// bouncycastle provider
String SECURITY_PROVIDER = "BC";
// RSA settings
String ALGORITHM_RSA = "RSA";
String ALGORITHM_RSA_CIPHER = "RSA/None/NoPadding";
int ALGORITHM_RSA_KEYSIZE = 2048;
// AES settings
String ALGORITHM_AES = "AES";
String ALGORITHM_AES_CIPHER = "AES/CBC/PKCS7Padding";
int ALGORITHM_AES_KEYSIZE = 256;
// ------
// CLIENT
// ------
// RSA: pub/priv keys
KeyPairGenerator keyPairGeneratorClient = KeyPairGenerator.getInstance(ALGORITHM_RSA);
keyPairGeneratorClient.initialize(ALGORITHM_RSA_KEYSIZE);
KeyPair keyPairClient = keyPairGeneratorClient.generateKeyPair();
PrivateKey privateKeyClient = keyPairClient.getPrivate();
PublicKey publicKeyClient = keyPairClient.getPublic();
Cipher cipherClient = Cipher.getInstance(ALGORITHM_RSA_CIPHER, SECURITY_PROVIDER);
// AES: symmetrical
KeyGenerator keyGeneratorSymmetricalKeyClient = KeyGenerator.getInstance(ALGORITHM_AES);
keyGeneratorSymmetricalKeyClient.init(ALGORITHM_AES_KEYSIZE);
SecretKey symmetricalKeyClient = keyGeneratorSymmetricalKeyClient.generateKey();
Cipher cipherSymmetricalKeyClient = Cipher.getInstance(ALGORITHM_AES_CIPHER, SECURITY_PROVIDER);
// signature
SecureRandom secureRandomClient = new SecureRandom();
SHA256Digest sha256DigestClient = new SHA256Digest();
Signature signatureClient = Signature.getInstance(ALGORITHM_SIGNATURE);
// ------
// SERVER
// ------
// RSA: pub/priv keys
KeyPairGenerator keyPairGeneratorServer = KeyPairGenerator.getInstance(ALGORITHM_RSA);
keyPairGeneratorServer.initialize(ALGORITHM_RSA_KEYSIZE);
KeyPair keyPairServer = keyPairGeneratorServer.generateKeyPair();
PrivateKey privateKeyServer = keyPairServer.getPrivate();
PublicKey publicKeyServer = keyPairServer.getPublic();
Cipher cipherServer = Cipher.getInstance(ALGORITHM_RSA_CIPHER, SECURITY_PROVIDER);
// AES: symmetrical
KeyGenerator keyGeneratorSymmetricalKeyServer = KeyGenerator.getInstance(ALGORITHM_AES);
keyGeneratorSymmetricalKeyServer.init(ALGORITHM_AES_KEYSIZE);
// SecretKey symmetricalKeyServer = keyGeneratorSymmetricalKeyServer.generateKey();
Cipher cipherSymmetricalKeyServer = Cipher.getInstance(ALGORITHM_AES_CIPHER, SECURITY_PROVIDER);
// signature
SHA256Digest sha256DigestServer = new SHA256Digest();
Signature signatureServer = Signature.getInstance(ALGORITHM_SIGNATURE);
// -------------
// on the client
// -------------
String text = "encrypt me!";
byte[] plain = SerializationUtils.serialize(new Data(text));
EncryptedData encryptedData = new EncryptedData();
// calculate digest
byte[] digest = new byte[sha256DigestClient.getDigestSize()];
sha256DigestClient.update(plain, 0, plain.length);
sha256DigestClient.doFinal(digest, 0);
// sign the digest
signatureClient.initSign(privateKeyClient);
signatureClient.update(digest);
encryptedData.signature = signatureClient.sign();
// crypt text
IvParameterSpec ivParameterClient = new IvParameterSpec(secureRandomClient.generateSeed(16));
cipherSymmetricalKeyServer.init(Cipher.ENCRYPT_MODE, symmetricalKeyClient, ivParameterClient);
encryptedData.encryptedData = cipherSymmetricalKeyServer.doFinal(plain);
encryptedData.iv = ivParameterClient.getIV();
// crypt aes key
cipherClient.init(Cipher.WRAP_MODE, publicKeyServer);
encryptedData.encryptedKey = cipherClient.wrap(symmetricalKeyClient);
// --------------
// transportation
// --------------
EncryptedData serializedEncryptedData =
(EncryptedData) SerializationUtils.deserialize(
SerializationUtils.serialize(encryptedData));
// -------------
// on the server
// -------------
// unwrap aes key
cipherServer.init(Cipher.UNWRAP_MODE, privateKeyServer);
SecretKey decryptedKey = (SecretKey) cipherServer.unwrap(
serializedEncryptedData.encryptedKey, "AES", Cipher.SECRET_KEY);
// decrypt text
IvParameterSpec ivParameterSpecServer = new IvParameterSpec(encryptedData.iv);
cipherSymmetricalKeyClient.init(Cipher.DECRYPT_MODE, decryptedKey, ivParameterSpecServer);
byte[] decyptedData = cipherSymmetricalKeyClient.doFinal(serializedEncryptedData.encryptedData);
// calculate digest
byte[] digestServer = new byte[sha256DigestServer.getDigestSize()];
sha256DigestServer.update(decyptedData, 0, decyptedData.length);
sha256DigestServer.doFinal(digestServer, 0);
// verify signature from digest
signatureServer.initVerify(publicKeyClient);
signatureServer.update(digestServer);
// validate signature
Assert.assertTrue("valid signature(" + Base64.toBase64String(serializedEncryptedData.signature) + ") from client", signatureServer.verify(serializedEncryptedData.signature));
// validate decrypted text
if (signatureServer.verify(serializedEncryptedData.signature)) {
Data decryptedData = (Data) SerializationUtils.deserialize(decyptedData);
Assert.assertEquals("decypted text same as original", decryptedData.msg, text);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment