[Webfunds-commits] java/webfunds/x509 AsnAlgorithmId.java AsnBitString.java AsnInputStream.java AsnInteger.java AsnNull.java AsnObject.java AsnObjectId.java AsnOutputStream.java AsnSequence.java DerException.java SubInputStream.java Test.java
Jeroen C. van Gelderen
gelderen@cypherpunks.ai
Tue, 18 Jul 2000 22:35:43 -0400 (AST)
gelderen 00/07/18 22:35:43
Modified: webfunds/sox Crypto.java
Added: webfunds/x509 AsnAlgorithmId.java AsnBitString.java
AsnInputStream.java AsnInteger.java AsnNull.java
AsnObject.java AsnObjectId.java
AsnOutputStream.java AsnSequence.java
DerException.java SubInputStream.java Test.java
Log:
Revision Changes Path
1.37 +233 -263 java/webfunds/sox/Crypto.java
Index: Crypto.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/sox/Crypto.java,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- Crypto.java 2000/07/14 00:17:16 1.36
+++ Crypto.java 2000/07/19 02:35:41 1.37
@@ -1,4 +1,4 @@
-/* $Id: Crypto.java,v 1.36 2000/07/14 00:17:16 gelderen Exp $
+/* $Id: Crypto.java,v 1.37 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) Systemics Inc. 1995-2000 on behalf of
* The WebFunds Development Team. All Rights Reserved.
@@ -28,39 +28,31 @@
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
-// XXX: Sun X.509 classes we shouldn't be using
-import sun.security.util.BigInt; // done
-import sun.security.util.DerOutputStream;
-import sun.security.util.DerValue;
-import sun.security.x509.AlgorithmId;
-import sun.security.x509.CertException; // done
-import sun.security.x509.X509Cert; // done
-import sun.security.x509.X509Key;
-
import cryptix.provider.key.RawSecretKey;
+import cryptix.provider.rsa.RawRSAPrivateKey;
+import cryptix.provider.rsa.RawRSAPublicKey;
import webfunds.utils.Hex;
+import webfunds.x509.AsnAlgorithmId;
+import webfunds.x509.AsnInputStream;
+import webfunds.x509.AsnObject;
+import webfunds.x509.AsnObjectId;
+import webfunds.x509.AsnOutputStream;
+import webfunds.x509.AsnBitString;
+import webfunds.x509.AsnInteger;
+import webfunds.x509.AsnSequence;
+import webfunds.x509.X509Cert;
/**
+ * XXX: Do Not Touch This File!!!
+ *
* Centralized crypto methods. Currently being overhauled.
*
- * @version $Revision: 1.36 $
+ * @version $Revision: 1.37 $
*/
-public class Crypto
+public final class Crypto
{
- /**
- * This function pulls in the hotlava provider.
- * We expect the Cryptix provider to be installed already.
- *
- * The hotlava provider basically maps additional names to
- * the existing Cryptix algorithm classes. This is neccessary
- * because the sun.* classes use hardwired algorithm names
- * which are not supported by an out-of-the-box Cryptix setup.
- *
- * This section requires the hotlava.crypto.Provider to be
- * present. Otherwise the program won't load.
- */
static
{
java.security.Security.addProvider(new cryptix.provider.Cryptix());
@@ -78,7 +70,6 @@
public static String cipher_padding = "PKCS#5";
public static String pk_alg = "RSA";
public static int pk_strength = 384; // Testing
-// aw shit, can't just arbitrarily change MD5 to SHA - see AlgorithmId.java
public static String sig_alg = "MD5/RSA";
public static int cert_validity = 365 * 24 * 60 * 60; // a year
public static boolean quiet = true;
@@ -157,7 +148,7 @@
try {
cert.verify(key);
return true;
- } catch (CertException e) {
+ } catch (SecurityException e) { // XXX: do CertException again
return false ;
}
}
@@ -171,7 +162,7 @@
public static PublicKey getPublicKeyFromCert(X509Cert cert)
{
try {
- X509Key xkey = (X509Key)cert.getPublicKey();
+ PublicKey xkey = cert.getPublicKey();
return decodePublicKey(keyData(xkey));
} catch (InvalidKeyException e) {
throw new IllegalArgumentException(
@@ -252,8 +243,10 @@
/**
* Create a message digest (as a byte array) from
* data (as a byte array)
- * The digest uses the algorithm specified in crypto.message-digest.algorithm,
+ * The digest uses the algorithm specified in
+ * crypto.message-digest.algorithm,
* and if not defined, defaults to the md_alg algorithm.
+ *
* @param data the data to be digested
* @param offset the offset into the array of the start of the data
* @param len the length of the data
@@ -276,8 +269,10 @@
/**
* Create a message digest (as a byte array) from
* data (as a byte array)
- * The digest uses the algorithm specified in crypto.message-digest.algorithm,
+ * The digest uses the algorithm specified in
+ * crypto.message-digest.algorithm,
* and if not defined, defaults to the md_alg algorithm.
+ *
* @param data the data to be digested
* @return the message digest (as a byte array)
*/
@@ -309,7 +304,8 @@
* @param len the length of the data
* @return the secure checksum (as a byte array)
*/
- public static byte[] checksum(String password, byte[] data, int offset, int len)
+ public static byte[] checksum(String password,
+ byte[] data, int offset, int len)
{
MessageDigest md;
try {
@@ -392,7 +388,8 @@
throw new IllegalArgumentException("Invalid key ("+e.getMessage()+")");
}
catch (NoSuchAlgorithmException e) {
- throw new ProviderException("Symmetric Algorithm not found ("+e.getMessage()+")");
+ throw new ProviderException(
+ "Symmetric Algorithm not found ("+e.getMessage()+")");
}
}
@@ -408,7 +405,8 @@
* @param len the length of the data with the <i>data</i> array
* @return the encrypted data
*/
- public static byte[] encrypt(String password, byte[] data, int offset, int len)
+ public static byte[] encrypt(String password,
+ byte[] data, int offset, int len)
{
return encrypt(password2key(password), data, offset, len);
}
@@ -468,7 +466,8 @@
int zippedLen = cipher.doFinal(data, offset, len, data, 0);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ByteArrayInputStream bais = new ByteArrayInputStream(data, 0, zippedLen);
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(data, 0, zippedLen);
GZIPInputStream gzis = new GZIPInputStream(bais);
byte[] buffer = new byte[4096];
@@ -505,7 +504,8 @@
* @param len the length of the data with the <i>data</i> array
* @return the decrypted data
*/
- public static byte[] decrypt(String password, byte[] data, int offset, int len)
+ public static byte[] decrypt(String password,
+ byte[] data, int offset, int len)
throws KeyException
{
return decrypt(password2key(password), data, offset, len);
@@ -554,10 +554,11 @@
* @param offset the offset within <i>data</i> where the data starts
* @param len the length of the data with the <i>data</i> array
* @return the encrypted data (as a byte array)
- * @exception KeyException a problem has occurred with the public key, such as
- * it not being in the correct format.
+ * @exception KeyException a problem has occurred with the public key,
+ * such as it not being in the correct format.
*/
- public static byte[] pk_encrypt(Key key, PublicKey pk, byte[] data, int offset, int len)
+ public static byte[] pk_encrypt(Key key, PublicKey pk,
+ byte[] data, int offset, int len)
throws KeyException
{
try {
@@ -634,10 +635,11 @@
* @param offset the offset within <i>data</i> where the data starts
* @param len the length of the data with the <i>data</i> array
* @return the encrypted data (as a byte array)
- * @exception KeyException a problem has occurred with the public key, such as
- * it not being in the correct format.
+ * @exception KeyException a problem has occurred with the public key,
+ * such as it not being in the correct format.
*/
- public static byte[] pk_encrypt(PublicKey pk, byte[] data, int offset, int len)
+ public static byte[] pk_encrypt(PublicKey pk,
+ byte[] data, int offset, int len)
throws KeyException
{
return pk_encrypt(generateKey(), pk, data, offset, len);
@@ -650,8 +652,8 @@
* @param pk the PublicKey with which to encrypt the symmetric key
* @param data the data to be encrypted (as a byte array)
* @return the encrypted data (as a byte array)
- * @exception KeyException a problem has occurred with the public key, such as
- * it not being in the correct format.
+ * @exception KeyException a problem has occurred with the public key,
+ * such as it not being in the correct format.
*/
public static byte[] pk_encrypt(Key key, PublicKey pk, byte[] data)
throws KeyException
@@ -666,8 +668,8 @@
* @param pk the PublicKey with which to encrypt the symmetric key
* @param data the data to be encrypted (as a byte array)
* @return the encrypted data (as a byte array)
- * @exception KeyException a problem has occurred with the public key, such as
- * it not being in the correct format.
+ * @exception KeyException a problem has occurred with the public key,
+ * such as it not being in the correct format.
*/
public static byte[] pk_encrypt(PublicKey pk, byte[] data)
throws KeyException
@@ -698,7 +700,7 @@
int pktlen = rsa.getCiphertextBlockSize() + 1;
- System.err.println("pktlen: " + pktlen + ", data.length: " + data.length);
+ System.err.println("pktlen: " +pktlen+", data.length: "+data.length);
byte[] rsa_pkt = rsa.crypt(data, offset, pktlen);
len -= pktlen;
@@ -728,7 +730,8 @@
return new RawSecretKey(cipher_alg, key);
} catch (NoSuchAlgorithmException e) {
- throw new ProviderException(pk_alg+" Algorithm not found ("+e.getMessage()+")");
+ throw new ProviderException(
+ pk_alg+" Algorithm not found ("+e.getMessage()+")");
}
}
@@ -737,7 +740,8 @@
* This method is pretty much the same as the decrypt method,
* except that the PKCS#1 header is skipped.
*
- * @param pk the PrivateKey (required to know the header length - no time consuming asymmetric decryption is done)
+ * @param pk the PrivateKey (required to know the header length
+ * - no time consuming asymmetric decryption is done)
* @param key a symmetric Key object with which to decrypt the data
* @param data the data to be decrypted (as a byte array)
* @param offset the offset within <i>data</i> where the pk-packet starts
@@ -745,7 +749,8 @@
* @return the decrypted Key from the data header
* @exception KeyException a problem has occurred with the private key
*/
- public static byte[] pk_decrypt_data(PrivateKey pk, Key key, byte[] data, int offset, int len)
+ public static byte[] pk_decrypt_data(PrivateKey pk, Key key,
+ byte[] data, int offset, int len)
throws KeyException
{
try {
@@ -755,7 +760,8 @@
int pktlen = rsa.getCiphertextBlockSize();
return decrypt(key, data, offset+pktlen, len-pktlen);
} catch (NoSuchAlgorithmException e) {
- throw new ProviderException(pk_alg+" Algorithm not found ("+e.getMessage()+")");
+ throw new ProviderException(
+ pk_alg+" Algorithm not found ("+e.getMessage()+")");
}
}
@@ -768,10 +774,11 @@
* @param offset the offset within <i>data</i> where the pk-packet starts
* @param len the length of the pk-packet with the <i>data</i> array
* @return the decrypted data (as a byte array)
- * @exception KeyException a problem has occurred with the private key, such as
- * the password being incorrect.
+ * @exception KeyException a problem has occurred with the private key,
+ * such as the password being incorrect.
*/
- public static byte[] pk_decrypt(PrivateKey pk, byte[] data, int offset, int len)
+ public static byte[] pk_decrypt(PrivateKey pk,
+ byte[] data, int offset, int len)
throws KeyException
{
Key key = pk_decrypt_key(pk, data, offset, len);
@@ -798,7 +805,8 @@
* This method is pretty much the same as the decrypt method,
* except that the PKCS#1 header is skipped.
*
- * @param pk the PrivateKey (required to know the header length - no time consuming asymmetric decryption is done)
+ * @param pk the PrivateKey (required to know the header length -
+ * no time consuming asymmetric decryption is done)
* @param key a symmetric Key object with which to decrypt the data
* @param data the data to be decrypted (as a byte array)
* @return the decrypted Key from the data header
@@ -816,8 +824,8 @@
* @param pk a PrivateKey with which to decrypt the data
* @param data the data to be decrypted (as a byte array)
* @return the decrypted data (as a byte array)
- * @exception KeyException a problem has occurred with the private key, such as
- * the password being incorrect.
+ * @exception KeyException a problem has occurred with the private key,
+ * such as the password being incorrect.
*/
public static byte[] pk_decrypt(PrivateKey pk, byte[] data)
throws KeyException
@@ -837,8 +845,8 @@
* @param key a PrivateKey with which to sign the data
* @param data the data being signed (as a byte array)
* @return the binary X509 signature
- * @exception KeyException a problem has occurred with the private key, such as
- * the password being incorrect.
+ * @exception KeyException a problem has occurred with the private key,
+ * such as the password being incorrect.
*/
public static byte[] sign(PrivateKey key, byte[] data)
throws KeyException
@@ -847,7 +855,8 @@
try {
sig = java.security.Signature.getInstance(sig_alg);
} catch (NoSuchAlgorithmException e) {
- throw new ProviderException(pk_alg+" Algorithm not found ("+e.getMessage()+")");
+ throw new ProviderException(
+ pk_alg+" Algorithm not found ("+e.getMessage()+")");
}
// Initialise the object with the private key
@@ -911,83 +920,34 @@
// Methods for extracting data from keys and certificates
////////////////////////////////////////////////////////////////////////
- /**
- * Extract the algorithm id from an X509Key object
- *
- * @param key An X509Key object, from which to extract the algorithm id
- * @return the AlgorithmId object from within the key
- * @exception InvalidKeyException the X509Key is invalid (i.e. incorrectly formatted)
- */
- public static AlgorithmId algorithmId(X509Key key)
+ /**
+ * Extract the key data (the bitstring) from the X509Key.
+ */
+ private static byte[] keyData(PublicKey key)
throws InvalidKeyException
{
- //
- // The X509Key is defined as:
- // SEQUENCE {
- // AlgorithId id
- // BitString key
- // }
-
- //
- // Extract the key data (the bitstring) from the X509Key
- //
- try {
- DerValue dv = new DerValue(key.getEncoded());
-
- // Ensure we have a SEQUENCE
- if (dv.tag != DerValue.tag_Sequence)
- throw new InvalidKeyException("invalid key format");
-
- AlgorithmId algorithmId = AlgorithmId.parse(dv.data.getDerValue());
- byte[] keydata = dv.data.getBitString();
-
- // Ensure no excess data
- if (dv.data.available() != 0)
- throw new InvalidKeyException("excess key data");
-
- return algorithmId;
- } catch (IOException e) {
- e = null;
- throw new InvalidKeyException("Could not parse encoded key data");
- }
- }
+ System.out.println("Fiets!");
+ /*
+ * The X509Key is defined as:
+ *
+ * SEQUENCE
+ * AlgorithId id
+ * BitString key
+ */
- /**
- * Extract the key data from an X509Key object
- *
- * @param key An X509Key object, from which to extract the public key data
- * @return the raw key data from within the key
- * @exception InvalidKeyException the X509Key is invalid (i.e. incorrectly formatted)
- */
- public static byte[] keyData(X509Key key)
- throws InvalidKeyException
- {
- //
- // The X509Key is defined as:
- // SEQUENCE {
- // AlgorithId id
- // BitString key
- // }
-
- //
- // Extract the key data (the bitstring) from the X509Key
- //
try {
- DerValue dv = new DerValue(key.getEncoded());
-
- // Ensure we have a SEQUENCE
- if (dv.tag != DerValue.tag_Sequence)
- throw new InvalidKeyException("invalid key format");
-
- AlgorithmId algorithmId = AlgorithmId.parse(dv.data.getDerValue());
- byte[] keydata = dv.data.getBitString();
-
- // Ensure no excess data
- if (dv.data.available() != 0)
- throw new InvalidKeyException("excess key data");
-
- return keydata;
+ AsnInputStream is = new AsnInputStream(key.getEncoded());
+ AsnSequence seq = (AsnSequence)is.read();
+ if( (is.available()!=0) || (seq.size() != 2) )
+ throw new InvalidKeyException("Excess data detected.");
+
+ //AsnAlgorithmId oid = (AsnAlgorithmId)seq.get(0);
+ AsnBitString bits = (AsnBitString)seq.get(1);
+ return bits.toByteArray();
+
+ } catch(ClassCastException e) {
+ throw new InvalidKeyException("Unexpected ASN.1 type detected.");
} catch (IOException e) {
throw new InvalidKeyException("Could not parse encoded key data");
}
@@ -1000,7 +960,8 @@
*
* @param key An X509Key object, from which to extract the public key data
* @return the key "fingerprint"
- * @exception InvalidKeyException the X509Key is invalid (i.e. incorrectly formatted)
+ * @exception InvalidKeyException the X509Key is invalid
+ * (i.e. incorrectly formatted)
*/
public static byte[] fingerprint(PublicKey key)
throws InvalidKeyException
@@ -1019,36 +980,34 @@
*
* @param data The X509 signature packet containing the raw signature
* @return the raw signature data
- * @exception SignatureException the signature packet is invalid (i.e. incorrectly formatted)
+ * @exception SignatureException the signature packet is invalid
+ * (i.e. incorrectly formatted)
*/
public static byte[] decodeSignature(byte[] data)
throws SignatureException
{
- //
- // An X509 signature is defined as:
- //
- // SEQUENCE {
- // AlgorithmId id
- // BitString signature
- // }
- //
+ System.out.println("Automobiel!");
+ /*
+ * An X509 signature is defined as:
+ *
+ * SEQUENCE
+ * AlgorithmId id
+ * BitString signature
+ */
+
try {
- DerValue dv = new DerValue(data);
-
- // Ensure we have a SEQUENCE
- if (dv.tag != DerValue.tag_Sequence)
- throw new SignatureException("invalid key format");
-
- /* AlgorithmId algorithmId = */
- AlgorithmId.parse(dv.data.getDerValue());
- byte[] sig = dv.data.getBitString();
-
- // Ensure no excess data
- if (dv.data.available() != 0)
- throw new SignatureException("excess raw key data");
-
- return sig;
- } catch (IOException e) {
+ AsnInputStream is = new AsnInputStream(data);
+ AsnSequence seq = (AsnSequence)is.read();
+ if( (is.available()!=0) || (seq.size() != 2) )
+ throw new SignatureException("Excess data detected.");
+
+ //AsnAlgorithmId oid = (AsnAlgorithmId)seq.get(0);
+ AsnBitString bits = (AsnBitString)seq.get(1);
+ return bits.toByteArray();
+
+ } catch(ClassCastException e) {
+ throw new SignatureException("Unexpected ASN.1 type detected.");
+ } catch(IOException e) {
throw new SignatureException("Could not parse encoded signature");
}
}
@@ -1072,21 +1031,21 @@
//
try {
- DerOutputStream dos = new DerOutputStream();
- (AlgorithmId.get("MD5withRSA")).emit(dos);
- dos.putBitString(sig);
- return new DerValue(DerValue.tag_Sequence,
- dos.toByteArray()).toByteArray();
- // return dos.toByteArray();
- } catch (NoSuchAlgorithmException e) {
- throw new ProviderException("Algorithm not found: "+e.getMessage());
+ int[] OID_MD5_WITH_RSA = { 1, 2, 840, 113549, 1, 1, 4 };
+ AsnSequence seq = new AsnSequence(
+ new AsnAlgorithmId( new AsnObjectId(OID_MD5_WITH_RSA) ),
+ new AsnBitString(sig) );
+
+ AsnOutputStream os = new AsnOutputStream();
+ os.write(seq);
+ return os.toByteArray();
+
} catch (IOException e) {
throw new InternalError("Unexpected IOException");
}
}
-
////////////////////////////////////////////////////////////////////////
// Methods for encoding and decoding public keys
////////////////////////////////////////////////////////////////////////
@@ -1096,39 +1055,40 @@
*
* @param data The encoded data containing the public key
* @return a PublicKey object, derived from the data
- * @exception InvalidKeyException the encoded public key is invalid (i.e. incorrectly formatted)
+ * @exception InvalidKeyException the encoded public key is invalid
+ * (i.e. incorrectly formatted)
*/
public static PublicKey decodePublicKey(byte[] data)
throws InvalidKeyException
{
- // An RSA public key is defined as:
- //
- // SEQUENCE {
- // Integer Modulus
- // Integer Exponent
- // }
- //
+ /*
+ * An RSA public key is defined as:
+ *
+ * SEQUENCE {
+ * INTEGER Modulus
+ * INTEGER Exponent
+ */
try {
- DerValue dv = new DerValue(data);
-
- // Ensure we have a SEQUENCE
- if (dv.tag != DerValue.tag_Sequence)
- throw new InvalidKeyException("invalid key format");
-
- java.math.BigInteger n = dv.data.getInteger().toBigInteger();
- java.math.BigInteger e = dv.data.getInteger().toBigInteger();
-
- // Ensure no excess data
- if (dv.data.available() != 0)
- throw new InvalidKeyException("excess raw key data");
-
- // Convert from a Cryptix key
- return (PublicKey)new cryptix.provider.rsa.RawRSAPublicKey(n, e);
- } catch (IOException e) {
- throw new InvalidKeyException("Could not parse encoded key data");
+ AsnInputStream is = new AsnInputStream(data);
+ AsnSequence seq = (AsnSequence)is.read();
+ if( (is.available()!=0) || (seq.size() != 2) )
+ throw new InvalidKeyException("Excess data detected.");
+
+ AsnInteger n = (AsnInteger)seq.get(0);
+ AsnInteger e = (AsnInteger)seq.get(1);
+
+ return new RawRSAPublicKey(
+ n.toBigInteger(),
+ e.toBigInteger());
+
+ } catch(ClassCastException e) {
+ throw new InvalidKeyException("Unexpected ASN.1 type detected.");
+ } catch(IOException e) {
+ throw new InvalidKeyException("Could not parse encoded key data.");
}
}
+
/**
* Encode an RSA PublicKey object
*
@@ -1137,26 +1097,29 @@
*/
public static byte[] encodePublicKey(PublicKey key)
{
- // An RSA public key is defined as:
- //
- // SEQUENCE {
- // Integer Modulus
- // Integer Exponent
- // }
- //
+ /*
+ * An RSA public key is defined as:
+ *
+ * SEQUENCE {
+ * INTEGER Modulus
+ * INTEGER Exponent
+ * }
+ */
- // Convert to a Cryptix key
- if (!(key instanceof cryptix.provider.rsa.RawRSAPublicKey))
+ if( !(key instanceof RawRSAPublicKey) )
throw new InternalError("Unexpected object");
- cryptix.provider.rsa.RawRSAPublicKey pub;
- pub = (cryptix.provider.rsa.RawRSAPublicKey)key;
+
+ RawRSAPublicKey pub = (RawRSAPublicKey)key;
try {
- DerOutputStream dos = new DerOutputStream();
- dos.putInteger(new BigInt(pub.getModulus()));
- dos.putInteger(new BigInt(pub.getExponent()));
- return new DerValue(DerValue.tag_Sequence,
- dos.toByteArray()).toByteArray();
+ AsnSequence seq = new AsnSequence(
+ new AsnInteger( pub.getModulus() ),
+ new AsnInteger( pub.getExponent() ) );
+
+ AsnOutputStream dos = new AsnOutputStream();
+ dos.write(seq);
+ return dos.toByteArray();
+
} catch (IOException e) {
throw new InternalError("Unexpected IOException");
}
@@ -1172,59 +1135,62 @@
*
* @param data The encoded data containing the private key
* @return a PrivateKey object, derived from the data
- * @exception InvalidKeyException the encoded private key is invalid (i.e. incorrectly formatted)
+ * @exception InvalidKeyException the encoded private key is invalid
+ * (i.e. incorrectly formatted)
*/
public static PrivateKey decodePrivateKey(byte[] data)
- throws InvalidKeyException
+ throws InvalidKeyException
{
- // An RSA private key is defined as:
- //
- // SEQUENCE {
- // Integer N
- // Integer E
- // Integer D
- // Integer P
- // Integer Q
- // Integer DMP1
- // Integer DMQ1
- // Integer U (IQMP)
- // }
- //
+ /*
+ * An RSA private key is defined as:
+ *
+ * SEQUENCE
+ * INTEGER N
+ * INTEGER E
+ * INTEGER D
+ * INTEGER P
+ * INTEGER Q
+ * INTEGER DMP1
+ * INTEGER DMQ1
+ * INTEGER U (IQMP)
+ */
try
{
- DerValue dv = new DerValue(data);
-
- // Ensure we have a SEQUENCE
- if (dv.tag != DerValue.tag_Sequence)
- throw new InvalidKeyException("invalid key format");
-
- java.math.BigInteger n = dv.data.getInteger().toBigInteger();
- java.math.BigInteger e = dv.data.getInteger().toBigInteger();
- java.math.BigInteger d = dv.data.getInteger().toBigInteger();
- java.math.BigInteger p = dv.data.getInteger().toBigInteger();
- java.math.BigInteger q = dv.data.getInteger().toBigInteger();
- java.math.BigInteger dmp1 = dv.data.getInteger().toBigInteger();
- java.math.BigInteger dmq1 = dv.data.getInteger().toBigInteger();
- java.math.BigInteger u = dv.data.getInteger().toBigInteger();
-
- // Ensure no excess data
- if (dv.data.available() != 0)
- throw new InvalidKeyException("excess raw key data");
-
- // Convert from a Cryptix key
- PrivateKey k;
- k = new cryptix.provider.rsa.RawRSAPrivateKey(d, p, q, u);
-
- // Note - Cryptix RSA private key constructor doesn't bother
- // with values n, e, dmp1 or dmq1
+ AsnInputStream is = new AsnInputStream(data);
+ AsnSequence seq = (AsnSequence)is.read();
+ if( (is.available()!=0) || (seq.size() != 8) )
+ throw new InvalidKeyException("Excess data detected.");
+
+ /*
+ * NOTE: not all of these are used but the casts make sure
+ * that all ASN objects are indeed INTEGERS.
+ */
+ AsnInteger n = (AsnInteger)seq.get(0);
+ AsnInteger e = (AsnInteger)seq.get(1);
+ AsnInteger d = (AsnInteger)seq.get(2);
+ AsnInteger p = (AsnInteger)seq.get(3);
+ AsnInteger q = (AsnInteger)seq.get(4);
+ AsnInteger dmp1 = (AsnInteger)seq.get(5);
+ AsnInteger dmq1 = (AsnInteger)seq.get(6);
+ AsnInteger u = (AsnInteger)seq.get(7);
+
+ /*
+ * Convert to a Cryptix key.
+ *
+ * Note: Cryptix RSA private key constructor doesn't bother
+ * with values n, e, dmp1 or dmq1.
+ */
+ return new RawRSAPrivateKey(
+ d.toBigInteger(),
+ p.toBigInteger(),
+ q.toBigInteger(),
+ u.toBigInteger() );
- return k;
- }
- catch (IOException e)
- {
- e.printStackTrace();
- throw new InvalidKeyException("Could not parse encoded key data");
+ } catch(ClassCastException e) {
+ throw new InvalidKeyException("Unexpected ASN.1 type detected.");
+ } catch (IOException e) {
+ throw new InvalidKeyException("Could not parse encoded key data.");
}
}
@@ -1264,6 +1230,7 @@
// e, dmp1, dmq1 and iqmp)
//
BigInteger one = BigInteger.valueOf(1L);
+ BigInteger m = priv.getModulus();
BigInteger p = priv.getP();
BigInteger q = priv.getQ();
BigInteger d = priv.getExponent();
@@ -1272,18 +1239,21 @@
BigInteger dmp1 = d.mod(p.subtract(one));
BigInteger dmq1 = d.mod(q.subtract(one));
- DerOutputStream dos = new DerOutputStream();
- dos.putInteger(new BigInt(priv.getModulus()));
- dos.putInteger(new BigInt(e));
- dos.putInteger(new BigInt(d));
- dos.putInteger(new BigInt(p));
- dos.putInteger(new BigInt(q));
- dos.putInteger(new BigInt(dmp1));
- dos.putInteger(new BigInt(dmq1));
- dos.putInteger(new BigInt(priv.getInverseOfQModP()));
+ AsnInteger[] vals = new AsnInteger[8];
+ vals[0] = new AsnInteger(m);
+ vals[1] = new AsnInteger(e);
+ vals[2] = new AsnInteger(d);
+ vals[3] = new AsnInteger(p);
+ vals[4] = new AsnInteger(q);
+ vals[5] = new AsnInteger(dmp1);
+ vals[6] = new AsnInteger(dmq1);
+ vals[7] = new AsnInteger( priv.getInverseOfQModP() );
+ AsnSequence seq = new AsnSequence(vals);
+
+ AsnOutputStream os = new AsnOutputStream();
+ os.write(seq);
+ return os.toByteArray();
- return new DerValue(DerValue.tag_Sequence,
- dos.toByteArray()).toByteArray();
} catch (IOException e) {
throw new InternalError("Unexpected IOException");
}
1.1 java/webfunds/x509/AsnAlgorithmId.java
Index: AsnAlgorithmId.java
===================================================================
/* $Id: AsnAlgorithmId.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.IOException;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class AsnAlgorithmId extends AsnObject
{
private final AsnSequence val;
public AsnAlgorithmId(AsnInputStream is) throws IOException {
super(AsnObject.TAG_SEQUENCE);
this.val = new AsnSequence(is);
}
public AsnAlgorithmId(AsnObjectId oid) {
super(AsnObject.TAG_SEQUENCE);
this.val = new AsnSequence(oid, new AsnNull());
}
/** Write out payload. */
protected void encodePayload(AsnOutputStream os) throws IOException {
this.val.encodePayload(os);
}
protected int getEncodedLengthOfPayload(AsnOutputStream os) {
return this.val.getEncodedLengthOfPayload(os);
}
}
1.1 java/webfunds/x509/AsnBitString.java
Index: AsnBitString.java
===================================================================
/* $Id: AsnBitString.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.IOException;
import java.math.BigInteger;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class AsnBitString extends AsnObject
{
private final byte[] val;
/*package*/ AsnBitString(AsnInputStream is) throws IOException {
super(AsnObject.TAG_BITSTRING);
int len = is.readLength() - 1; // subtract 1 'unused' byte
if(len < 0)
throw new DerException("Negative length.");
// verify multiple of 8 bits
byte unused = is.readByte();
if(unused != 0)
throw new DerException("Length not a multiple of 8.");
this.val = is.readBytes(len);
}
public AsnBitString(byte[] value) {
super(AsnObject.TAG_BITSTRING);
this.val = (byte[])(value.clone());
}
public byte[] toByteArray() {
return (byte[])this.val.clone();
}
/** Write out payload. */
protected void encodePayload(AsnOutputStream os) throws IOException {
os.writeByte((byte)0x00); // no. of unsed bits (always 0)
os.writeBytes(this.val);
}
protected int getEncodedLengthOfPayload(AsnOutputStream os) {
return this.val.length+1; // plus 1 byte for 'unused bits field'
}
}
1.1 java/webfunds/x509/AsnInputStream.java
Index: AsnInputStream.java
===================================================================
/* $Id: AsnInputStream.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.IOException;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class AsnInputStream {
// Instance variables
//............................................................................
private final InputStream is;
//............................................................................
public AsnInputStream(byte[] data) {
this.is = new ByteArrayInputStream(data);
}
public AsnInputStream(InputStream is) {
this.is = is;
}
//............................................................................
public AsnObject read() throws IOException {
int tag = this.is.read();
if(tag == -1)
throw new IOException("End of stream.");
System.out.println("tag: " +tag);
switch(tag) {
case AsnObject.TAG_OBJECT_ID:
return new AsnObjectId(this);
case AsnObject.TAG_BITSTRING:
return new AsnBitString(this);
case AsnObject.TAG_INTEGER:
return new AsnInteger(this);
case AsnObject.TAG_NULL:
return new AsnNull(this);
case AsnObject.TAG_SEQUENCE:
return new AsnSequence(this);
default:
throw new IOException("Unknown ASN object type.");
}
}
//............................................................................
public int available() throws IOException {
return this.is.available();
}
/*package*/ int readLength() throws IOException {
int b = this.is.read();
if( b == -1 )
throw new IOException("Unexpected end of stream.");
// short form
if( b <= 127 )
return b;
// strip of high bit
b = b&0x7F;
// long form
if( b > 4 )
throw new IOException("Length too big.");
int t, res = 0;
while( b-- > 0 ) {
if( (t=this.is.read()) == -1 )
throw new IOException("Unexpected end of stream.");
res = (res<<8) | t;
}
if( res < 0 )
throw new IOException("Negative length.");
return res;
}
/*package*/ byte readByte() throws IOException {
return this.readBytes(1)[0];
}
/*package*/ byte[] readBytes(int todo) throws IOException {
byte[] res = new byte[todo];
int done, off = 0;
while( todo > 0 ) {
if( (done = this.is.read(res, off, todo)) == -1 )
throw new IOException("EOF");
todo -= done;
off += done;
}
return res;
}
/*package*/ AsnInputStream getSubStream(int len) {
return new AsnInputStream( new SubInputStream(this.is, len) );
}
}
1.1 java/webfunds/x509/AsnInteger.java
Index: AsnInteger.java
===================================================================
/* $Id: AsnInteger.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.IOException;
import java.math.BigInteger;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class AsnInteger extends AsnObject
{
//............................................................................
private final BigInteger val;
//............................................................................
/*package*/ AsnInteger(AsnInputStream is) throws IOException {
super(AsnObject.TAG_INTEGER);
int len = is.readLength();
byte[] data = is.readBytes(len);
this.val = new BigInteger(data);
}
public AsnInteger(BigInteger value) {
super(AsnObject.TAG_INTEGER);
this.val = value;
}
//............................................................................
public BigInteger toBigInteger() {
return this.val;
}
//............................................................................
/** Write out payload. */
protected void encodePayload(AsnOutputStream os) throws IOException {
os.writeBytes( this.val.toByteArray() );
}
/**
* Returns no. of bytes encodePayload will write out when called on
* the given AsnOutputStream.
*/
protected int getEncodedLengthOfPayload(AsnOutputStream os) {
return this.val.toByteArray().length;
}
}
1.1 java/webfunds/x509/AsnNull.java
Index: AsnNull.java
===================================================================
/* $Id: AsnNull.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.IOException;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class AsnNull extends AsnObject
{
public AsnNull(AsnInputStream is) throws IOException {
super(AsnObject.TAG_NULL);
int len = is.readLength();
}
public AsnNull() {
super(AsnObject.TAG_NULL);
}
/** Write out payload. */
protected void encodePayload(AsnOutputStream os) throws IOException {
}
protected int getEncodedLengthOfPayload(AsnOutputStream os) {
return 0;
}
}
1.1 java/webfunds/x509/AsnObject.java
Index: AsnObject.java
===================================================================
/* $Id: AsnObject.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.IOException;
/**
* Base class of all ASN objects. Provides type safety and common functionality.
* AsnObjects can encode themselves to AsnOutputStreams. All AsnObjects are
* immutable.
*
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@cryptix.org)
*/
public abstract class AsnObject {
/*package*/ static final byte
TAG_MASK = 0x1F,
TAG_INTEGER = 0x02,
TAG_BITSTRING = 0x03,
TAG_NULL = 0x05,
TAG_OBJECT_ID = 0x06,
TAG_SEQUENCE = 0x10 | 0x20;
private final byte tag;
protected AsnObject(byte tag) {
this.tag = tag;
}
/*package*/ final void encode(AsnOutputStream os) throws IOException {
os.writeType( this.tag );
os.writeLength( this.getEncodedLengthOfPayload(os) );
this.encodePayload(os);
}
/*package*/ final int getEncodedLength(AsnOutputStream os) {
int len = this.getEncodedLengthOfPayload(os);
len += os.getLengthOfLength(len);
len += 1; // tag
return len;
}
/**
* Write out this object's payload. Called upon by AsnObject.encode(...)
* after it has written the type tag and length field.
*/
protected abstract void encodePayload(AsnOutputStream os)
throws IOException;
/**
* Returns no. of bytes encodePayload will write out when called on
* the given AsnOutputStream.
*
* This is used by constructed types to determine the aggregrated
* length of their components.
*
* The stream argument is included for future proofing. Different
* streams may support different encodings for the length field.
* This obviously doesn't apply to DER :-)
*/
protected abstract int getEncodedLengthOfPayload(AsnOutputStream os);
}
1.1 java/webfunds/x509/AsnObjectId.java
Index: AsnObjectId.java
===================================================================
/* $Id: AsnObjectId.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.IOException;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class AsnObjectId extends AsnObject
{
private final int[] components;
public AsnObjectId(AsnInputStream is) throws IOException {
super(AsnObject.TAG_OBJECT_ID);
int len = is.readLength();
if( len < 2 )
throw new IOException("Invalid OBJECT_ID.");
is.readBytes(len);
this.components = null; // XXX: but this makes WebFunds work :-)
}
public AsnObjectId(int[] components) {
super(AsnObject.TAG_OBJECT_ID);
if( components.length < 2 )
throw new IllegalArgumentException("Less than 2 components.");
this.components = (int[])components.clone();
}
/** Write out payload. */
protected void encodePayload(AsnOutputStream os) throws IOException {
os.writeByte( (byte)(40*components[0] + components[1]) );
for(int i=2; i<components.length; i++)
this.writeComponent( os, components[i] );
}
/**
* Returns no. of bytes encodePayload will write out when called on
* the given AsnOutputStream. Payload length does NOT include length.
*/
protected int getEncodedLengthOfPayload(AsnOutputStream os) {
int len = 1; // first two are special
for(int i=2; i<this.components.length; i++)
len += getEncodedComponentLen( this.components[i] );
return len;
}
private void writeComponent(AsnOutputStream os, int c) throws IOException {
int len = getEncodedComponentLen(c);
for(int i=len-1; i>0; i--)
os.writeByte( (byte)((c>>>i*7) | 0x80) );
os.writeByte( (byte)(c&0x7F) );
}
private static int getEncodedComponentLen(int c) {
if( c < 0 )
throw new IllegalArgumentException("c: < 0");
else if( c <= 0x7F )
return 1;
else if( c <= 0x3FFF )
return 2;
else if( c <= 0x1FFFFF )
return 3;
else if( c <= 0xFFFFFFF )
return 4;
else
return 5;
}
}
1.1 java/webfunds/x509/AsnOutputStream.java
Index: AsnOutputStream.java
===================================================================
/* $Id: AsnOutputStream.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class AsnOutputStream {
// Instance variables
//............................................................................
private final OutputStream os;
// Constructors and java.lang.Object overrides
//............................................................................
public AsnOutputStream() {
this.os = new ByteArrayOutputStream();
}
public AsnOutputStream(OutputStream os) {
this.os = os;
}
// Public interface
//............................................................................
public void close() throws IOException {
this.os.flush();
this.os.close();
}
public void flush() throws IOException {
this.os.flush();
}
public void write(AsnObject obj) throws IOException {
obj.encode(this);
}
public byte[] toByteArray() {
if( !(this.os instanceof ByteArrayOutputStream) )
throw new IllegalStateException("Not layered on BAOS.");
ByteArrayOutputStream baos = (ByteArrayOutputStream)this.os;
return baos.toByteArray();
}
// AsnObject.encode(...) callbacks and helpers
//............................................................................
/**
* Returns the number of bytes writeLength() will write when called
* with the given 'len'.
*/
/*package*/ int getLengthOfLength(int len) {
if( len <= 127 )
return 1;
else if( len <= 0xFF )
return 2;
else if( len <= 0xFFFF )
return 3;
else if( len <= 0xFFFFFF )
return 4;
else
return 5;
}
/*package*/ void writeByte(byte b) throws IOException {
this.os.write(b&0xFF);
}
/*package*/ void writeBytes(byte[] data) throws IOException {
this.os.write(data);
}
/*package*/ void writeLength(int len) throws IOException {
if(len < 0 )
throw new IllegalArgumentException("len: < 0");
// shortcut for short form
if(len <= 127) {
this.os.write( (char)len );
return;
}
// long form
int lenOfLenData = getLengthOfLength(len) - 1;
this.os.write( (byte)(lenOfLenData | 0x80) );
while( lenOfLenData-- > 0 )
this.os.write( (byte)(len >>> (lenOfLenData*8)) );
}
/*package*/ void writeType(byte type) throws IOException {
this.os.write(type);
}
}
1.1 java/webfunds/x509/AsnSequence.java
Index: AsnSequence.java
===================================================================
/* $Id: AsnSequence.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.IOException;
import java.util.Vector;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class AsnSequence extends AsnObject
{
private final AsnObject[] vals;
/*package*/ AsnSequence(AsnInputStream is) throws IOException {
super(AsnObject.TAG_SEQUENCE);
int len = is.readLength();
System.out.println(" " + len);
AsnInputStream sub_is = is.getSubStream( len );
Vector vec = new Vector(3);
while( sub_is.available() > 0 ) {
System.out.println(" yeah!");
vec.addElement( sub_is.read() );
}
vec.copyInto(this.vals = new AsnObject[ vec.size() ]);
}
public AsnSequence(AsnObject[] vals) {
super(AsnObject.TAG_SEQUENCE);
this.vals = (AsnObject[])vals.clone();
}
public AsnSequence(AsnObject a, AsnObject b) {
super(AsnObject.TAG_SEQUENCE);
AsnObject[] objs = new AsnObject[2];
objs[0] = a;
objs[1] = b;
this.vals = objs;
}
public AsnObject get(int index) {
return this.vals[index];
}
public int size() {
return this.vals.length;
}
/** Write out payload. */
protected void encodePayload(AsnOutputStream os) throws IOException {
for(int i=0; i<this.vals.length; i++)
os.write(this.vals[i]);
}
protected int getEncodedLengthOfPayload(AsnOutputStream os) {
int len = 0;
for(int i=0; i<this.vals.length; i++)
len += this.vals[i].getEncodedLength(os);
return len;
}
}
1.1 java/webfunds/x509/DerException.java
Index: DerException.java
===================================================================
/* $Id: DerException.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.IOException;
/**
* Thrown for all DER encoding and decoding errors.
*
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class DerException extends IOException {
public DerException(String msg) {
super(msg);
}
}
1.1 java/webfunds/x509/SubInputStream.java
Index: SubInputStream.java
===================================================================
/* $Id: SubInputStream.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.InputStream;
import java.io.IOException;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class SubInputStream extends InputStream {
// Instance variables
//............................................................................
private int len;
private final InputStream is;
//............................................................................
public SubInputStream(InputStream is, int len) {
if( len < 0 )
throw new IllegalArgumentException("len: < 0");
this.is = is;
this.len = len;
}
//............................................................................
public int available() throws IOException {
return (this.len > 0) ? this.is.available() : 0;
}
public int read() throws IOException {
return (this.len-- <= 0) ? -1 : this.is.read();
}
}
1.1 java/webfunds/x509/Test.java
Index: Test.java
===================================================================
/* $Id: Test.java,v 1.1 2000/07/19 02:35:41 gelderen Exp $
*
* Copyright (c) 2000 Systemics Inc. on behalf of
* The WebFunds Development Team. All rights reserved.
*/
package webfunds.x509;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import webfunds.utils.Hex;
/**
* @version $Revision: 1.1 $
* @author Jeroen C. van Gelderen (gelderen@webfunds.org)
*/
public final class Test {
public static void main(String[] argv) {
testBitString();
testInteger();
testSequence();
testObjectId();
}
private static void test() {
try {
byte[] sig = new byte[128];
for(int i=0; i<sig.length; i++) sig[i] = (byte)170;
int[] OID_MD5_WITH_RSA = { 1, 2, 840, 113549, 1, 1, 4 };
AsnSequence seq = new AsnSequence(
new AsnAlgorithmId( new AsnObjectId(OID_MD5_WITH_RSA) ),
new AsnBitString(sig) );
AsnOutputStream os = new AsnOutputStream();
os.write(seq);
byte[] result = os.toByteArray();
System.out.println( "N sigbytes:" + Hex.data2hex(result) );
} catch(IOException e) {
e.printStackTrace();
}
}
private static void testInteger() {
try {
byte[] INT_0 = { 0x02, 0x01, 0x00 };
AsnInteger i = new AsnInteger(BigInteger.valueOf(0));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
AsnOutputStream dos = new AsnOutputStream(baos);
dos.write(i);
dos.close();
byte[] encoded = baos.toByteArray();
System.out.println( Hex.data2hex(encoded) );
AsnInputStream is = new AsnInputStream(encoded);
AsnInteger res = (AsnInteger)is.read();
System.out.println( res.toBigInteger() );
} catch(IOException e) {
e.printStackTrace();
}
}
private static void testBitString() {
try {
byte[] BS = { 0x6e, 0x5d, (byte)0xc0 };
AsnBitString bs = new AsnBitString(BS);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
AsnOutputStream dos = new AsnOutputStream(baos);
dos.write(bs);
dos.close();
byte[] encoded = baos.toByteArray();
System.out.println( Hex.data2hex(encoded) );
AsnInputStream is = new AsnInputStream(encoded);
AsnBitString res = (AsnBitString)is.read();
System.out.println( Hex.data2hex(res.toByteArray()) );
} catch(IOException e) {
e.printStackTrace();
}
}
private static void testObjectId() {
try {
int[] vals = { 1, 2, 840, 113549 };
AsnObjectId oid = new AsnObjectId(vals);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
AsnOutputStream dos = new AsnOutputStream(baos);
dos.write(oid);
dos.close();
System.out.println(
webfunds.utils.Hex.data2hex(baos.toByteArray()) );
System.out.println(oid.getEncodedLength(dos));
} catch(IOException e) {
e.printStackTrace();
}
}
private static void testSequence() {
try {
byte[] BS = { 0x6e, 0x5d, (byte)0xc0 };
AsnBitString bs = new AsnBitString(BS);
bs = new AsnBitString(new byte[300]);
AsnInteger i = new AsnInteger(BigInteger.valueOf(-129));
AsnObject[] objs = new AsnObject[3];
objs[0] = bs;
objs[1] = i;
objs[2] = i;
AsnSequence t = new AsnSequence(objs);
objs[0] = t;
objs[1] = i;
objs[2] = bs;
AsnSequence seq = new AsnSequence(objs);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
AsnOutputStream dos = new AsnOutputStream(baos);
dos.write(seq);
dos.close();
byte[] encoded = baos.toByteArray();
System.out.println( Hex.data2hex(encoded) );
AsnInputStream is = new AsnInputStream(encoded);
AsnSequence res = (AsnSequence)is.read();
System.out.println( (res) );
baos = new ByteArrayOutputStream();
dos = new AsnOutputStream(baos);
dos.write(res);
dos.close();
byte[] encoded2 = baos.toByteArray();
System.out.println( Hex.data2hex(encoded2) );
if(encoded.length != encoded2.length)
throw new RuntimeException();
for(int j=0; j<encoded.length; j++)
if(encoded[j] != encoded2[j])
throw new RuntimeException();
} catch(IOException e) {
e.printStackTrace();
}
}
}