001: package org.bouncycastle.asn1.test;
002:
003: import org.bouncycastle.asn1.ASN1InputStream;
004: import org.bouncycastle.asn1.ASN1OutputStream;
005: import org.bouncycastle.asn1.ASN1Set;
006: import org.bouncycastle.asn1.DERSet;
007: import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
008: import org.bouncycastle.asn1.cms.CompressedData;
009: import org.bouncycastle.asn1.cms.ContentInfo;
010: import org.bouncycastle.asn1.cms.EnvelopedData;
011: import org.bouncycastle.asn1.cms.KEKRecipientInfo;
012: import org.bouncycastle.asn1.cms.KeyTransRecipientInfo;
013: import org.bouncycastle.asn1.cms.RecipientInfo;
014: import org.bouncycastle.asn1.cms.SignedData;
015: import org.bouncycastle.util.encoders.Base64;
016: import org.bouncycastle.util.test.SimpleTestResult;
017: import org.bouncycastle.util.test.Test;
018: import org.bouncycastle.util.test.TestResult;
019:
020: import java.io.ByteArrayInputStream;
021: import java.io.ByteArrayOutputStream;
022:
023: public class CMSTest implements Test {
024: //
025: // compressed data object
026: //
027: byte[] compData = Base64
028: .decode("MIAGCyqGSIb3DQEJEAEJoIAwgAIBADANBgsqhkiG9w0BCRADCDCABgkqhkiG9w0BBwGggCSABIIC"
029: + "Hnic7ZRdb9owFIbvK/k/5PqVYPFXGK12YYyboVFASSp1vQtZGiLRACZE49/XHoUW7S/0tXP8Efux"
030: + "fU5ivWnasml72XFb3gb5druui7ytN803M570nii7C5r8tfwR281hy/p/KSM3+jzH5s3+pbQ90xSb"
031: + "P3VT3QbLusnt8WPIuN5vN/vaA2+DulnXTXkXvNTr8j8ouZmkCmGI/UW+ZS/C8zP0bz2dz0zwLt+1"
032: + "UEk2M8mlaxjRMByAhZTj0RGYg4TvogiRASROsZgjpVcJCb1KV6QzQeDJ1XkoQ5Jm+C5PbOHZZGRi"
033: + "v+ORAcshOGeCcdFJyfgFxdtCdEcmOrbinc/+BBMzRThEYpwl+jEBpciSGWQkI0TSlREmD/eOHb2D"
034: + "SGLuESm/iKUFt1y4XHBO2a5oq0IKJKWLS9kUZTA7vC5LSxYmgVL46SIWxIfWBQd6AdrnjLmH94UT"
035: + "vGxVibLqRCtIpp4g2qpdtqK1LiOeolpVK5wVQ5P7+QjZAlrh0cePYTx/gNZuB9Vhndtgujl9T/tg"
036: + "W9ogK+3rnmg3YWygnTuF5GDS+Q/jIVLnCcYZFc6Kk/+c80wKwZjwdZIqDYWRH68MuBQSXLgXYXj2"
037: + "3CAaYOBNJMliTl0X7eV5DnoKIFSKYdj3cRpD/cK/JWTHJRe76MUXnfBW8m7Hd5zhQ4ri2NrVF/WL"
038: + "+kV1/3AGSlJ32bFPd2BsQD8uSzIx6lObkjdz95c0AAAAAAAAAAAAAAAA");
039:
040: //
041: // enveloepd data
042: //
043: byte[] envDataKeyTrns = Base64
044: .decode("MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1Cb3Vu"
045: + "Y3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBCjANBgkqhkiG9w0BAQEFAASBgC5vdGrB"
046: + "itQSGwifLf3KwPILjaB4WEXgT/IIO1KDzrsbItCJsMA0Smq2y0zptxT0pSRL6JRg"
047: + "NMxLk1ySnrIrvGiEPLMR1zjxlT8yQ6VLX+kEoK43ztd1aaLw0oBfrcXcLN7BEpZ1"
048: + "TIdjlBfXIOx1S88WY1MiYqJJFc3LMwRUaTEDMIAGCSqGSIb3DQEHATAdBglghkgB"
049: + "ZQMEARYEEAfxLMWeaBOTTZQwUq0Y5FuggAQgwOJhL04rjSZCBCSOv5i5XpFfGsOd"
050: + "YSHSqwntGpFqCx4AAAAAAAAAAAAA");
051:
052: byte[] envDataKEK = Base64
053: .decode("MIAGCSqGSIb3DQEHA6CAMIACAQIxUqJQAgEEMAcEBQECAwQFMBAGCyqGSIb3DQEJE"
054: + "AMHAgE6BDC7G/HyUPilIrin2Yeajqmj795VoLWETRnZAAFcAiQdoQWyz+oCh6WY/H"
055: + "jHHi+0y+cwgAYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAiY3eDBBbF6naCABBiNdzJb"
056: + "/v6+UZB3XXKipxFDUpz9GyjzB+gAAAAAAAAAAAAA");
057:
058: //
059: // signed data
060: //
061: byte[] signedData = Base64
062: .decode("MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCA"
063: + "JIAEDEhlbGxvIFdvcmxkIQAAAAAAAKCCBGIwggINMIIBdqADAgECAgEBMA0GCSqG"
064: + "SIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFV"
065: + "MB4XDTA0MTAyNDA0MzA1OFoXDTA1MDIwMTA0MzA1OFowJTEWMBQGA1UEChMNQm91"
066: + "bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
067: + "AoGBAJj3OAshAOgDmPcYZ1jdNSuhOHRH9VhC/PG17FdiInVGc2ulJhEifEQga/uq"
068: + "ZCpSd1nHsJUZKm9k1bVneWzC0941i9Znfxgb2jnXXsa5kwB2KEVESrOWsRjSRtnY"
069: + "iLgqBG0rzpaMn5A5ntu7N0406EesBhe19cjZAageEHGZDbufAgMBAAGjTTBLMB0G"
070: + "A1UdDgQWBBR/iHNKOo6f4ByWFFywRNZ65XSr1jAfBgNVHSMEGDAWgBR/iHNKOo6f"
071: + "4ByWFFywRNZ65XSr1jAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBBAUAA4GBAFMJJ7QO"
072: + "pHo30bnlQ4Ny3PCnK+Se+Gw3TpaYGp84+a8fGD9Dme78G6NEsgvpFGTyoLxvJ4CB"
073: + "84Kzys+1p2HdXzoZiyXAer5S4IwptE3TxxFwKyj28cRrM6dK47DDyXUkV0qwBAMN"
074: + "luwnk/no4K7ilzN2MZk5l7wXyNa9yJ6CHW6dMIICTTCCAbagAwIBAgIBAjANBgkq"
075: + "hkiG9w0BAQQFADAlMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJB"
076: + "VTAeFw0wNDEwMjQwNDMwNTlaFw0wNTAyMDEwNDMwNTlaMGUxGDAWBgNVBAMTD0Vy"
077: + "aWMgSC4gRWNoaWRuYTEkMCIGCSqGSIb3DQEJARYVZXJpY0Bib3VuY3ljYXN0bGUu"
078: + "b3JnMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTCBnzANBgkq"
079: + "hkiG9w0BAQEFAAOBjQAwgYkCgYEAm+5CnGU6W45iUpCsaGkn5gDruZv3j/o7N6ag"
080: + "mRZhikaLG2JF6ECaX13iioVJfmzBsPKxAACWwuTXCoSSXG8viK/qpSHwJpfQHYEh"
081: + "tcC0CxIqlnltv3KQAGwh/PdwpSPvSNnkQBGvtFq++9gnXDBbynfP8b2L2Eis0X9U"
082: + "2y6gFiMCAwEAAaNNMEswHQYDVR0OBBYEFEAmOksnF66FoQm6IQBVN66vJo1TMB8G"
083: + "A1UdIwQYMBaAFH+Ic0o6jp/gHJYUXLBE1nrldKvWMAkGA1UdEwQCMAAwDQYJKoZI"
084: + "hvcNAQEEBQADgYEAEeIjvNkKMPU/ZYCu1TqjGZPEqi+glntg2hC/CF0oGyHFpMuG"
085: + "tMepF3puW+uzKM1s61ar3ahidp3XFhr/GEU/XxK24AolI3yFgxP8PRgUWmQizTQX"
086: + "pWUmhlsBe1uIKVEfNAzCgtYfJQ8HJIKsUCcdWeCKVKs4jRionsek1rozkPExggEv"
087: + "MIIBKwIBATAqMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFV"
088: + "AgECMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqG"
089: + "SIb3DQEJBTEPFw0wNDEwMjQwNDMwNTlaMCMGCSqGSIb3DQEJBDEWBBQu973mCM5U"
090: + "BOl9XwQvlfifHCMocTANBgkqhkiG9w0BAQEFAASBgGHbe3/jcZu6b/erRhc3PEji"
091: + "MUO8mEIRiNYBr5/vFNhkry8TrGfOpI45m7gu1MS0/vdas7ykvidl/sNZfO0GphEI"
092: + "UaIjMRT3U6yuTWF4aLpatJbbRsIepJO/B2kdIAbV5SCbZgVDJIPOR2qnruHN2wLF"
093: + "a+fEv4J8wQ8Xwvk0C8iMAAAAAAAA");
094:
095: private boolean isSameAs(byte[] a, byte[] b) {
096: if (a.length != b.length) {
097: return false;
098: }
099:
100: for (int i = 0; i != a.length; i++) {
101: if (a[i] != b[i]) {
102: return false;
103: }
104: }
105:
106: return true;
107: }
108:
109: private TestResult compressionTest() {
110: try {
111: ASN1InputStream aIn = new ASN1InputStream(
112: new ByteArrayInputStream(compData));
113:
114: ContentInfo info = ContentInfo
115: .getInstance(aIn.readObject());
116: CompressedData data = CompressedData.getInstance(info
117: .getContent());
118:
119: data = new CompressedData(data
120: .getCompressionAlgorithmIdentifier(), data
121: .getEncapContentInfo());
122: info = new ContentInfo(CMSObjectIdentifiers.compressedData,
123: data);
124:
125: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
126: ASN1OutputStream aOut = new ASN1OutputStream(bOut);
127:
128: aOut.writeObject(info);
129:
130: if (!isSameAs(bOut.toByteArray(), compData)) {
131: return new SimpleTestResult(false, getName()
132: + ": CMS compression failed to re-encode");
133: }
134:
135: return new SimpleTestResult(true, getName() + ": Okay");
136: } catch (Exception e) {
137: return new SimpleTestResult(false, getName()
138: + ": CMS compression failed - " + e.toString(), e);
139: }
140: }
141:
142: private TestResult envelopedTest() {
143: try {
144: //
145: // Key trans
146: //
147: ASN1InputStream aIn = new ASN1InputStream(
148: new ByteArrayInputStream(envDataKeyTrns));
149:
150: ContentInfo info = ContentInfo
151: .getInstance(aIn.readObject());
152: EnvelopedData envData = EnvelopedData.getInstance(info
153: .getContent());
154: ASN1Set s = envData.getRecipientInfos();
155:
156: if (s.size() != 1) {
157: return new SimpleTestResult(
158: false,
159: getName()
160: + ": CMS KeyTrans enveloped, wrong number of recipients");
161: }
162:
163: RecipientInfo recip = RecipientInfo.getInstance(s
164: .getObjectAt(0));
165:
166: if (recip.getInfo() instanceof KeyTransRecipientInfo) {
167: KeyTransRecipientInfo inf = KeyTransRecipientInfo
168: .getInstance(recip.getInfo());
169:
170: inf = new KeyTransRecipientInfo(inf
171: .getRecipientIdentifier(), inf
172: .getKeyEncryptionAlgorithm(), inf
173: .getEncryptedKey());
174:
175: s = new DERSet(new RecipientInfo(inf));
176: } else {
177: return new SimpleTestResult(
178: false,
179: getName()
180: + ": CMS KeyTrans enveloped, wrong recipient type");
181: }
182:
183: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
184: ASN1OutputStream aOut = new ASN1OutputStream(bOut);
185:
186: envData = new EnvelopedData(envData.getOriginatorInfo(), s,
187: envData.getEncryptedContentInfo(), envData
188: .getUnprotectedAttrs());
189: info = new ContentInfo(CMSObjectIdentifiers.envelopedData,
190: envData);
191:
192: aOut.writeObject(info);
193:
194: if (!isSameAs(bOut.toByteArray(), envDataKeyTrns)) {
195: return new SimpleTestResult(
196: false,
197: getName()
198: + ": CMS KeyTrans enveloped failed to re-encode");
199: }
200:
201: //
202: // KEK
203: //
204: aIn = new ASN1InputStream(new ByteArrayInputStream(
205: envDataKEK));
206:
207: info = ContentInfo.getInstance(aIn.readObject());
208: envData = EnvelopedData.getInstance(info.getContent());
209: s = envData.getRecipientInfos();
210:
211: if (s.size() != 1) {
212: return new SimpleTestResult(
213: false,
214: getName()
215: + ": CMS KEK enveloped, wrong number of recipients");
216: }
217:
218: recip = RecipientInfo.getInstance(s.getObjectAt(0));
219:
220: if (recip.getInfo() instanceof KEKRecipientInfo) {
221: KEKRecipientInfo inf = KEKRecipientInfo
222: .getInstance(recip.getInfo());
223:
224: inf = new KEKRecipientInfo(inf.getKekid(), inf
225: .getKeyEncryptionAlgorithm(), inf
226: .getEncryptedKey());
227:
228: s = new DERSet(new RecipientInfo(inf));
229: } else {
230: return new SimpleTestResult(false, getName()
231: + ": CMS KEK enveloped, wrong recipient type");
232: }
233:
234: bOut = new ByteArrayOutputStream();
235: aOut = new ASN1OutputStream(bOut);
236:
237: envData = new EnvelopedData(envData.getOriginatorInfo(), s,
238: envData.getEncryptedContentInfo(), envData
239: .getUnprotectedAttrs());
240: info = new ContentInfo(CMSObjectIdentifiers.envelopedData,
241: envData);
242:
243: aOut.writeObject(info);
244:
245: if (!isSameAs(bOut.toByteArray(), envDataKEK)) {
246: System.out.println(new String(Base64.encode(bOut
247: .toByteArray())));
248: return new SimpleTestResult(false, getName()
249: + ": CMS KEK enveloped failed to re-encode");
250: }
251:
252: return new SimpleTestResult(true, getName() + ": Okay");
253: } catch (Exception e) {
254: return new SimpleTestResult(false, getName()
255: + ": CMS enveloped failed - " + e.toString(), e);
256: }
257: }
258:
259: private TestResult signedTest() {
260: try {
261: ASN1InputStream aIn = new ASN1InputStream(
262: new ByteArrayInputStream(signedData));
263:
264: ContentInfo info = ContentInfo
265: .getInstance(aIn.readObject());
266: SignedData sData = SignedData
267: .getInstance(info.getContent());
268:
269: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
270: ASN1OutputStream aOut = new ASN1OutputStream(bOut);
271:
272: sData = new SignedData(sData.getDigestAlgorithms(), sData
273: .getEncapContentInfo(), sData.getCertificates(),
274: sData.getCRLs(), sData.getSignerInfos());
275: info = new ContentInfo(CMSObjectIdentifiers.signedData,
276: sData);
277:
278: aOut.writeObject(info);
279:
280: if (!isSameAs(bOut.toByteArray(), signedData)) {
281: return new SimpleTestResult(false, getName()
282: + ": CMS signed failed to re-encode");
283: }
284:
285: return new SimpleTestResult(true, getName() + ": Okay");
286: } catch (Exception e) {
287: return new SimpleTestResult(false, getName()
288: + ": CMS signed failed - " + e.toString(), e);
289: }
290: }
291:
292: public TestResult perform() {
293: TestResult res = compressionTest();
294:
295: if (!res.isSuccessful()) {
296: return res;
297: }
298:
299: res = envelopedTest();
300: if (!res.isSuccessful()) {
301: return res;
302: }
303:
304: return signedTest();
305: }
306:
307: public String getName() {
308: return "CMS";
309: }
310:
311: public static void main(String[] args) {
312: CMSTest test = new CMSTest();
313: TestResult result = test.perform();
314:
315: System.out.println(result);
316: }
317: }
|