Created
December 16, 2015 22:42
-
-
Save alopresto/15477cf7bf12f74359c5 to your computer and use it in GitHub Desktop.
Test code and output using BcPEMDecryptorProvider to try to decrypt an OpenSSL-encrypted file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Test | |
public void testShouldDecryptOpenSSLWithBcPEMDecryptor() throws Exception { | |
// Arrange | |
if (!isUnlimitedStrengthCrypto()) { | |
logger.info("Running in limited encryption mode. Overriding...") | |
setJCEUnlimitedStrength() | |
logger.info("Now running with unlimited strength crypto") | |
} | |
logger.info("Plaintext: ${plaintext}") | |
File file = new File("src/test/resources/salted_raw.enc") | |
byte[] encryptedBytes = file.bytes | |
logger.info("Read encrypted bytes: ${Hex.encodeHexString(encryptedBytes)}") | |
String saltHex = OpenSSLPBEEncryptor.extractHexSaltFromHeader(encryptedBytes) | |
logger.info("Extracted salt hex: ${saltHex.padLeft(saltHex.length() * 2)}") | |
final String PASSWORD = "thisIsABadPassword" | |
byte[] salt = Hex.decodeHex(saltHex.toCharArray()) | |
// Sanity check against known values | |
final String EXPECTED_KEY_HEX = "9C876867E3E914DE8E6249D1C5B4EC21DBCEB8A3F1A09579C8C5AE08B73DCB2E" | |
logger.info("Expected key: ${EXPECTED_KEY_HEX.toLowerCase()}") | |
final String EXPECTED_IV_HEX = "C3A9B16EA80F76CEDA1DB445A62F1BC2" | |
logger.info("Expected IV: ${EXPECTED_IV_HEX.toLowerCase()}") | |
final String EXPECTED_SALT_HEX = "4D41C78350EE0CE8" | |
logger.info("Expected salt: ${EXPECTED_SALT_HEX.toLowerCase()}") | |
final byte[] EXPECTED_KEY = Hex.decodeHex(EXPECTED_KEY_HEX.toCharArray()) | |
final byte[] EXPECTED_IV = Hex.decodeHex(EXPECTED_IV_HEX.toCharArray()) | |
final byte[] EXPECTED_SALT = Hex.decodeHex(EXPECTED_SALT_HEX.toCharArray()) | |
final int EXPECTED_KEY_SIZE = 256 | |
final int EXPECTED_IV_SIZE = 128 | |
String algorithm = "PBEWITHMD5AND256BITAES-CBC-OPENSSL" | |
String provider = "BC" | |
logger.info("Password: ${PASSWORD}") | |
logger.info("Salt : ${fb(salt)}") | |
// Demonstrate that the existing code works correctly | |
PBEKeySpec pbeSpec = new PBEKeySpec(PASSWORD.toCharArray()); | |
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithm, provider); | |
SecretKey secretKey = secretKeyFactory.generateSecret(pbeSpec); | |
PBEParameterSpec saltParams = new PBEParameterSpec(salt, 0); | |
Cipher cipher = Cipher.getInstance(algorithm, "BC"); | |
cipher.init(Cipher.DECRYPT_MODE, secretKey, saltParams); | |
logger.info("Derived IV: ${Hex.encodeHexString(cipher.IV)}") | |
assert cipher.IV == EXPECTED_IV | |
final byte[] cipherBytes = OpenSSLPBEEncryptor.extractCipherTextFromBody(encryptedBytes) | |
byte[] sanityRecovered = cipher.doFinal(cipherBytes) | |
logger.info("Recovered (hex): ${Hex.encodeHexString(sanityRecovered)}") | |
logger.info("Recovered: ${new String(sanityRecovered)}") | |
assert sanityRecovered == plaintext.bytes | |
// // Manually derive the IV because the decryptor requires it as a parameter | |
// OpenSSLPBEParametersGenerator gen = new OpenSSLPBEParametersGenerator(); | |
// gen.init(PASSWORD.bytes, salt); | |
// ParametersWithIV parametersWithIV = (ParametersWithIV) gen.generateDerivedParameters(EXPECTED_KEY_SIZE, EXPECTED_IV_SIZE); | |
// byte[] iv = parametersWithIV.IV | |
// logger.info("Derived IV (PEM): ${Hex.encodeHexString(iv)}") | |
// assert iv == EXPECTED_IV | |
// Act | |
BcPEMDecryptorProvider decryptorProvider = new BcPEMDecryptorProvider(PASSWORD.toCharArray()) | |
PEMDecryptor decryptor = decryptorProvider.get(algorithm) | |
byte[] recovered = decryptor.decrypt(cipherBytes, salt) | |
// Assert | |
assert new String(recovered) == plaintext | |
} | |
Output: | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Running in limited encryption mode. Overriding... | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Now running with unlimited strength crypto | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Plaintext: This is a plaintext message. | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Read encrypted bytes: 53616c7465645f5f4d41c78350ee0ce8e0ebb9a85bd0cbef4ff06849135817413fc73c6f3bcdab247fa7fb446166108f | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Extracted salt hex: 4d41c78350ee0ce8 | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Expected key: 9c876867e3e914de8e6249d1c5b4ec21dbceb8a3f1a09579c8c5ae08b73dcb2e | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Expected IV: c3a9b16ea80f76ceda1db445a62f1bc2 | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Expected salt: 4d41c78350ee0ce8 | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Password: thisIsABadPassword | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Salt : 77 65 -57 -125 80 -18 12 -24 | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Derived IV: c3a9b16ea80f76ceda1db445a62f1bc2 | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Recovered (hex): 54686973206973206120706c61696e74657874206d6573736167652e | |
[main] INFO com.hortonworks.crypto.OpenSSLPBEEncryptorTest - Recovered: This is a plaintext message. | |
org.bouncycastle.openssl.EncryptionException: unknown encryption with private key | |
at org.bouncycastle.openssl.bc.PEMUtilities.crypt(Unknown Source) | |
at org.bouncycastle.openssl.bc.BcPEMDecryptorProvider$1.decrypt(Unknown Source) | |
at org.bouncycastle.openssl.PEMDecryptor$decrypt.call(Unknown Source) | |
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45) | |
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:110) | |
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130) | |
at com.hortonworks.crypto.OpenSSLPBEEncryptorTest.testShouldDecryptOpenSSLWithBcPEMDecryptor(OpenSSLPBEEncryptorTest.groovy:1312) | |
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) | |
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) | |
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) | |
at java.lang.reflect.Method.invoke(Method.java:497) | |
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) | |
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) | |
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) | |
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) | |
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) | |
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) | |
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) | |
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) | |
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) | |
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) | |
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) | |
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) | |
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) | |
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) | |
at org.junit.runners.ParentRunner.run(ParentRunner.java:309) | |
at org.junit.runner.JUnitCore.run(JUnitCore.java:160) | |
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) | |
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234) | |
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74) | |
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) | |
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) | |
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) | |
at java.lang.reflect.Method.invoke(Method.java:497) | |
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment