001: package org.bouncycastle.crypto.test;
002:
003: import org.bouncycastle.asn1.ASN1InputStream;
004: import org.bouncycastle.asn1.ASN1OctetString;
005: import org.bouncycastle.asn1.ASN1Sequence;
006: import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
007: import org.bouncycastle.asn1.pkcs.EncryptionScheme;
008: import org.bouncycastle.asn1.pkcs.PBES2Parameters;
009: import org.bouncycastle.asn1.pkcs.PBKDF2Params;
010: import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
011: import org.bouncycastle.asn1.pkcs.RC2CBCParameter;
012: import org.bouncycastle.crypto.BufferedBlockCipher;
013: import org.bouncycastle.crypto.CipherParameters;
014: import org.bouncycastle.crypto.PBEParametersGenerator;
015: import org.bouncycastle.crypto.engines.DESEngine;
016: import org.bouncycastle.crypto.engines.DESedeEngine;
017: import org.bouncycastle.crypto.engines.RC2Engine;
018: import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
019: import org.bouncycastle.crypto.modes.CBCBlockCipher;
020: import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
021: import org.bouncycastle.crypto.params.KeyParameter;
022: import org.bouncycastle.crypto.params.ParametersWithIV;
023: import org.bouncycastle.util.encoders.Base64;
024: import org.bouncycastle.util.encoders.Hex;
025: import org.bouncycastle.util.test.SimpleTest;
026:
027: import java.io.ByteArrayInputStream;
028:
029: /**
030: * A test class for PKCS5 PBES2 with PBKDF2 (PKCS5 v2.0) using
031: * test vectors provider at
032: * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
033: * RSA's PKCS5 Page</a>
034: * <br>
035: * The vectors are Base 64 encoded and encrypted using the password "password"
036: * (without quotes). They should all yield the same PrivateKeyInfo object.
037: */
038: public class PKCS5Test extends SimpleTest {
039: /**
040: * encrypted using des-cbc.
041: */
042: static byte[] sample1 = Base64
043: .decode("MIIBozA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIfWBDXwLp4K4CAggA"
044: + "MBEGBSsOAwIHBAiaCF/AvOgQ6QSCAWDWX4BdAzCRNSQSANSuNsT5X8mWYO27mr3Y"
045: + "9c9LoBVXGNmYWKA77MI4967f7SmjNcgXj3xNE/jmnVz6hhsjS8E5VPT3kfyVkpdZ"
046: + "0lr5e9Yk2m3JWpPU7++v5zBkZmC4V/MwV/XuIs6U+vykgzMgpxQg0oZKS9zgmiZo"
047: + "f/4dOCL0UtCDnyOSvqT7mCVIcMDIEKu8QbVlgZYBop08l60EuEU3gARUo8WsYQmO"
048: + "Dz/ldx0Z+znIT0SXVuOwc+RVItC5T/Qx+aijmmpt+9l14nmaGBrEkmuhmtdvU/4v"
049: + "aptewGRgmjOfD6cqK+zs0O5NrrJ3P/6ZSxXj91CQgrThGfOv72bUncXEMNtc8pks"
050: + "2jpHFjGMdKufnadAD7XuMgzkkaklEXZ4f5tU6heIIwr51g0GBEGF96gYPFnjnSQM"
051: + "75JE02Clo+DfcfXpcybPTwwFg2jd6JTTOfkdf6OdSlA/1XNK43FA");
052:
053: /**
054: * encrypted using des-ede3-cbc.
055: */
056: static byte[] sample2 = Base64
057: .decode("MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA"
058: + "MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/"
059: + "koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8"
060: + "+MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5"
061: + "6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi"
062: + "5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ"
063: + "BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrXE9XR3tPayE+iOB15llFSmi8"
064: + "z0ByOXldEpkezCn92Umk++suzIVj1qfsK+bv2phZWJPbLEIWPDRHUbYf76q5ArAr"
065: + "u4xtxT/hoK3krEs/IN3d70qjlUJ36SEw1UaZ82PWhakQbdtu39ZraMJB");
066:
067: /**
068: * encrypted using rc2-cbc.
069: */
070: static byte[] sample3 = Base64
071: .decode("MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA"
072: + "AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop"
073: + "7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f"
074: + "wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21"
075: + "RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6"
076: + "VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1"
077: + "MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8RqH2MRyblsPNSikyYhxX/cz"
078: + "tdDxRKhilySbSBg5Kr8OfcwKp9bpinN96nmG4xr3Tch1bnVvqJzOQ5+Vva2WwVvH"
079: + "2JkWvYm5WaANg4Q6bRxu9vz7DuhbJjQdZbxFezIAgrJdSe92B00jO/0Kny1WjiVO"
080: + "6DA=");
081:
082: static byte[] result = Hex
083: .decode("30820155020100300d06092a864886f70d01010105000482013f3082013b020100024100"
084: + "debbfc2c09d61bada2a9462f24224e54cc6b3cc0755f15ce318ef57e79df17026b6a85cc"
085: + "a12428027245045df2052a329a2f9ad3d17b78a10572ad9b22bf343b020301000102402d"
086: + "90a96adcec472743527bc023153d8f0d6e96b40c8ed228276d467d843306429f8670559b"
087: + "f376dd41857f6397c2fc8d95e0e53ed62de420b855430ee4a1b8a1022100ffcaf0838239"
088: + "31e073ff534f06a5d415b3d414bc614a4544a3dff7ed271817eb022100deea30242117db"
089: + "2d3b8837f58f1da530ff83cf9283680da33683ec4e583610f1022100e6026381adb0a683"
090: + "f16a8f4c096b462979b9e4277cc89f3ed8a905b46fa9ff9f02210097c146d4d1d2b3dbaf"
091: + "53a504ff51674c5c271800de84d003f4f10ac6ab36e38102202bfa141f10bda874e1017d"
092: + "845e82767c1c38e82745daf421f0c8cd09d7652387");
093:
094: private class PBETest extends SimpleTest {
095: int id;
096: BufferedBlockCipher cipher;
097: byte[] sample;
098: int keySize;
099:
100: PBETest(int id, BufferedBlockCipher cipher, byte[] sample,
101: int keySize) {
102: this .id = id;
103: this .cipher = cipher;
104: this .sample = sample;
105: this .keySize = keySize;
106: }
107:
108: public String getName() {
109: return cipher.getUnderlyingCipher().getAlgorithmName()
110: + " PKCS5S2 Test " + id;
111: }
112:
113: public void performTest() {
114: char[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
115: PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
116: ByteArrayInputStream bIn = new ByteArrayInputStream(sample);
117: ASN1InputStream dIn = new ASN1InputStream(bIn);
118: EncryptedPrivateKeyInfo info = null;
119:
120: try {
121: info = new EncryptedPrivateKeyInfo((ASN1Sequence) dIn
122: .readObject());
123: } catch (Exception e) {
124: fail("failed construction - exception " + e.toString(),
125: e);
126: }
127:
128: PBES2Parameters alg = new PBES2Parameters(
129: (ASN1Sequence) info.getEncryptionAlgorithm()
130: .getParameters());
131: PBKDF2Params func = PBKDF2Params.getInstance(alg
132: .getKeyDerivationFunc().getParameters());
133: EncryptionScheme scheme = alg.getEncryptionScheme();
134:
135: if (func.getKeyLength() != null) {
136: keySize = func.getKeyLength().intValue() * 8;
137: }
138:
139: int iterationCount = func.getIterationCount().intValue();
140: byte[] salt = func.getSalt();
141:
142: generator.init(PBEParametersGenerator
143: .PKCS5PasswordToBytes(password), salt,
144: iterationCount);
145:
146: CipherParameters param;
147:
148: if (scheme.getObjectId().equals(
149: PKCSObjectIdentifiers.RC2_CBC)) {
150: RC2CBCParameter rc2Params = new RC2CBCParameter(
151: (ASN1Sequence) scheme.getObject());
152: byte[] iv = rc2Params.getIV();
153:
154: param = new ParametersWithIV(generator
155: .generateDerivedParameters(keySize), iv);
156: } else {
157: byte[] iv = ((ASN1OctetString) scheme.getObject())
158: .getOctets();
159:
160: param = new ParametersWithIV(generator
161: .generateDerivedParameters(keySize), iv);
162: }
163:
164: cipher.init(false, param);
165:
166: byte[] data = info.getEncryptedData();
167: byte[] out = new byte[cipher.getOutputSize(data.length)];
168: int len = cipher.processBytes(data, 0, data.length, out, 0);
169:
170: try {
171: len += cipher.doFinal(out, len);
172: } catch (Exception e) {
173: fail("failed doFinal - exception " + e.toString());
174: }
175:
176: if (result.length != len) {
177: fail("failed length");
178: }
179:
180: for (int i = 0; i != len; i++) {
181: if (out[i] != result[i]) {
182: fail("failed comparison");
183: }
184: }
185: }
186: }
187:
188: public String getName() {
189: return "PKCS5S2";
190: }
191:
192: public void performTest() throws Exception {
193: BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
194: new CBCBlockCipher(new DESEngine()));
195: SimpleTest test = new PBETest(0, cipher, sample1, 64);
196:
197: test.performTest();
198:
199: cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(
200: new DESedeEngine()));
201: test = new PBETest(1, cipher, sample2, 192);
202:
203: test.performTest();
204:
205: cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(
206: new RC2Engine()));
207: test = new PBETest(2, cipher, sample3, 0);
208: test.performTest();
209:
210: //
211: // RFC 3211 tests
212: //
213: char[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
214: PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
215:
216: byte[] salt = Hex.decode("1234567878563412");
217:
218: generator.init(PBEParametersGenerator
219: .PKCS5PasswordToBytes(password), salt, 5);
220:
221: if (!areEqual(((KeyParameter) generator
222: .generateDerivedParameters(64)).getKey(), Hex
223: .decode("d1daa78615f287e6"))) {
224: fail("64 test failed");
225: }
226:
227: password = "All n-entities must communicate with other n-entities via n-1 entiteeheehees"
228: .toCharArray();
229:
230: generator.init(PBEParametersGenerator
231: .PKCS5PasswordToBytes(password), salt, 500);
232:
233: if (!areEqual(
234: ((KeyParameter) generator
235: .generateDerivedParameters(192)).getKey(),
236: Hex
237: .decode("6a8970bf68c92caea84a8df28510858607126380cc47ab2d"))) {
238: fail("192 test failed");
239: }
240: }
241:
242: public static void main(String[] args) {
243: runTest(new PKCS5Test());
244: }
245: }
|