1 package org.bouncycastle.pkcs.test; 2 3 import java.math.BigInteger; 4 import java.security.Security; 5 6 import junit.framework.TestCase; 7 import org.bouncycastle.asn1.DERNull; 8 import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; 9 import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo; 10 import org.bouncycastle.asn1.pkcs.PBES2Parameters; 11 import org.bouncycastle.asn1.pkcs.PBKDF2Params; 12 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 13 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; 14 import org.bouncycastle.asn1.pkcs.RSAPrivateKey; 15 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 16 import org.bouncycastle.crypto.util.PBKDFConfig; 17 import org.bouncycastle.crypto.util.ScryptConfig; 18 import org.bouncycastle.jce.provider.BouncyCastleProvider; 19 import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; 20 import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfoBuilder; 21 import org.bouncycastle.pkcs.jcajce.JcePKCSPBEInputDecryptorProviderBuilder; 22 import org.bouncycastle.pkcs.jcajce.JcePKCSPBEOutputEncryptorBuilder; 23 import org.bouncycastle.util.Arrays; 24 import org.bouncycastle.util.encoders.Base64; 25 26 public class PKCS8Test 27 extends TestCase 28 { 29 private static BigInteger modulus = new BigInteger( 30 "b6ce33ccbf839457b0d32487b6c807bca584f85c627466b787fc09d0b1f73d97c9a381eca20e0ba851d317a8964327fa0010de76c" + 31 "6c0facb83f13612752d166b49d9ba272c38c9a4ed71a94ea69f7bbdc63d7a5c5d3f3c039223e4ac1bb5d433c6bf01e68364a7ef4f" + 32 "061f7cdfba82fa471bb1444b2034e53cc9c3e402a8fa89", 16); 33 34 private static byte[] pkInfo = Base64.decode( 35 "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALbOM8y/g5RXsNMkh7bIB7ylhPhcYnRmt4f8CdCx9z2XyaOB7KIOC6hR" + 36 "0xeolkMn+gAQ3nbGwPrLg/E2EnUtFmtJ2bonLDjJpO1xqU6mn3u9xj16XF0/PAOSI+SsG7XUM8a/AeaDZKfvTwYffN+6gvpHG7FESyA0" + 37 "5TzJw+QCqPqJAgMBAAECgYAMQxCeb0o4LRmjUBP6YriCIugkcK35+NneuT0/TnCzJPdVjGV/CUom5DYwpBJQNuJCFt+VQAe5yuTyzRm3" + 38 "2mpicusxKsMHqJRJFWIQ5ztuRehGF1KB+NPze7GxWVB2vRWJQQhlgq/nRsAjWoUfxbFkKBlNPhUnLm1klwBptpqpcQJBAOBiAnrrraBu" + 39 "3Lc9B8QtCdEAIr5LYyWYd3jSvyTt04OI8Q3l7zG9omKpdIskGNu7n5RRYixsNXAVCaiHsyHHCO8CQQDQkGdtlH5fQZ2PJVSNZ6RlDhUq" + 40 "6RGqajnkXw/sK1GR388FGqc9xTB9Eu1vg7ywlsuWSWpiCe/q+1nGVJufLAQHAkEAyTba5oQGNYJ1J1Txa/i/fs7SWTedd49cQ9spUeJ7" + 41 "9M6O7FmvwDlAL52qR0Rdjl6YYhcBJLj8yr/y41CdUML9vQJAYGDqurOtNj2vHrAkg3fKezxnwb2UgUi3WfYn+H4IIr3m/7fSYvQVtSai" + 42 "/C5Hat80U0230HhBGzhtwv3kMEj5zwJAViD4ceQRYyC+G2z5fyFz8Ca6sjDB9LwY0YEOFxR+3nqtteJI2vgITl4HrrnTRGuiVSY6pqkX" + 43 "hX2DZcWDZMieLA=="); 44 45 private static byte[] pkcs8Sha256 = Base64.decode( 46 "MIIC9TBvBgkqhkiG9w0BBQ0wYjBBBgkqhkiG9w0BBQwwNAQgsa99yy9MqsJQ+4l5" + 47 "SehvabVidNKBoJeqPJDZAPmbKCgCAggAMAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUD" + 48 "BAEqBBBAncGTD5Yp0oqVklTgmzt4BIICgDJLy5EF12+l9cjYIRVLcHFc7QE7prBy" + 49 "yj+nENvxqPJaVAVo+VVguOPUSGKQAeZnUhpU1kwKa4EyUhA5CvVtTcQ3hd7v769E" + 50 "n59EJ2NKFNOmplxbE3QU/Z7g63ECDvu4jsUVjZmWGrzDXwDEkraG5VdtVhIfdFOj" + 51 "yR1CEnxLqq5l3qlkCjKFap/UBh6wbsItJJYw4HJ/7fCJtY8xKG9b1hxHiyH2Yhrh" + 52 "Pak2P4ukFClg8Kzv92ZbUKSv92C/zrlkUWx7+u7b97YZVd/nL4VLVnQW79YI7ApL" + 53 "QHFNZ9Jp3cm3XtddzlJJVWwghF+slvULsGzQ05yMICyCRHEwPAPSXvf6VpNezQ+v" + 54 "8mD+lS7IavJRx7S4y2NFzZCLDaZfX32/S4vRv7Q4Ax87YKHqHwLnZRLWn3QimtX5" + 55 "oJPsf8Sj0/w31W49c7I3a4rWLAWO3fTVSvH+vQdPUCq9geqatOjiwSnUy6oSP4f3" + 56 "vvdMlvNFafWyLwqONM8nKijNSSk8fjJtncvIDBCRYmwuQFmkFBRtCpHNeY43vrCV" + 57 "O04x5N6PPTnnp/Ru7xYbrEyO2SQX/JJQV2l/pZgyF4w/2Y3i0hW+dItkoFVPGuY0" + 58 "XfBgPlVx5w/72Et8GKh8a5E03IPJOa3J+/vhx9hYc7Hc4AJHsQQwiXco5ybBNZBV" + 59 "wteKQwP6XRL5GMWJr4v4fJk0ksZ7sDAIlLWOeZu0jxWSx3VLC6QR9Ij+uMGkkY3t" + 60 "nVxJii5qFSnWSH5e2Qk9HJ64a0ossKBFaln8wT/2tryBxa1+YZDYwGrasG4EvKHC" + 61 "N0PVvCZ6nreGoWpaBlTolOl7HpbjcsryQ2SMkWNIurrivWKAoqRQ53Q="); 62 63 64 private static byte[] pkcs8Gost3411 = Base64.decode( 65 "MIIC8zBtBgkqhkiG9w0BBQ0wYDA/BgkqhkiG9w0BBQwwMgQgo40hf88LUYklfxUE" + 66 "HO0KjJFo52p9lEqfYDDmJJosDpYCAggAMAoGBiqFAwICCgUAMB0GCWCGSAFlAwQB" + 67 "KgQQJXNzoxem4QvtoToJbJVt1ASCAoBtcnpMvp/Skip+m8e0A+Hh8BnzoRDkKoeD" + 68 "QFuyR1HRfXa6iZ+CT5Bt38kM7shDA1se1uEo5WnDCydmzQ5WdHinMaokryd+3l65" + 69 "AszZLrbK56E78820RMTwFevDAXcwhneomCkEg059r+GfO0OLe6YJ1JR88uiPWxJy" + 70 "gthltJoefOnK87cG53oOPAmgKkMS0lbd13FeYduo9r2473O80CtTpA0p5GHFHdI8" + 71 "9ebu8PWoGez+HR3FU5+m4Qj63spW2F1qblgocywABFqVCWVp/8h4dptQ7754jNmK" + 72 "HN4MWgXYb5SdScz8IkE9Cv+Xn0tAW5eqhgYDot4GfbYRqCjup0jnCmgNxFo/TMOS" + 73 "H1EMXeFnEEEft/fx8K1jZ1jtfJQRBY1N0jOBBzsMKVgj8GYkFAlOYXziCK+YzYjY" + 74 "gmD2/IQ1+VfPnCkT14BqM9KzJidOjMDE9jlMiBhaBzee0qpdCLZ9bPQ0L6s6Urwm" + 75 "mR7l1nCvLY5GYRBUC/ZOZf+MiPEpD/Lu+DUv5RgPEDStSXoKqtxvgpsT4upDVpEw" + 76 "i4z7TWGpkcOGZJEe8JHEw5rDC15FHm44WoeFhlgLaFhjUD9Ou4CYM3LYT6VwUbmF" + 77 "XBBVuKssFbbvOcU1ez4vfx7i8r09R/olVmopsiUBapyLwfck3hlQEYrAJKHQ9HFV" + 78 "qYM9tU0OoaZB1qYYmLQPIe99cr66xTmfUkRQaJ2RAhbZQDPTX3Bm4SseEfmrkfuY" + 79 "/RzOT5l2cgEOuTmkzhfgxVqyhOBeWfGPWYWtDD2QmQBcAHZbf9XVaoRe7YDRXTG/" + 80 "WhEN3fKJaM/Qfif5wwWvHjQb5TWrTyeNNuh4YtXsyQ3PkwOxHrmm" 81 ); 82 83 // from RFC 7914 84 private static byte[] pkcs8Scrypt = Base64.decode( 85 "MIHiME0GCSqGSIb3DQEFDTBAMB8GCSsGAQQB2kcECzASBAVNb3VzZQIDEAAAAgEI" + 86 "AgEBMB0GCWCGSAFlAwQBKgQQyYmguHMsOwzGMPoyObk/JgSBkJb47EWd5iAqJlyy" + 87 "+ni5ftd6gZgOPaLQClL7mEZc2KQay0VhjZm/7MbBUNbqOAXNM6OGebXxVp6sHUAL" + 88 "iBGY/Dls7B1TsWeGObE0sS1MXEpuREuloZjcsNVcNXWPlLdZtkSH6uwWzR0PyG/Z" + 89 "+ZXfNodZtd/voKlvLOw5B3opGIFaLkbtLZQwMiGtl42AS89lZg==" 90 ); 91 92 private static byte[] scryptKey = Base64.decode( 93 "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg4RaNK5CuHY3CXr9f" + 94 "/CdVgOhEurMohrQmWbbLZK4ZInyhRANCAARs2WMV6UMlLjLaoc0Dsdnj4Vlffc9T" + 95 "t48lJU0RiCzXc280Vg/H5fm1xAP1B7UnIVcBqgDHDcfqWm1h/xSeCHXS" 96 ); 97 setUp()98 public void setUp() 99 { 100 Security.addProvider(new BouncyCastleProvider()); 101 } 102 testSHA256()103 public void testSHA256() 104 throws Exception 105 { 106 PKCS8EncryptedPrivateKeyInfo info = new PKCS8EncryptedPrivateKeyInfo(pkcs8Sha256); 107 108 PrivateKeyInfo pkInfo = info.decryptPrivateKeyInfo(new JcePKCSPBEInputDecryptorProviderBuilder().setProvider("BC").build("hello".toCharArray())); 109 110 RSAPrivateKey k = RSAPrivateKey.getInstance(pkInfo.parsePrivateKey()); 111 112 assertEquals(modulus, k.getModulus()); 113 } 114 testGOST3411()115 public void testGOST3411() 116 throws Exception 117 { 118 PKCS8EncryptedPrivateKeyInfo info = new PKCS8EncryptedPrivateKeyInfo(pkcs8Gost3411); 119 120 PrivateKeyInfo pkInfo = info.decryptPrivateKeyInfo(new JcePKCSPBEInputDecryptorProviderBuilder().setProvider("BC").build("hello".toCharArray())); 121 122 RSAPrivateKey k = RSAPrivateKey.getInstance(pkInfo.parsePrivateKey()); 123 124 assertEquals(modulus, k.getModulus()); 125 } 126 testSHA256Encryption()127 public void testSHA256Encryption() 128 throws Exception 129 { 130 PKCS8EncryptedPrivateKeyInfoBuilder bldr = new PKCS8EncryptedPrivateKeyInfoBuilder(pkInfo); 131 132 PKCS8EncryptedPrivateKeyInfo encInfo = bldr.build( 133 new JcePKCSPBEOutputEncryptorBuilder(NISTObjectIdentifiers.id_aes256_CBC) 134 .setPRF(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA256, DERNull.INSTANCE)) 135 .setProvider("BC") 136 .build("hello".toCharArray())); 137 138 EncryptedPrivateKeyInfo encPkInfo = EncryptedPrivateKeyInfo.getInstance(encInfo.getEncoded()); 139 140 assertEquals( 141 new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA256, DERNull.INSTANCE), 142 PBKDF2Params.getInstance( 143 PBES2Parameters.getInstance(encPkInfo.getEncryptionAlgorithm().getParameters()) 144 .getKeyDerivationFunc().getParameters()) 145 .getPrf()); 146 147 PrivateKeyInfo pkInfo = encInfo.decryptPrivateKeyInfo(new JcePKCSPBEInputDecryptorProviderBuilder().setProvider("BC").build("hello".toCharArray())); 148 149 RSAPrivateKey k = RSAPrivateKey.getInstance(pkInfo.parsePrivateKey()); 150 151 assertEquals(modulus, k.getModulus()); 152 } 153 testSHA3_256Encryption()154 public void testSHA3_256Encryption() 155 throws Exception 156 { 157 PKCS8EncryptedPrivateKeyInfoBuilder bldr = new PKCS8EncryptedPrivateKeyInfoBuilder(pkInfo); 158 159 PKCS8EncryptedPrivateKeyInfo encInfo = bldr.build( 160 new JcePKCSPBEOutputEncryptorBuilder(NISTObjectIdentifiers.id_aes256_CBC) 161 .setPRF(new AlgorithmIdentifier(NISTObjectIdentifiers.id_hmacWithSHA3_256, DERNull.INSTANCE)) 162 .setProvider("BC") 163 .build("hello".toCharArray())); 164 165 EncryptedPrivateKeyInfo encPkInfo = EncryptedPrivateKeyInfo.getInstance(encInfo.getEncoded()); 166 167 assertEquals( 168 new AlgorithmIdentifier(NISTObjectIdentifiers.id_hmacWithSHA3_256, DERNull.INSTANCE), 169 PBKDF2Params.getInstance( 170 PBES2Parameters.getInstance(encPkInfo.getEncryptionAlgorithm().getParameters()) 171 .getKeyDerivationFunc().getParameters()) 172 .getPrf()); 173 174 PrivateKeyInfo pkInfo = encInfo.decryptPrivateKeyInfo(new JcePKCSPBEInputDecryptorProviderBuilder().setProvider("BC").build("hello".toCharArray())); 175 176 RSAPrivateKey k = RSAPrivateKey.getInstance(pkInfo.parsePrivateKey()); 177 178 assertEquals(modulus, k.getModulus()); 179 } 180 testScryptEncryption()181 public void testScryptEncryption() 182 throws Exception 183 { 184 PKCS8EncryptedPrivateKeyInfoBuilder bldr = new PKCS8EncryptedPrivateKeyInfoBuilder(scryptKey); 185 186 PBKDFConfig scrypt = new ScryptConfig.Builder(16, 8, 1) 187 .withSaltLength(20).build(); 188 189 PKCS8EncryptedPrivateKeyInfo encInfo = bldr.build( 190 new JcePKCSPBEOutputEncryptorBuilder(scrypt, NISTObjectIdentifiers.id_aes256_CBC) 191 .setProvider("BC") 192 .build("Rabbit".toCharArray())); 193 194 EncryptedPrivateKeyInfo encPkInfo = EncryptedPrivateKeyInfo.getInstance(encInfo.getEncoded()); 195 196 PKCS8EncryptedPrivateKeyInfo info = new PKCS8EncryptedPrivateKeyInfo(encPkInfo); 197 198 PrivateKeyInfo pkInfo = info.decryptPrivateKeyInfo(new JcePKCSPBEInputDecryptorProviderBuilder().setProvider("BC").build("Rabbit".toCharArray())); 199 200 assertTrue(Arrays.areEqual(scryptKey, pkInfo.getEncoded())); 201 } 202 } 203