private static String dumpBinaryDataAsString(String indent, byte[] bytes) { String nl = System.getProperty("line.separator"); StringBuffer buf = new StringBuffer(); indent += TAB; buf.append(nl); for (int i = 0; i < bytes.length; i += SAMPLE_SIZE) { if (bytes.length - i > SAMPLE_SIZE) { buf.append(indent); buf.append(new String(Hex.encode(bytes, i, SAMPLE_SIZE))); buf.append(TAB); buf.append(calculateAscString(bytes, i, SAMPLE_SIZE)); buf.append(nl); } else { buf.append(indent); buf.append(new String(Hex.encode(bytes, i, bytes.length - i))); for (int j = bytes.length - i; j != SAMPLE_SIZE; j++) { buf.append(" "); } buf.append(TAB); buf.append(calculateAscString(bytes, i, bytes.length - i)); buf.append(nl); } } return buf.toString(); }
private static String outputApplicationSpecific( String type, String indent, boolean verbose, DERObject obj, String nl) { DERApplicationSpecific app = (DERApplicationSpecific) obj; StringBuffer buf = new StringBuffer(); if (app.isConstructed()) { try { ASN1Sequence s = ASN1Sequence.getInstance(app.getObject(DERTags.SEQUENCE)); buf.append(indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "]" + nl); for (Enumeration e = s.getObjects(); e.hasMoreElements(); ) { _dumpAsString(indent + TAB, verbose, (DERObject) e.nextElement(), buf); } } catch (IOException e) { buf.append(e); } return buf.toString(); } return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + new String(Hex.encode(app.getContents())) + ")" + nl; }
/** check that cipher input/output streams are working correctly */ public class CipherStreamTest extends SimpleTest { private static byte[] RK = Hex.decode("0123456789ABCDEF"); private static byte[] RIN = Hex.decode("4e6f772069732074"); private static byte[] ROUT = Hex.decode("3afbb5c77938280d"); private static byte[] SIN = Hex.decode( "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000"); private static final byte[] SK = Hex.decode("80000000000000000000000000000000"); private static final byte[] SIV = Hex.decode("0000000000000000"); private static final byte[] SOUT = Hex.decode( "4DFA5E481DA23EA09A31022050859936" + "DA52FCEE218005164F267CB65F5CFD7F" + "2B4F97E0FF16924A52DF269515110A07" + "F9E460BC65EF95DA58F740B7D1DBB0AA"); private static final byte[] HCIN = new byte[64]; private static final byte[] HCIV = new byte[32]; private static final byte[] HCK256A = new byte[32]; private static final byte[] HC256A = Hex.decode( "5B078985D8F6F30D42C5C02FA6B67951" + "53F06534801F89F24E74248B720B4818" + "CD9227ECEBCF4DBF8DBF6977E4AE14FA" + "E8504C7BC8A9F3EA6C0106F5327E6981"); private static final byte[] HCK128A = new byte[16]; private static final byte[] HC128A = Hex.decode( "82001573A003FD3B7FD72FFB0EAF63AA" + "C62F12DEB629DCA72785A66268EC758B" + "1EDB36900560898178E0AD009ABF1F49" + "1330DC1C246E3D6CB264F6900271D59C"); private static final byte[] GRAIN_V1 = Hex.decode("0123456789abcdef1234"); private static final byte[] GRAIN_V1_IV = Hex.decode("0123456789abcdef"); private static final byte[] GRAIN_V1_IN = new byte[10]; private static final byte[] GRAIN_V1_OUT = Hex.decode("7f362bd3f7abae203664"); private static final byte[] GRAIN_128 = Hex.decode("0123456789abcdef123456789abcdef0"); private static final byte[] GRAIN_128_IV = Hex.decode("0123456789abcdef12345678"); private static final byte[] GRAIN_128_IN = new byte[16]; private static final byte[] GRAIN_128_OUT = Hex.decode("afb5babfa8de896b4b9c6acaf7c4fbfd"); public CipherStreamTest() {} private void runTest(String name) throws Exception { String lCode = "ABCDEFGHIJKLMNOPQRSTUVWXY0123456789"; KeyGenerator kGen; if (name.indexOf('/') < 0) { kGen = KeyGenerator.getInstance(name, "BC"); } else { kGen = KeyGenerator.getInstance(name.substring(0, name.indexOf('/')), "BC"); } Cipher in = Cipher.getInstance(name, "BC"); Cipher out = Cipher.getInstance(name, "BC"); Key key = kGen.generateKey(); ByteArrayInputStream bIn = new ByteArrayInputStream(lCode.getBytes()); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); in.init(Cipher.ENCRYPT_MODE, key); if (in.getIV() != null) { out.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(in.getIV())); } else { out.init(Cipher.DECRYPT_MODE, key); } CipherInputStream cIn = new CipherInputStream(bIn, in); CipherOutputStream cOut = new CipherOutputStream(bOut, out); int c; while ((c = cIn.read()) >= 0) { cOut.write(c); } cIn.close(); cOut.flush(); cOut.close(); String res = new String(bOut.toByteArray()); if (!res.equals(lCode)) { fail("Failed - decrypted data doesn't match."); } } private void testAlgorithm( String name, byte[] keyBytes, byte[] iv, byte[] plainText, byte[] cipherText) throws Exception { SecretKey key = new SecretKeySpec(keyBytes, name); Cipher in = Cipher.getInstance(name, "BC"); Cipher out = Cipher.getInstance(name, "BC"); if (iv != null) { in.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); out.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); } else { in.init(Cipher.ENCRYPT_MODE, key); out.init(Cipher.DECRYPT_MODE, key); } byte[] enc = in.doFinal(plainText); if (!areEqual(enc, cipherText)) { fail(name + ": cipher text doesn't match"); } byte[] dec = out.doFinal(enc); if (!areEqual(dec, plainText)) { fail(name + ": plain text doesn't match"); } } private void testException(String name) { try { byte[] key128 = { (byte) 128, (byte) 131, (byte) 133, (byte) 134, (byte) 137, (byte) 138, (byte) 140, (byte) 143, (byte) 128, (byte) 131, (byte) 133, (byte) 134, (byte) 137, (byte) 138, (byte) 140, (byte) 143 }; byte[] key256 = { (byte) 128, (byte) 131, (byte) 133, (byte) 134, (byte) 137, (byte) 138, (byte) 140, (byte) 143, (byte) 128, (byte) 131, (byte) 133, (byte) 134, (byte) 137, (byte) 138, (byte) 140, (byte) 143, (byte) 128, (byte) 131, (byte) 133, (byte) 134, (byte) 137, (byte) 138, (byte) 140, (byte) 143, (byte) 128, (byte) 131, (byte) 133, (byte) 134, (byte) 137, (byte) 138, (byte) 140, (byte) 143 }; byte[] keyBytes; if (name.equals("HC256")) { keyBytes = key256; } else { keyBytes = key128; } SecretKeySpec cipherKey = new SecretKeySpec(keyBytes, name); Cipher ecipher = Cipher.getInstance(name, "BC"); ecipher.init(Cipher.ENCRYPT_MODE, cipherKey); byte[] cipherText = new byte[0]; try { // According specification Method engineUpdate(byte[] input, // int inputOffset, int inputLen, byte[] output, int // outputOffset) // throws ShortBufferException - if the given output buffer is // too // small to hold the result ecipher.update(new byte[20], 0, 20, cipherText); fail("failed exception test - no ShortBufferException thrown"); } catch (ShortBufferException e) { // ignore } try { Cipher c = Cipher.getInstance(name, "BC"); Key k = new PublicKey() { public String getAlgorithm() { return "STUB"; } public String getFormat() { return null; } public byte[] getEncoded() { return null; } }; c.init(Cipher.ENCRYPT_MODE, k); fail("failed exception test - no InvalidKeyException thrown for public key"); } catch (InvalidKeyException e) { // okay } try { Cipher c = Cipher.getInstance(name, "BC"); Key k = new PrivateKey() { public String getAlgorithm() { return "STUB"; } public String getFormat() { return null; } public byte[] getEncoded() { return null; } }; c.init(Cipher.DECRYPT_MODE, k); fail("failed exception test - no InvalidKeyException thrown for private key"); } catch (InvalidKeyException e) { // okay } } catch (Exception e) { fail("unexpected exception.", e); } } public void performTest() throws Exception { runTest("RC4"); testException("RC4"); testAlgorithm("RC4", RK, null, RIN, ROUT); runTest("Salsa20"); testException("Salsa20"); testAlgorithm("Salsa20", SK, SIV, SIN, SOUT); runTest("HC128"); testException("HC128"); testAlgorithm("HC128", HCK128A, HCIV, HCIN, HC128A); runTest("HC256"); testException("HC256"); testAlgorithm("HC256", HCK256A, HCIV, HCIN, HC256A); runTest("VMPC"); testException("VMPC"); // testAlgorithm("VMPC", a, iv, in, a); runTest("VMPC-KSA3"); testException("VMPC-KSA3"); // testAlgorithm("VMPC-KSA3", a, iv, in, a); testAlgorithm("Grainv1", GRAIN_V1, GRAIN_V1_IV, GRAIN_V1_IN, GRAIN_V1_OUT); testAlgorithm("Grain128", GRAIN_128, GRAIN_128_IV, GRAIN_128_IN, GRAIN_128_OUT); runTest("DES/ECB/PKCS7Padding"); runTest("DES/CFB8/NoPadding"); } public String getName() { return "CipherStreamTest"; } public static void main(String[] args) { Security.addProvider(new BouncyCastleProvider()); runTest(new CipherStreamTest()); } }
/** * dump a DER object as a formatted string with indentation * * @param obj the DERObject to be dumped out. */ static void _dumpAsString(String indent, boolean verbose, DERObject obj, StringBuffer buf) { String nl = System.getProperty("line.separator"); if (obj instanceof ASN1Sequence) { Enumeration e = ((ASN1Sequence) obj).getObjects(); String tab = indent + TAB; buf.append(indent); if (obj instanceof BERSequence) { buf.append("BER Sequence"); } else if (obj instanceof DERSequence) { buf.append("DER Sequence"); } else { buf.append("Sequence"); } buf.append(nl); while (e.hasMoreElements()) { Object o = e.nextElement(); if (o == null || o.equals(new DERNull())) { buf.append(tab); buf.append("NULL"); buf.append(nl); } else if (o instanceof DERObject) { _dumpAsString(tab, verbose, (DERObject) o, buf); } else { _dumpAsString(tab, verbose, ((DEREncodable) o).getDERObject(), buf); } } } else if (obj instanceof DERTaggedObject) { String tab = indent + TAB; buf.append(indent); if (obj instanceof BERTaggedObject) { buf.append("BER Tagged ["); } else { buf.append("Tagged ["); } DERTaggedObject o = (DERTaggedObject) obj; buf.append(Integer.toString(o.getTagNo())); buf.append(']'); if (!o.isExplicit()) { buf.append(" IMPLICIT "); } buf.append(nl); if (o.isEmpty()) { buf.append(tab); buf.append("EMPTY"); buf.append(nl); } else { _dumpAsString(tab, verbose, o.getObject(), buf); } } else if (obj instanceof BERSet) { Enumeration e = ((ASN1Set) obj).getObjects(); String tab = indent + TAB; buf.append(indent); buf.append("BER Set"); buf.append(nl); while (e.hasMoreElements()) { Object o = e.nextElement(); if (o == null) { buf.append(tab); buf.append("NULL"); buf.append(nl); } else if (o instanceof DERObject) { _dumpAsString(tab, verbose, (DERObject) o, buf); } else { _dumpAsString(tab, verbose, ((DEREncodable) o).getDERObject(), buf); } } } else if (obj instanceof DERSet) { Enumeration e = ((ASN1Set) obj).getObjects(); String tab = indent + TAB; buf.append(indent); buf.append("DER Set"); buf.append(nl); while (e.hasMoreElements()) { Object o = e.nextElement(); if (o == null) { buf.append(tab); buf.append("NULL"); buf.append(nl); } else if (o instanceof DERObject) { _dumpAsString(tab, verbose, (DERObject) o, buf); } else { _dumpAsString(tab, verbose, ((DEREncodable) o).getDERObject(), buf); } } } else if (obj instanceof DERObjectIdentifier) { buf.append(indent + "ObjectIdentifier(" + ((DERObjectIdentifier) obj).getId() + ")" + nl); } else if (obj instanceof DERBoolean) { buf.append(indent + "Boolean(" + ((DERBoolean) obj).isTrue() + ")" + nl); } else if (obj instanceof DERInteger) { buf.append(indent + "Integer(" + ((DERInteger) obj).getValue() + ")" + nl); } else if (obj instanceof BERConstructedOctetString) { ASN1OctetString oct = (ASN1OctetString) obj; buf.append(indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] "); if (verbose) { buf.append(dumpBinaryDataAsString(indent, oct.getOctets())); } else { buf.append(nl); } } else if (obj instanceof DEROctetString) { ASN1OctetString oct = (ASN1OctetString) obj; buf.append(indent + "DER Octet String" + "[" + oct.getOctets().length + "] "); if (verbose) { buf.append(dumpBinaryDataAsString(indent, oct.getOctets())); } else { buf.append(nl); } } else if (obj instanceof DERBitString) { DERBitString bt = (DERBitString) obj; buf.append( indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] "); if (verbose) { buf.append(dumpBinaryDataAsString(indent, bt.getBytes())); } else { buf.append(nl); } } else if (obj instanceof DERIA5String) { buf.append(indent + "IA5String(" + ((DERIA5String) obj).getString() + ") " + nl); } else if (obj instanceof DERUTF8String) { buf.append(indent + "UTF8String(" + ((DERUTF8String) obj).getString() + ") " + nl); } else if (obj instanceof DERPrintableString) { buf.append(indent + "PrintableString(" + ((DERPrintableString) obj).getString() + ") " + nl); } else if (obj instanceof DERVisibleString) { buf.append(indent + "VisibleString(" + ((DERVisibleString) obj).getString() + ") " + nl); } else if (obj instanceof DERBMPString) { buf.append(indent + "BMPString(" + ((DERBMPString) obj).getString() + ") " + nl); } else if (obj instanceof DERT61String) { buf.append(indent + "T61String(" + ((DERT61String) obj).getString() + ") " + nl); } else if (obj instanceof DERUTCTime) { buf.append(indent + "UTCTime(" + ((DERUTCTime) obj).getTime() + ") " + nl); } else if (obj instanceof DERGeneralizedTime) { buf.append(indent + "GeneralizedTime(" + ((DERGeneralizedTime) obj).getTime() + ") " + nl); } else if (obj instanceof DERUnknownTag) { buf.append( indent + "Unknown " + Integer.toString(((DERUnknownTag) obj).getTag(), 16) + " " + new String(Hex.encode(((DERUnknownTag) obj).getData())) + nl); } else if (obj instanceof BERApplicationSpecific) { buf.append(outputApplicationSpecific("BER", indent, verbose, obj, nl)); } else if (obj instanceof DERApplicationSpecific) { buf.append(outputApplicationSpecific("DER", indent, verbose, obj, nl)); } else if (obj instanceof DEREnumerated) { DEREnumerated en = (DEREnumerated) obj; buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl); } else if (obj instanceof DERExternal) { DERExternal ext = (DERExternal) obj; buf.append(indent + "External " + nl); String tab = indent + TAB; if (ext.getDirectReference() != null) { buf.append(tab + "Direct Reference: " + ext.getDirectReference().getId() + nl); } if (ext.getIndirectReference() != null) { buf.append(tab + "Indirect Reference: " + ext.getIndirectReference().toString() + nl); } if (ext.getDataValueDescriptor() != null) { _dumpAsString(tab, verbose, ext.getDataValueDescriptor(), buf); } buf.append(tab + "Encoding: " + ext.getEncoding() + nl); _dumpAsString(tab, verbose, ext.getExternalContent(), buf); } else { buf.append(indent + obj.toString() + nl); } }