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