Removed dependency on bouncycastle. Now uses a undocumented method JDK method for signing certificates however. The same method is as used by keytool.
This commit is contained in:
@ -1,29 +1,25 @@
|
||||
package net.i2p.i2pcontrol.security;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStore.Builder;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
import java.security.SignatureException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
@ -33,36 +29,24 @@ import java.security.cert.X509Certificate;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.DERBMPString;
|
||||
import org.bouncycastle.asn1.DERBitString;
|
||||
import org.bouncycastle.asn1.DERNull;
|
||||
import org.bouncycastle.asn1.DERObjectIdentifier;
|
||||
import org.bouncycastle.asn1.DEROutputStream;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.jce.PKCS10CertificationRequest;
|
||||
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.jce.provider.X509CertificateObject;
|
||||
import org.bouncycastle.x509.X509Util;
|
||||
import org.bouncycastle.x509.X509V3CertificateGenerator;
|
||||
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
|
||||
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
|
||||
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
|
||||
import org.bouncycastle.asn1.x509.*;
|
||||
import org.bouncycastle.crypto.AsymmetricBlockCipher;
|
||||
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||
import org.bouncycastle.crypto.digests.SHA1Digest;
|
||||
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
|
||||
import org.bouncycastle.crypto.engines.RSAEngine;
|
||||
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
|
||||
import sun.security.util.ObjectIdentifier;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.x509.CertificateAlgorithmId;
|
||||
import sun.security.x509.CertificateIssuerName;
|
||||
import sun.security.x509.CertificateSerialNumber;
|
||||
import sun.security.x509.CertificateSubjectName;
|
||||
import sun.security.x509.CertificateValidity;
|
||||
import sun.security.x509.CertificateVersion;
|
||||
import sun.security.x509.CertificateX509Key;
|
||||
import sun.security.x509.X500Name;
|
||||
import sun.security.x509.X509CertImpl;
|
||||
import sun.security.x509.X509CertInfo;
|
||||
|
||||
public class KeyStoreFactory {
|
||||
public static final String DEFAULT_SIGNATURE_ALGORITHM = "SHA1withRSA";
|
||||
public static final ObjectIdentifier DEFAULT_CERTIFICATE_ALGORITHM = AlgorithmId.sha512WithRSAEncryption_oid;
|
||||
public static final String DEFAULT_CERTIFICATE_ALGORITHM_STRING = "SHA512WithRSA";
|
||||
public static final String DEFAULT_KEYSTORE_TYPE = "JKS";
|
||||
public static final String DEFAULT_KEYSTORE_PROVIDER = "SUN";
|
||||
public static final String DEFAULT_KEYSTORE_LOCATION = "key.store";
|
||||
@ -70,9 +54,6 @@ public class KeyStoreFactory {
|
||||
public static final String DEFAULT_KEYSTORE_ALGORITHM = "SunX509";
|
||||
private static KeyStore _keystore = null;
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
public static KeyPair generateKeyPair() {
|
||||
KeyPairGenerator keyGen;
|
||||
@ -82,9 +63,6 @@ public class KeyStoreFactory {
|
||||
keyGen.initialize(1024, random);
|
||||
|
||||
KeyPair pair = keyGen.generateKeyPair();
|
||||
PrivateKey privKey = pair.getPrivate();
|
||||
PublicKey pubKey = pair.getPublic();
|
||||
|
||||
return pair;
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
@ -95,108 +73,60 @@ public class KeyStoreFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static X509Certificate generateCACertificate(String caName, KeyPair keyPair, int validNbrDays){
|
||||
Date startDate = new Date(System.currentTimeMillis()); // time from which certificate is valid
|
||||
|
||||
Calendar expiry = Calendar.getInstance();
|
||||
expiry.add(Calendar.DAY_OF_YEAR, validNbrDays);
|
||||
Date expiryDate = expiry.getTime(); // time after which certificate is not valid
|
||||
|
||||
byte[] bigNum = new byte[1024];
|
||||
(new SecureRandom()).nextBytes(bigNum);
|
||||
BigInteger serialNumber = new BigInteger(bigNum);
|
||||
serialNumber = serialNumber.abs(); // serial number for certificate
|
||||
|
||||
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
|
||||
X500Principal dname = new X500Principal("CN=" + caName);
|
||||
|
||||
certGen.setSerialNumber(serialNumber);
|
||||
certGen.setIssuerDN(dname);
|
||||
certGen.setNotBefore(startDate);
|
||||
certGen.setNotAfter(expiryDate);
|
||||
certGen.setSubjectDN(dname);
|
||||
certGen.setPublicKey(keyPair.getPublic());
|
||||
certGen.setSignatureAlgorithm(DEFAULT_SIGNATURE_ALGORITHM);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a self-signed X.509 Certificate
|
||||
* @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
|
||||
* @param pair the KeyPair
|
||||
* @param days how many days from now the Certificate is valid for
|
||||
* @param algorithm the signing algorithm, eg "SHA1withRSA"
|
||||
*/
|
||||
static X509Certificate generateCACertificate(String dn, KeyPair pair, int days) {
|
||||
try {
|
||||
X509Certificate cert = certGen.generate(keyPair.getPrivate(), "BC"); // BC == BouncyCastle
|
||||
PrivateKey privkey = pair.getPrivate();
|
||||
X509CertInfo info = new X509CertInfo();
|
||||
Date from = new Date();
|
||||
Date to = new Date(from.getTime() + days * 86400000l);
|
||||
CertificateValidity interval = new CertificateValidity(from, to);
|
||||
BigInteger sn = new BigInteger(64, new SecureRandom());
|
||||
X500Name owner = new X500Name("CN=" + dn);
|
||||
|
||||
info.set(X509CertInfo.VALIDITY, interval);
|
||||
info.set(X509CertInfo.SERIAL_NUMBER,
|
||||
new CertificateSerialNumber(sn));
|
||||
info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
|
||||
info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
|
||||
info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
|
||||
info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
|
||||
AlgorithmId algo = new AlgorithmId(DEFAULT_CERTIFICATE_ALGORITHM);
|
||||
info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
|
||||
|
||||
// Sign the cert to identify the algorithm that's used.
|
||||
X509CertImpl cert = new X509CertImpl(info);
|
||||
cert.sign(privkey, DEFAULT_CERTIFICATE_ALGORITHM_STRING);
|
||||
|
||||
// Update the algorith, and resign.
|
||||
algo = (AlgorithmId) cert.get(X509CertImpl.SIG_ALG);
|
||||
info.set(CertificateAlgorithmId.NAME + "."
|
||||
+ CertificateAlgorithmId.ALGORITHM, algo);
|
||||
cert = new X509CertImpl(info);
|
||||
cert.sign(privkey, DEFAULT_CERTIFICATE_ALGORITHM_STRING);
|
||||
return cert;
|
||||
} catch (CertificateEncodingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CertificateException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeyException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IllegalStateException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchProviderException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchProviderException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SignatureException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} // note: private key of CA
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static X509Certificate generateCertificate(X509Certificate caCert, PrivateKey caPrivKey, String certName, KeyPair certKeyPair, int validNbrDays) {
|
||||
|
||||
Date startDate = new Date(System.currentTimeMillis()); // time from which certificate is valid
|
||||
|
||||
Calendar expiry = Calendar.getInstance();
|
||||
expiry.add(Calendar.DAY_OF_YEAR, validNbrDays);
|
||||
Date expiryDate = expiry.getTime(); // time after which certificate is not valid
|
||||
|
||||
byte[] bigNum = new byte[1024];
|
||||
(new SecureRandom()).nextBytes(bigNum);
|
||||
BigInteger serialNumber = new BigInteger(bigNum);
|
||||
serialNumber = serialNumber.abs(); // serial number for certificate
|
||||
|
||||
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
|
||||
X500Principal subjectName = new X500Principal("CN=" + certName);
|
||||
|
||||
certGen.setSerialNumber(serialNumber);
|
||||
certGen.setIssuerDN(caCert.getSubjectX500Principal());
|
||||
certGen.setNotBefore(startDate);
|
||||
certGen.setNotAfter(expiryDate);
|
||||
certGen.setSubjectDN(subjectName);
|
||||
certGen.setPublicKey(certKeyPair.getPublic());
|
||||
certGen.setSignatureAlgorithm(DEFAULT_SIGNATURE_ALGORITHM);
|
||||
|
||||
try {
|
||||
certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert));
|
||||
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(certKeyPair.getPublic()));
|
||||
X509Certificate cert = certGen.generate(caPrivKey, "BC"); // note: private key of CA
|
||||
return cert;
|
||||
} catch (CertificateParsingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (CertificateEncodingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeyException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IllegalStateException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchProviderException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (SignatureException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static X509Certificate readCert(KeyStore ks, String certAlias, String password){
|
||||
try{
|
||||
@ -291,97 +221,10 @@ public class KeyStoreFactory {
|
||||
}
|
||||
|
||||
|
||||
public static X509CertificateObject signWithCa(X509Certificate x509Issuer, RSAPrivateCrtKeyParameters caKeyParameters, TBSCertificateStructure tbsCert) {
|
||||
|
||||
try{
|
||||
SHA1Digest digester = new SHA1Digest();
|
||||
|
||||
AsymmetricBlockCipher rsa = new PKCS1Encoding(new RSAEngine());
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
DEROutputStream dOut = new DEROutputStream(bOut);
|
||||
|
||||
DERObjectIdentifier sigOID = X509Util.getAlgorithmOID("SHA1WithRSAEncryption");
|
||||
AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(sigOID, new DERNull());
|
||||
|
||||
dOut.writeObject(tbsCert);
|
||||
|
||||
byte[] signature;
|
||||
|
||||
byte[] certBlock = bOut.toByteArray();
|
||||
|
||||
// first create digest
|
||||
digester.update(certBlock, 0, certBlock.length);
|
||||
byte[] hash = new byte[digester.getDigestSize()];
|
||||
digester.doFinal(hash, 0);
|
||||
|
||||
// and sign that
|
||||
rsa.init(true, caKeyParameters);
|
||||
DigestInfo dInfo = new DigestInfo( new AlgorithmIdentifier(X509ObjectIdentifiers.id_SHA1, null), hash);
|
||||
byte[] digest = dInfo.getEncoded(ASN1Encodable.DER);
|
||||
signature = rsa.processBlock(digest, 0, digest.length);
|
||||
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
v.add(tbsCert);
|
||||
v.add(sigAlgId);
|
||||
v.add(new DERBitString(signature));
|
||||
X509CertificateObject clientCert = new X509CertificateObject(new X509CertificateStructure(new DERSequence(v)));
|
||||
|
||||
|
||||
try {
|
||||
clientCert.verify(x509Issuer.getPublicKey());
|
||||
} catch (Exception e) {
|
||||
System.out.println("Failed to verify client certificate against caCert");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return clientCert;
|
||||
|
||||
} catch(IOException e){
|
||||
e.printStackTrace();
|
||||
} catch (InvalidCipherTextException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CertificateParsingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PKCS10CertificationRequest createCSR(String name, KeyPair csrKeyPair){
|
||||
X500Principal subjectName = new X500Principal("CN=" + name);
|
||||
|
||||
try {
|
||||
PKCS10CertificationRequest kpGen = new PKCS10CertificationRequest(
|
||||
DEFAULT_SIGNATURE_ALGORITHM,
|
||||
subjectName,
|
||||
csrKeyPair.getPublic(),
|
||||
null,
|
||||
csrKeyPair.getPrivate());
|
||||
return kpGen;
|
||||
} catch (InvalidKeyException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchProviderException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (SignatureException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static KeyStore writeCACertToKeyStore(KeyStore keyStore, String keyPassword, String alias, PrivateKey caPrivKey, X509Certificate caCert){
|
||||
try {
|
||||
|
||||
PKCS12BagAttributeCarrier bagCert = (X509CertificateObject) caCert;
|
||||
bagCert.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
|
||||
new DERBMPString(alias));
|
||||
|
||||
bagCert.setBagAttribute(
|
||||
PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
|
||||
new SubjectKeyIdentifierStructure(caCert.getPublicKey()));
|
||||
|
||||
|
||||
X509Certificate[] chain = new X509Certificate[1];
|
||||
chain[0] = caCert;
|
||||
@ -403,62 +246,6 @@ public class KeyStoreFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static KeyStore writeCertToStore(KeyStore keyStore, String keyPassword, String alias, PrivateKey userPrivKey, X509Certificate clientCert, X509Certificate caCert){
|
||||
|
||||
try {
|
||||
clientCert.verify(caCert.getPublicKey());
|
||||
} catch (Exception e) {
|
||||
System.out.println("Failed to verify client certificate against caCert");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
PKCS12BagAttributeCarrier bagCert = (X509CertificateObject) clientCert;
|
||||
bagCert.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
|
||||
new DERBMPString(alias));
|
||||
|
||||
bagCert.setBagAttribute(
|
||||
PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
|
||||
new SubjectKeyIdentifierStructure(clientCert.getPublicKey()));
|
||||
|
||||
|
||||
X509Certificate[] chain = new X509Certificate[2];
|
||||
|
||||
// first the client, then the CA certificate
|
||||
chain[0] = clientCert;
|
||||
chain[1] = caCert;
|
||||
|
||||
|
||||
|
||||
keyStore.setKeyEntry(alias, userPrivKey, keyPassword.toCharArray(), chain);
|
||||
keyStore.store(new FileOutputStream(DEFAULT_KEYSTORE_LOCATION), DEFAULT_KEYSTORE_PASSWORD.toCharArray());
|
||||
try {
|
||||
clientCert.verify(chain[1].getPublicKey());
|
||||
} catch (InvalidKeyException e) {
|
||||
System.out.println("Unable to verify clientCert against caCert");
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchProviderException e) {
|
||||
System.out.println("Unable to verify clientCert against caCert");
|
||||
e.printStackTrace();
|
||||
} catch (SignatureException e) {
|
||||
System.out.println("Unable to verify clientCert against caCert");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return keyStore;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CertificateException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static synchronized KeyStore getDefaultKeyStore(){
|
||||
if (_keystore == null){
|
||||
|
@ -43,7 +43,7 @@ import net.i2p.util.Log;
|
||||
* Manage the password storing for I2PControl.
|
||||
*/
|
||||
public class SecurityManager {
|
||||
public final static String CERT_ALIAS = "CA";
|
||||
public final static String CERT_ALIAS = "I2PControl CA";
|
||||
private final static String SSL_PROVIDER = "SunJSSE";
|
||||
private final static String DEFAULT_AUTH_BCRYPT_SALT = "$2a$11$5aOLx2x/8i4fNaitoCSSWu";
|
||||
private final static String DEFAULT_AUTH_PASSWORD = "$2a$11$5aOLx2x/8i4fNaitoCSSWuut2wEl3Hupuca8DCT.NXzvH9fq1pBU.";
|
||||
|
@ -34,7 +34,6 @@ import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.AuthenticateHandler;
|
||||
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.EchoHandler;
|
||||
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.GetRateHandler;
|
||||
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.NetworkSettingHandler;
|
||||
import net.i2p.i2pcontrol.servlets.jsonrpc2handlers.OLDNetworkInfoHandler;
|
||||
|
||||
import com.thetransactioncompany.jsonrpc2.*;
|
||||
import com.thetransactioncompany.jsonrpc2.server.*;
|
||||
|
@ -1,63 +0,0 @@
|
||||
package org.bouncycastle;
|
||||
|
||||
/**
|
||||
* The Bouncy Castle License
|
||||
*
|
||||
* Copyright (c) 2000-2008 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
|
||||
* <p>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
* <p>
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
* <p>
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
public class LICENSE
|
||||
{
|
||||
public static String licenseText =
|
||||
"Copyright (c) 2000-2008 The Legion Of The Bouncy Castle (http://www.bouncycastle.org) "
|
||||
+ System.getProperty("line.separator")
|
||||
+ System.getProperty("line.separator")
|
||||
+ "Permission is hereby granted, free of charge, to any person obtaining a copy of this software "
|
||||
+ System.getProperty("line.separator")
|
||||
+ "and associated documentation files (the \"Software\"), to deal in the Software without restriction, "
|
||||
+ System.getProperty("line.separator")
|
||||
+ "including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, "
|
||||
+ System.getProperty("line.separator")
|
||||
+ "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,"
|
||||
+ System.getProperty("line.separator")
|
||||
+ "subject to the following conditions:"
|
||||
+ System.getProperty("line.separator")
|
||||
+ System.getProperty("line.separator")
|
||||
+ "The above copyright notice and this permission notice shall be included in all copies or substantial"
|
||||
+ System.getProperty("line.separator")
|
||||
+ "portions of the Software."
|
||||
+ System.getProperty("line.separator")
|
||||
+ System.getProperty("line.separator")
|
||||
+ "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,"
|
||||
+ System.getProperty("line.separator")
|
||||
+ "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR"
|
||||
+ System.getProperty("line.separator")
|
||||
+ "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE"
|
||||
+ System.getProperty("line.separator")
|
||||
+ "LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR"
|
||||
+ System.getProperty("line.separator")
|
||||
+ "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER"
|
||||
+ System.getProperty("line.separator")
|
||||
+ "DEALINGS IN THE SOFTWARE.";
|
||||
|
||||
public static void main(
|
||||
String[] args)
|
||||
{
|
||||
System.out.println(licenseText);
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ASN1ApplicationSpecificParser
|
||||
extends DEREncodable
|
||||
{
|
||||
DEREncodable readObject()
|
||||
throws IOException;
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
/**
|
||||
* Marker interface for CHOICE objects - if you implement this in a role your
|
||||
* own object any attempt to tag the object implicitly will convert the tag to
|
||||
* an explicit one as the encoding rules require.
|
||||
* <p>
|
||||
* If you use this interface your class should also implement the getInstance
|
||||
* pattern which takes a tag object and the tagging mode used.
|
||||
*/
|
||||
public interface ASN1Choice
|
||||
{
|
||||
// marker interface
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Base class for objects which can be written directly to ASN.1 output streams.
|
||||
*/
|
||||
public abstract class ASN1Encodable
|
||||
implements DEREncodable
|
||||
{
|
||||
public static final String DER = "DER";
|
||||
public static final String BER = "BER";
|
||||
|
||||
/**
|
||||
* Return the default BER or DER encoding for this object.
|
||||
*
|
||||
* @return BER/DER byte encoded object.
|
||||
* @throws IOException on encoding error.
|
||||
*/
|
||||
public byte[] getEncoded()
|
||||
throws IOException
|
||||
{
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
|
||||
|
||||
aOut.writeObject(this);
|
||||
|
||||
return bOut.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return either the default for "BER" or a DER encoding if "DER" is specified.
|
||||
*
|
||||
* @param encoding name of encoding to use.
|
||||
* @return byte encoded object.
|
||||
* @throws IOException on encoding error.
|
||||
*/
|
||||
public byte[] getEncoded(
|
||||
String encoding)
|
||||
throws IOException
|
||||
{
|
||||
if (encoding.equals(DER))
|
||||
{
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
DEROutputStream dOut = new DEROutputStream(bOut);
|
||||
|
||||
dOut.writeObject(this);
|
||||
|
||||
return bOut.toByteArray();
|
||||
}
|
||||
|
||||
return this.getEncoded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DER encoding of the object, null if the DER encoding can not be made.
|
||||
*
|
||||
* @return a DER byte array, null otherwise.
|
||||
*/
|
||||
public byte[] getDEREncoded()
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.getEncoded(DER);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.toASN1Object().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(
|
||||
Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof DEREncodable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DEREncodable other = (DEREncodable)o;
|
||||
|
||||
return this.toASN1Object().equals(other.getDERObject());
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
return this.toASN1Object();
|
||||
}
|
||||
|
||||
public abstract DERObject toASN1Object();
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
/**
|
||||
* the parent class for this will eventually disappear. Use this one!
|
||||
*/
|
||||
public class ASN1EncodableVector
|
||||
extends DEREncodableVector
|
||||
{
|
||||
// migrating from DEREncodeableVector
|
||||
public ASN1EncodableVector()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public abstract class ASN1Generator
|
||||
{
|
||||
protected OutputStream _out;
|
||||
|
||||
public ASN1Generator(OutputStream out)
|
||||
{
|
||||
_out = out;
|
||||
}
|
||||
|
||||
public abstract OutputStream getRawOutputStream();
|
||||
}
|
@ -1,386 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
|
||||
/**
|
||||
* a general purpose ASN.1 decoder - note: this class differs from the
|
||||
* others in that it returns null after it has read the last object in
|
||||
* the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
|
||||
* returned.
|
||||
*/
|
||||
public class ASN1InputStream
|
||||
extends FilterInputStream
|
||||
implements DERTags
|
||||
{
|
||||
private final int limit;
|
||||
private final boolean lazyEvaluate;
|
||||
|
||||
public ASN1InputStream(
|
||||
InputStream is)
|
||||
{
|
||||
this(is, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ASN1InputStream based on the input byte array. The length of DER objects in
|
||||
* the stream is automatically limited to the length of the input array.
|
||||
*
|
||||
* @param input array containing ASN.1 encoded data.
|
||||
*/
|
||||
public ASN1InputStream(
|
||||
byte[] input)
|
||||
{
|
||||
this(new ByteArrayInputStream(input), input.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ASN1InputStream based on the input byte array. The length of DER objects in
|
||||
* the stream is automatically limited to the length of the input array.
|
||||
*
|
||||
* @param input array containing ASN.1 encoded data.
|
||||
* @param lazyEvaluate true if parsing inside constructed objects can be delayed.
|
||||
*/
|
||||
public ASN1InputStream(
|
||||
byte[] input,
|
||||
boolean lazyEvaluate)
|
||||
{
|
||||
this(new ByteArrayInputStream(input), input.length, lazyEvaluate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ASN1InputStream where no DER object will be longer than limit.
|
||||
*
|
||||
* @param input stream containing ASN.1 encoded data.
|
||||
* @param limit maximum size of a DER encoded object.
|
||||
*/
|
||||
public ASN1InputStream(
|
||||
InputStream input,
|
||||
int limit)
|
||||
{
|
||||
this(input, limit, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ASN1InputStream where no DER object will be longer than limit, and constructed
|
||||
* objects such as sequences will be parsed lazily.
|
||||
*
|
||||
* @param input stream containing ASN.1 encoded data.
|
||||
* @param limit maximum size of a DER encoded object.
|
||||
* @param lazyEvaluate true if parsing inside constructed objects can be delayed.
|
||||
*/
|
||||
public ASN1InputStream(
|
||||
InputStream input,
|
||||
int limit,
|
||||
boolean lazyEvaluate)
|
||||
{
|
||||
super(input);
|
||||
this.limit = limit;
|
||||
this.lazyEvaluate = lazyEvaluate;
|
||||
}
|
||||
|
||||
protected int readLength()
|
||||
throws IOException
|
||||
{
|
||||
return readLength(this, limit);
|
||||
}
|
||||
|
||||
protected void readFully(
|
||||
byte[] bytes)
|
||||
throws IOException
|
||||
{
|
||||
if (Streams.readFully(this, bytes) != bytes.length)
|
||||
{
|
||||
throw new EOFException("EOF encountered in middle of object");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* build an object given its tag and the number of bytes to construct it from.
|
||||
*/
|
||||
protected DERObject buildObject(
|
||||
int tag,
|
||||
int tagNo,
|
||||
int length)
|
||||
throws IOException
|
||||
{
|
||||
boolean isConstructed = (tag & CONSTRUCTED) != 0;
|
||||
|
||||
DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
|
||||
|
||||
if ((tag & APPLICATION) != 0)
|
||||
{
|
||||
return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
|
||||
}
|
||||
|
||||
if ((tag & TAGGED) != 0)
|
||||
{
|
||||
return new BERTaggedObjectParser(tag, tagNo, defIn).getDERObject();
|
||||
}
|
||||
|
||||
if (isConstructed)
|
||||
{
|
||||
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
|
||||
switch (tagNo)
|
||||
{
|
||||
case OCTET_STRING:
|
||||
//
|
||||
// yes, people actually do this...
|
||||
//
|
||||
return new BERConstructedOctetString(buildDEREncodableVector(defIn).v);
|
||||
case SEQUENCE:
|
||||
if (lazyEvaluate)
|
||||
{
|
||||
return new LazyDERSequence(defIn.toByteArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
return DERFactory.createSequence(buildDEREncodableVector(defIn));
|
||||
}
|
||||
case SET:
|
||||
return DERFactory.createSet(buildDEREncodableVector(defIn), false);
|
||||
case EXTERNAL:
|
||||
return new DERExternal(buildDEREncodableVector(defIn));
|
||||
default:
|
||||
return new DERUnknownTag(true, tagNo, defIn.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
return createPrimitiveDERObject(tagNo, defIn.toByteArray());
|
||||
}
|
||||
|
||||
ASN1EncodableVector buildEncodableVector()
|
||||
throws IOException
|
||||
{
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
DERObject o;
|
||||
|
||||
while ((o = readObject()) != null)
|
||||
{
|
||||
v.add(o);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
ASN1EncodableVector buildDEREncodableVector(
|
||||
DefiniteLengthInputStream dIn) throws IOException
|
||||
{
|
||||
return new ASN1InputStream(dIn).buildEncodableVector();
|
||||
}
|
||||
|
||||
public DERObject readObject()
|
||||
throws IOException
|
||||
{
|
||||
int tag = read();
|
||||
if (tag <= 0)
|
||||
{
|
||||
if (tag == 0)
|
||||
{
|
||||
throw new IOException("unexpected end-of-contents marker");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// calculate tag number
|
||||
//
|
||||
int tagNo = readTagNumber(this, tag);
|
||||
|
||||
boolean isConstructed = (tag & CONSTRUCTED) != 0;
|
||||
|
||||
//
|
||||
// calculate length
|
||||
//
|
||||
int length = readLength();
|
||||
|
||||
if (length < 0) // indefinite length method
|
||||
{
|
||||
if (!isConstructed)
|
||||
{
|
||||
throw new IOException("indefinite length primitive encoding encountered");
|
||||
}
|
||||
|
||||
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this);
|
||||
|
||||
if ((tag & APPLICATION) != 0)
|
||||
{
|
||||
ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
|
||||
|
||||
return new BERApplicationSpecificParser(tagNo, sp).getDERObject();
|
||||
}
|
||||
if ((tag & TAGGED) != 0)
|
||||
{
|
||||
return new BERTaggedObjectParser(tag, tagNo, indIn).getDERObject();
|
||||
}
|
||||
|
||||
ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
|
||||
|
||||
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
|
||||
switch (tagNo)
|
||||
{
|
||||
case OCTET_STRING:
|
||||
return new BEROctetStringParser(sp).getDERObject();
|
||||
case SEQUENCE:
|
||||
return new BERSequenceParser(sp).getDERObject();
|
||||
case SET:
|
||||
return new BERSetParser(sp).getDERObject();
|
||||
case EXTERNAL:
|
||||
return new DERExternalParser(sp).getDERObject();
|
||||
default:
|
||||
throw new IOException("unknown BER object encountered");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return buildObject(tag, tagNo, length);
|
||||
}
|
||||
}
|
||||
|
||||
static int readTagNumber(InputStream s, int tag)
|
||||
throws IOException
|
||||
{
|
||||
int tagNo = tag & 0x1f;
|
||||
|
||||
//
|
||||
// with tagged object tag number is bottom 5 bits, or stored at the start of the content
|
||||
//
|
||||
if (tagNo == 0x1f)
|
||||
{
|
||||
tagNo = 0;
|
||||
|
||||
int b = s.read();
|
||||
|
||||
// X.690-0207 8.1.2.4.2
|
||||
// "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
|
||||
if ((b & 0x7f) == 0) // Note: -1 will pass
|
||||
{
|
||||
throw new IOException("corrupted stream - invalid high tag number found");
|
||||
}
|
||||
|
||||
while ((b >= 0) && ((b & 0x80) != 0))
|
||||
{
|
||||
tagNo |= (b & 0x7f);
|
||||
tagNo <<= 7;
|
||||
b = s.read();
|
||||
}
|
||||
|
||||
if (b < 0)
|
||||
{
|
||||
throw new EOFException("EOF found inside tag value.");
|
||||
}
|
||||
|
||||
tagNo |= (b & 0x7f);
|
||||
}
|
||||
|
||||
return tagNo;
|
||||
}
|
||||
|
||||
static int readLength(InputStream s, int limit)
|
||||
throws IOException
|
||||
{
|
||||
int length = s.read();
|
||||
if (length < 0)
|
||||
{
|
||||
throw new EOFException("EOF found when length expected");
|
||||
}
|
||||
|
||||
if (length == 0x80)
|
||||
{
|
||||
return -1; // indefinite-length encoding
|
||||
}
|
||||
|
||||
if (length > 127)
|
||||
{
|
||||
int size = length & 0x7f;
|
||||
|
||||
if (size > 4)
|
||||
{
|
||||
throw new IOException("DER length more than 4 bytes: " + size);
|
||||
}
|
||||
|
||||
length = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
int next = s.read();
|
||||
|
||||
if (next < 0)
|
||||
{
|
||||
throw new EOFException("EOF found reading length");
|
||||
}
|
||||
|
||||
length = (length << 8) + next;
|
||||
}
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
throw new IOException("corrupted stream - negative length found");
|
||||
}
|
||||
|
||||
if (length >= limit) // after all we must have read at least 1 byte
|
||||
{
|
||||
throw new IOException("corrupted stream - out of bounds length found");
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static DERObject createPrimitiveDERObject(
|
||||
int tagNo,
|
||||
byte[] bytes)
|
||||
{
|
||||
switch (tagNo)
|
||||
{
|
||||
case BIT_STRING:
|
||||
{
|
||||
int padBits = bytes[0];
|
||||
byte[] data = new byte[bytes.length - 1];
|
||||
System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
|
||||
return new DERBitString(data, padBits);
|
||||
}
|
||||
case BMP_STRING:
|
||||
return new DERBMPString(bytes);
|
||||
case BOOLEAN:
|
||||
return new DERBoolean(bytes);
|
||||
case ENUMERATED:
|
||||
return new DEREnumerated(bytes);
|
||||
case GENERALIZED_TIME:
|
||||
return new DERGeneralizedTime(bytes);
|
||||
case GENERAL_STRING:
|
||||
return new DERGeneralString(bytes);
|
||||
case IA5_STRING:
|
||||
return new DERIA5String(bytes);
|
||||
case INTEGER:
|
||||
return new DERInteger(bytes);
|
||||
case NULL:
|
||||
return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
|
||||
case NUMERIC_STRING:
|
||||
return new DERNumericString(bytes);
|
||||
case OBJECT_IDENTIFIER:
|
||||
return new DERObjectIdentifier(bytes);
|
||||
case OCTET_STRING:
|
||||
return new DEROctetString(bytes);
|
||||
case PRINTABLE_STRING:
|
||||
return new DERPrintableString(bytes);
|
||||
case T61_STRING:
|
||||
return new DERT61String(bytes);
|
||||
case UNIVERSAL_STRING:
|
||||
return new DERUniversalString(bytes);
|
||||
case UTC_TIME:
|
||||
return new DERUTCTime(bytes);
|
||||
case UTF8_STRING:
|
||||
return new DERUTF8String(bytes);
|
||||
case VISIBLE_STRING:
|
||||
return new DERVisibleString(bytes);
|
||||
default:
|
||||
return new DERUnknownTag(false, tagNo, bytes);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A NULL object.
|
||||
*/
|
||||
public abstract class ASN1Null
|
||||
extends ASN1Object
|
||||
{
|
||||
public ASN1Null()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof ASN1Null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract void encode(DEROutputStream out)
|
||||
throws IOException;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "NULL";
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class ASN1Object
|
||||
extends DERObject
|
||||
{
|
||||
/**
|
||||
* Create a base ASN.1 object from a byte stream.
|
||||
*
|
||||
* @param data the byte stream to parse.
|
||||
* @return the base ASN.1 object represented by the byte stream.
|
||||
* @exception IOException if there is a problem parsing the data.
|
||||
*/
|
||||
public static ASN1Object fromByteArray(byte[] data)
|
||||
throws IOException
|
||||
{
|
||||
ASN1InputStream aIn = new ASN1InputStream(data);
|
||||
|
||||
return (ASN1Object)aIn.readObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return (o instanceof DEREncodable) && asn1Equals(((DEREncodable)o).getDERObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
@Override
|
||||
abstract void encode(DEROutputStream out) throws IOException;
|
||||
|
||||
abstract boolean asn1Equals(DERObject o);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @deprecated will be removed
|
||||
*/
|
||||
@Deprecated
|
||||
public class ASN1ObjectParser
|
||||
{
|
||||
ASN1StreamParser _aIn;
|
||||
|
||||
protected ASN1ObjectParser(
|
||||
int baseTag,
|
||||
int tagNumber,
|
||||
InputStream contentStream)
|
||||
{
|
||||
_aIn = new ASN1StreamParser(contentStream);
|
||||
}
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.bouncycastle.util.Arrays;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
public abstract class ASN1OctetString
|
||||
extends ASN1Object
|
||||
implements ASN1OctetStringParser
|
||||
{
|
||||
byte[] string;
|
||||
|
||||
/**
|
||||
* return an Octet String from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want.
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static ASN1OctetString getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* return an Octet String from the given object.
|
||||
*
|
||||
* @param obj the object we want converted.
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static ASN1OctetString getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof ASN1OctetString)
|
||||
{
|
||||
return (ASN1OctetString)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1Sequence)
|
||||
{
|
||||
Vector v = new Vector();
|
||||
Enumeration e = ((ASN1Sequence)obj).getObjects();
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
v.addElement(e.nextElement());
|
||||
}
|
||||
|
||||
return new BERConstructedOctetString(v);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string the octets making up the octet string.
|
||||
*/
|
||||
public ASN1OctetString(
|
||||
byte[] string)
|
||||
{
|
||||
if (string == null)
|
||||
{
|
||||
throw new NullPointerException("string cannot be null");
|
||||
}
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public ASN1OctetString(
|
||||
DEREncodable obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.string = obj.getDERObject().getEncoded(ASN1Encodable.DER);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalArgumentException("Error processing object : " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getOctetStream()
|
||||
{
|
||||
return new ByteArrayInputStream(string);
|
||||
}
|
||||
|
||||
public ASN1OctetStringParser parser()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public byte[] getOctets()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Arrays.hashCode(this.getOctets());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof ASN1OctetString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ASN1OctetString other = (ASN1OctetString)o;
|
||||
|
||||
return Arrays.areEqual(string, other.string);
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract void encode(DEROutputStream out)
|
||||
throws IOException;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "#"+new String(Hex.encode(string));
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface ASN1OctetStringParser
|
||||
extends DEREncodable
|
||||
{
|
||||
public InputStream getOctetStream();
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class ASN1OutputStream
|
||||
extends DEROutputStream
|
||||
{
|
||||
public ASN1OutputStream(
|
||||
OutputStream os)
|
||||
{
|
||||
super(os);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeObject(
|
||||
Object obj)
|
||||
throws IOException
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
writeNull();
|
||||
}
|
||||
else if (obj instanceof DERObject)
|
||||
{
|
||||
((DERObject)obj).encode(this);
|
||||
}
|
||||
else if (obj instanceof DEREncodable)
|
||||
{
|
||||
((DEREncodable)obj).getDERObject().encode(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("object not ASN1Encodable");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
public class ASN1ParsingException
|
||||
extends IllegalStateException
|
||||
{
|
||||
private Throwable cause;
|
||||
|
||||
ASN1ParsingException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
ASN1ParsingException(String message, Throwable cause)
|
||||
{
|
||||
super(message);
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable getCause()
|
||||
{
|
||||
return cause;
|
||||
}
|
||||
}
|
@ -1,221 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
public abstract class ASN1Sequence
|
||||
extends ASN1Object
|
||||
{
|
||||
private Vector seq = new Vector();
|
||||
|
||||
/**
|
||||
* return an ASN1Sequence from the given object.
|
||||
*
|
||||
* @param obj the object we want converted.
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static ASN1Sequence getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof ASN1Sequence)
|
||||
{
|
||||
return (ASN1Sequence)obj;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an ASN1 sequence from a tagged object. There is a special
|
||||
* case here, if an object appears to have been explicitly tagged on
|
||||
* reading but we were expecting it to be implicitly tagged in the
|
||||
* normal course of events it indicates that we lost the surrounding
|
||||
* sequence - so we need to add it back (this will happen if the tagged
|
||||
* object is a sequence that contains other sequences). If you are
|
||||
* dealing with implicitly tagged sequences you really <b>should</b>
|
||||
* be using this method.
|
||||
*
|
||||
* @param obj the tagged object.
|
||||
* @param explicit true if the object is meant to be explicitly tagged,
|
||||
* false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static ASN1Sequence getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
if (explicit)
|
||||
{
|
||||
if (!obj.isExplicit())
|
||||
{
|
||||
throw new IllegalArgumentException("object implicit - explicit expected.");
|
||||
}
|
||||
|
||||
return (ASN1Sequence)obj.getObject();
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// constructed object which appears to be explicitly tagged
|
||||
// when it should be implicit means we have to add the
|
||||
// surrounding sequence.
|
||||
//
|
||||
if (obj.isExplicit())
|
||||
{
|
||||
if (obj instanceof BERTaggedObject)
|
||||
{
|
||||
return new BERSequence(obj.getObject());
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DERSequence(obj.getObject());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (obj.getObject() instanceof ASN1Sequence)
|
||||
{
|
||||
return (ASN1Sequence)obj.getObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
public Enumeration getObjects()
|
||||
{
|
||||
return seq.elements();
|
||||
}
|
||||
|
||||
public ASN1SequenceParser parser()
|
||||
{
|
||||
final ASN1Sequence outer = this;
|
||||
|
||||
return new ASN1SequenceParser()
|
||||
{
|
||||
private final int max = size();
|
||||
|
||||
private int index;
|
||||
|
||||
public DEREncodable readObject() throws IOException
|
||||
{
|
||||
if (index == max)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
DEREncodable obj = getObjectAt(index++);
|
||||
if (obj instanceof ASN1Sequence)
|
||||
{
|
||||
return ((ASN1Sequence)obj).parser();
|
||||
}
|
||||
if (obj instanceof ASN1Set)
|
||||
{
|
||||
return ((ASN1Set)obj).parser();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
return outer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* return the object at the sequence position indicated by index.
|
||||
*
|
||||
* @param index the sequence number (starting at zero) of the object
|
||||
* @return the object at the sequence position indicated by index.
|
||||
*/
|
||||
public DEREncodable getObjectAt(
|
||||
int index)
|
||||
{
|
||||
return (DEREncodable)seq.elementAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the number of objects in this sequence.
|
||||
*
|
||||
* @return the number of objects in this sequence.
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return seq.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
Enumeration e = this.getObjects();
|
||||
int hashCode = size();
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
Object o = e.nextElement();
|
||||
hashCode *= 17;
|
||||
if (o != null)
|
||||
{
|
||||
hashCode ^= o.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof ASN1Sequence))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ASN1Sequence other = (ASN1Sequence)o;
|
||||
|
||||
if (this.size() != other.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Enumeration s1 = this.getObjects();
|
||||
Enumeration s2 = other.getObjects();
|
||||
|
||||
while (s1.hasMoreElements())
|
||||
{
|
||||
DERObject o1 = ((DEREncodable)s1.nextElement()).getDERObject();
|
||||
DERObject o2 = ((DEREncodable)s2.nextElement()).getDERObject();
|
||||
|
||||
if (o1 == o2 || (o1 != null && o1.equals(o2)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void addObject(
|
||||
DEREncodable obj)
|
||||
{
|
||||
seq.addElement(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract void encode(DEROutputStream out)
|
||||
throws IOException;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return seq.toString();
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ASN1SequenceParser
|
||||
extends DEREncodable
|
||||
{
|
||||
DEREncodable readObject()
|
||||
throws IOException;
|
||||
}
|
@ -1,347 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
abstract public class ASN1Set
|
||||
extends ASN1Object
|
||||
{
|
||||
protected Vector set = new Vector();
|
||||
|
||||
/**
|
||||
* return an ASN1Set from the given object.
|
||||
*
|
||||
* @param obj the object we want converted.
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static ASN1Set getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof ASN1Set)
|
||||
{
|
||||
return (ASN1Set)obj;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an ASN1 set from a tagged object. There is a special
|
||||
* case here, if an object appears to have been explicitly tagged on
|
||||
* reading but we were expecting it to be implicitly tagged in the
|
||||
* normal course of events it indicates that we lost the surrounding
|
||||
* set - so we need to add it back (this will happen if the tagged
|
||||
* object is a sequence that contains other sequences). If you are
|
||||
* dealing with implicitly tagged sets you really <b>should</b>
|
||||
* be using this method.
|
||||
*
|
||||
* @param obj the tagged object.
|
||||
* @param explicit true if the object is meant to be explicitly tagged
|
||||
* false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static ASN1Set getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
if (explicit)
|
||||
{
|
||||
if (!obj.isExplicit())
|
||||
{
|
||||
throw new IllegalArgumentException("object implicit - explicit expected.");
|
||||
}
|
||||
|
||||
return (ASN1Set)obj.getObject();
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// constructed object which appears to be explicitly tagged
|
||||
// and it's really implicit means we have to add the
|
||||
// surrounding sequence.
|
||||
//
|
||||
if (obj.isExplicit())
|
||||
{
|
||||
ASN1Set set = new DERSet(obj.getObject());
|
||||
|
||||
return set;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (obj.getObject() instanceof ASN1Set)
|
||||
{
|
||||
return (ASN1Set)obj.getObject();
|
||||
}
|
||||
|
||||
//
|
||||
// in this case the parser returns a sequence, convert it
|
||||
// into a set.
|
||||
//
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
if (obj.getObject() instanceof ASN1Sequence)
|
||||
{
|
||||
ASN1Sequence s = (ASN1Sequence)obj.getObject();
|
||||
Enumeration e = s.getObjects();
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
v.add((DEREncodable)e.nextElement());
|
||||
}
|
||||
|
||||
return new DERSet(v, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
public ASN1Set()
|
||||
{
|
||||
}
|
||||
|
||||
public Enumeration getObjects()
|
||||
{
|
||||
return set.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* return the object at the set position indicated by index.
|
||||
*
|
||||
* @param index the set number (starting at zero) of the object
|
||||
* @return the object at the set position indicated by index.
|
||||
*/
|
||||
public DEREncodable getObjectAt(
|
||||
int index)
|
||||
{
|
||||
return (DEREncodable)set.elementAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the number of objects in this set.
|
||||
*
|
||||
* @return the number of objects in this set.
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return set.size();
|
||||
}
|
||||
|
||||
public ASN1SetParser parser()
|
||||
{
|
||||
final ASN1Set outer = this;
|
||||
|
||||
return new ASN1SetParser()
|
||||
{
|
||||
private final int max = size();
|
||||
|
||||
private int index;
|
||||
|
||||
public DEREncodable readObject() throws IOException
|
||||
{
|
||||
if (index == max)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
DEREncodable obj = getObjectAt(index++);
|
||||
if (obj instanceof ASN1Sequence)
|
||||
{
|
||||
return ((ASN1Sequence)obj).parser();
|
||||
}
|
||||
if (obj instanceof ASN1Set)
|
||||
{
|
||||
return ((ASN1Set)obj).parser();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
return outer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
Enumeration e = this.getObjects();
|
||||
int hashCode = size();
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
Object o = e.nextElement();
|
||||
hashCode *= 17;
|
||||
if (o != null)
|
||||
{
|
||||
hashCode ^= o.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof ASN1Set))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ASN1Set other = (ASN1Set)o;
|
||||
|
||||
if (this.size() != other.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Enumeration s1 = this.getObjects();
|
||||
Enumeration s2 = other.getObjects();
|
||||
|
||||
while (s1.hasMoreElements())
|
||||
{
|
||||
DERObject o1 = ((DEREncodable)s1.nextElement()).getDERObject();
|
||||
DERObject o2 = ((DEREncodable)s2.nextElement()).getDERObject();
|
||||
|
||||
if (o1 == o2 || (o1 != null && o1.equals(o2)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if a <= b (arrays are assumed padded with zeros).
|
||||
*/
|
||||
private boolean lessThanOrEqual(
|
||||
byte[] a,
|
||||
byte[] b)
|
||||
{
|
||||
if (a.length <= b.length)
|
||||
{
|
||||
for (int i = 0; i != a.length; i++)
|
||||
{
|
||||
int l = a[i] & 0xff;
|
||||
int r = b[i] & 0xff;
|
||||
|
||||
if (r > l)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (l > r)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i != b.length; i++)
|
||||
{
|
||||
int l = a[i] & 0xff;
|
||||
int r = b[i] & 0xff;
|
||||
|
||||
if (r > l)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (l > r)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getEncoded(
|
||||
DEREncodable obj)
|
||||
{
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
|
||||
|
||||
try
|
||||
{
|
||||
aOut.writeObject(obj);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalArgumentException("cannot encode object added to SET");
|
||||
}
|
||||
|
||||
return bOut.toByteArray();
|
||||
}
|
||||
|
||||
protected void sort()
|
||||
{
|
||||
if (set.size() > 1)
|
||||
{
|
||||
boolean swapped = true;
|
||||
int lastSwap = set.size() - 1;
|
||||
|
||||
while (swapped)
|
||||
{
|
||||
int index = 0;
|
||||
int swapIndex = 0;
|
||||
byte[] a = getEncoded((DEREncodable)set.elementAt(0));
|
||||
|
||||
swapped = false;
|
||||
|
||||
while (index != lastSwap)
|
||||
{
|
||||
byte[] b = getEncoded((DEREncodable)set.elementAt(index + 1));
|
||||
|
||||
if (lessThanOrEqual(a, b))
|
||||
{
|
||||
a = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
Object o = set.elementAt(index);
|
||||
|
||||
set.setElementAt(set.elementAt(index + 1), index);
|
||||
set.setElementAt(o, index + 1);
|
||||
|
||||
swapped = true;
|
||||
swapIndex = index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
lastSwap = swapIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void addObject(
|
||||
DEREncodable obj)
|
||||
{
|
||||
set.addElement(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract void encode(DEROutputStream out)
|
||||
throws IOException;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return set.toString();
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ASN1SetParser
|
||||
extends DEREncodable
|
||||
{
|
||||
public DEREncodable readObject()
|
||||
throws IOException;
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ASN1StreamParser
|
||||
{
|
||||
private final InputStream _in;
|
||||
private final int _limit;
|
||||
|
||||
private static int findLimit(InputStream in)
|
||||
{
|
||||
if (in instanceof DefiniteLengthInputStream)
|
||||
{
|
||||
return ((DefiniteLengthInputStream)in).getRemaining();
|
||||
}
|
||||
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
public ASN1StreamParser(
|
||||
InputStream in)
|
||||
{
|
||||
this(in, findLimit(in));
|
||||
}
|
||||
|
||||
public ASN1StreamParser(
|
||||
InputStream in,
|
||||
int limit)
|
||||
{
|
||||
this._in = in;
|
||||
this._limit = limit;
|
||||
}
|
||||
|
||||
public ASN1StreamParser(
|
||||
byte[] encoding)
|
||||
{
|
||||
this(new ByteArrayInputStream(encoding), encoding.length);
|
||||
}
|
||||
|
||||
public DEREncodable readObject()
|
||||
throws IOException
|
||||
{
|
||||
int tag = _in.read();
|
||||
if (tag == -1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// turn of looking for "00" while we resolve the tag
|
||||
//
|
||||
set00Check(false);
|
||||
|
||||
//
|
||||
// calculate tag number
|
||||
//
|
||||
int tagNo = ASN1InputStream.readTagNumber(_in, tag);
|
||||
|
||||
boolean isConstructed = (tag & DERTags.CONSTRUCTED) != 0;
|
||||
|
||||
//
|
||||
// calculate length
|
||||
//
|
||||
int length = ASN1InputStream.readLength(_in, _limit);
|
||||
|
||||
if (length < 0) // indefinite length method
|
||||
{
|
||||
if (!isConstructed)
|
||||
{
|
||||
throw new IOException("indefinite length primitive encoding encountered");
|
||||
}
|
||||
|
||||
IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in);
|
||||
|
||||
if ((tag & DERTags.APPLICATION) != 0)
|
||||
{
|
||||
ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
|
||||
|
||||
return new BERApplicationSpecificParser(tagNo, sp);
|
||||
}
|
||||
|
||||
if ((tag & DERTags.TAGGED) != 0)
|
||||
{
|
||||
return new BERTaggedObjectParser(tag, tagNo, indIn);
|
||||
}
|
||||
|
||||
ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
|
||||
|
||||
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
|
||||
switch (tagNo)
|
||||
{
|
||||
case DERTags.OCTET_STRING:
|
||||
return new BEROctetStringParser(sp);
|
||||
case DERTags.SEQUENCE:
|
||||
return new BERSequenceParser(sp);
|
||||
case DERTags.SET:
|
||||
return new BERSetParser(sp);
|
||||
case DERTags.EXTERNAL:{
|
||||
return new DERExternalParser(sp);
|
||||
}
|
||||
default:
|
||||
throw new IOException("unknown BER object encountered: 0x" + Integer.toHexString(tagNo));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
|
||||
|
||||
if ((tag & DERTags.APPLICATION) != 0)
|
||||
{
|
||||
return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
|
||||
}
|
||||
|
||||
if ((tag & DERTags.TAGGED) != 0)
|
||||
{
|
||||
return new BERTaggedObjectParser(tag, tagNo, defIn);
|
||||
}
|
||||
|
||||
if (isConstructed)
|
||||
{
|
||||
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
|
||||
switch (tagNo)
|
||||
{
|
||||
case DERTags.OCTET_STRING:
|
||||
//
|
||||
// yes, people actually do this...
|
||||
//
|
||||
return new BEROctetStringParser(new ASN1StreamParser(defIn));
|
||||
case DERTags.SEQUENCE:
|
||||
return new DERSequenceParser(new ASN1StreamParser(defIn));
|
||||
case DERTags.SET:
|
||||
return new DERSetParser(new ASN1StreamParser(defIn));
|
||||
case DERTags.EXTERNAL:
|
||||
return new DERExternalParser(new ASN1StreamParser(defIn));
|
||||
default:
|
||||
// TODO Add DERUnknownTagParser class?
|
||||
return new DERUnknownTag(true, tagNo, defIn.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
// Some primitive encodings can be handled by parsers too...
|
||||
switch (tagNo)
|
||||
{
|
||||
case DERTags.OCTET_STRING:
|
||||
return new DEROctetStringParser(defIn);
|
||||
}
|
||||
|
||||
return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void set00Check(boolean enabled)
|
||||
{
|
||||
if (_in instanceof IndefiniteLengthInputStream)
|
||||
{
|
||||
((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
ASN1EncodableVector readVector() throws IOException
|
||||
{
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
DEREncodable obj;
|
||||
while ((obj = readObject()) != null)
|
||||
{
|
||||
v.add(obj.getDERObject());
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
@ -1,214 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
|
||||
* a [n] where n is some number - these are assumed to follow the construction
|
||||
* rules (as with sequences).
|
||||
*/
|
||||
public abstract class ASN1TaggedObject
|
||||
extends ASN1Object
|
||||
implements ASN1TaggedObjectParser
|
||||
{
|
||||
int tagNo;
|
||||
boolean empty = false;
|
||||
boolean explicit = true;
|
||||
DEREncodable obj = null;
|
||||
|
||||
static public ASN1TaggedObject getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
if (explicit)
|
||||
{
|
||||
return (ASN1TaggedObject)obj.getObject();
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("implicitly tagged tagged object");
|
||||
}
|
||||
|
||||
static public ASN1TaggedObject getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return (ASN1TaggedObject)obj;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a tagged object in the explicit style.
|
||||
*
|
||||
* @param tagNo the tag number for this object.
|
||||
* @param obj the tagged object.
|
||||
*/
|
||||
public ASN1TaggedObject(
|
||||
int tagNo,
|
||||
DEREncodable obj)
|
||||
{
|
||||
this.explicit = true;
|
||||
this.tagNo = tagNo;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a tagged object with the style given by the value of explicit.
|
||||
* <p>
|
||||
* If the object implements ASN1Choice the tag style will always be changed
|
||||
* to explicit in accordance with the ASN.1 encoding rules.
|
||||
* </p>
|
||||
* @param explicit true if the object is explicitly tagged.
|
||||
* @param tagNo the tag number for this object.
|
||||
* @param obj the tagged object.
|
||||
*/
|
||||
public ASN1TaggedObject(
|
||||
boolean explicit,
|
||||
int tagNo,
|
||||
DEREncodable obj)
|
||||
{
|
||||
if (obj instanceof ASN1Choice)
|
||||
{
|
||||
this.explicit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.explicit = explicit;
|
||||
}
|
||||
|
||||
this.tagNo = tagNo;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof ASN1TaggedObject))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ASN1TaggedObject other = (ASN1TaggedObject)o;
|
||||
|
||||
if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(obj == null)
|
||||
{
|
||||
if (other.obj != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(obj.getDERObject().equals(other.obj.getDERObject())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int code = tagNo;
|
||||
|
||||
// TODO: actually this is wrong - the problem is that a re-encoded
|
||||
// object may end up with a different hashCode due to implicit
|
||||
// tagging. As implicit tagging is ambiguous if a sequence is involved
|
||||
// it seems the only correct method for both equals and hashCode is to
|
||||
// compare the encodings...
|
||||
if (obj != null)
|
||||
{
|
||||
code ^= obj.hashCode();
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
public int getTagNo()
|
||||
{
|
||||
return tagNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* return whether or not the object may be explicitly tagged.
|
||||
* <p>
|
||||
* Note: if the object has been read from an input stream, the only
|
||||
* time you can be sure if isExplicit is returning the true state of
|
||||
* affairs is if it returns false. An implicitly tagged object may appear
|
||||
* to be explicitly tagged, so you need to understand the context under
|
||||
* which the reading was done as well, see getObject below.
|
||||
*/
|
||||
public boolean isExplicit()
|
||||
{
|
||||
return explicit;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* return whatever was following the tag.
|
||||
* <p>
|
||||
* Note: tagged objects are generally context dependent if you're
|
||||
* trying to extract a tagged object you should be going via the
|
||||
* appropriate getInstance method.
|
||||
*/
|
||||
public DERObject getObject()
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
return obj.getDERObject();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object held in this tagged object as a parser assuming it has
|
||||
* the type of the passed in tag. If the object doesn't have a parser
|
||||
* associated with it, the base object is returned.
|
||||
*/
|
||||
public DEREncodable getObjectParser(
|
||||
int tag,
|
||||
boolean isExplicit)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case DERTags.SET:
|
||||
return ASN1Set.getInstance(this, isExplicit).parser();
|
||||
case DERTags.SEQUENCE:
|
||||
return ASN1Sequence.getInstance(this, isExplicit).parser();
|
||||
case DERTags.OCTET_STRING:
|
||||
return ASN1OctetString.getInstance(this, isExplicit).parser();
|
||||
}
|
||||
|
||||
if (isExplicit)
|
||||
{
|
||||
return getObject();
|
||||
}
|
||||
|
||||
throw new RuntimeException("implicit tagging not implemented for tag: " + tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract void encode(DEROutputStream out)
|
||||
throws IOException;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "[" + tagNo + "]" + obj;
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ASN1TaggedObjectParser
|
||||
extends DEREncodable
|
||||
{
|
||||
public int getTagNo();
|
||||
|
||||
public DEREncodable getObjectParser(int tag, boolean isExplicit)
|
||||
throws IOException;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
public class BERApplicationSpecific
|
||||
extends DERApplicationSpecific
|
||||
{
|
||||
public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
|
||||
{
|
||||
super(tagNo, vec);
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BERApplicationSpecificParser
|
||||
implements ASN1ApplicationSpecificParser
|
||||
{
|
||||
private final int tag;
|
||||
private final ASN1StreamParser parser;
|
||||
|
||||
BERApplicationSpecificParser(int tag, ASN1StreamParser parser)
|
||||
{
|
||||
this.tag = tag;
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
public DEREncodable readObject()
|
||||
throws IOException
|
||||
{
|
||||
return parser.readObject();
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new BERApplicationSpecific(tag, parser.readVector());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ASN1ParsingException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
public class BERConstructedOctetString
|
||||
extends DEROctetString
|
||||
{
|
||||
private static final int MAX_LENGTH = 1000;
|
||||
|
||||
/**
|
||||
* convert a vector of octet strings into a single byte string
|
||||
*/
|
||||
static private byte[] toBytes(
|
||||
Vector octs)
|
||||
{
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
|
||||
for (int i = 0; i != octs.size(); i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
DEROctetString o = (DEROctetString)octs.elementAt(i);
|
||||
|
||||
bOut.write(o.getOctets());
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
{
|
||||
throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalArgumentException("exception converting octets " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return bOut.toByteArray();
|
||||
}
|
||||
|
||||
private Vector octs;
|
||||
|
||||
/**
|
||||
* @param string the octets making up the octet string.
|
||||
*/
|
||||
public BERConstructedOctetString(
|
||||
byte[] string)
|
||||
{
|
||||
super(string);
|
||||
}
|
||||
|
||||
public BERConstructedOctetString(
|
||||
Vector octs)
|
||||
{
|
||||
super(toBytes(octs));
|
||||
|
||||
this.octs = octs;
|
||||
}
|
||||
|
||||
public BERConstructedOctetString(
|
||||
DERObject obj)
|
||||
{
|
||||
super(obj);
|
||||
}
|
||||
|
||||
public BERConstructedOctetString(
|
||||
DEREncodable obj)
|
||||
{
|
||||
super(obj.getDERObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getOctets()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the DER octets that make up this string.
|
||||
*/
|
||||
public Enumeration getObjects()
|
||||
{
|
||||
if (octs == null)
|
||||
{
|
||||
return generateOcts().elements();
|
||||
}
|
||||
|
||||
return octs.elements();
|
||||
}
|
||||
|
||||
private Vector generateOcts()
|
||||
{
|
||||
Vector vec = new Vector();
|
||||
for (int i = 0; i < string.length; i += MAX_LENGTH)
|
||||
{
|
||||
int end;
|
||||
|
||||
if (i + MAX_LENGTH > string.length)
|
||||
{
|
||||
end = string.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = i + MAX_LENGTH;
|
||||
}
|
||||
|
||||
byte[] nStr = new byte[end - i];
|
||||
|
||||
System.arraycopy(string, i, nStr, 0, nStr.length);
|
||||
|
||||
vec.addElement(new DEROctetString(nStr));
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
|
||||
{
|
||||
out.write(CONSTRUCTED | OCTET_STRING);
|
||||
|
||||
out.write(0x80);
|
||||
|
||||
//
|
||||
// write out the octet array
|
||||
//
|
||||
Enumeration e = getObjects();
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
out.writeObject(e.nextElement());
|
||||
}
|
||||
|
||||
out.write(0x00);
|
||||
out.write(0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.encode(out);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* @deprecated use BERSequence
|
||||
*/
|
||||
@Deprecated
|
||||
public class BERConstructedSequence
|
||||
extends DERConstructedSequence
|
||||
{
|
||||
/*
|
||||
*/
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
|
||||
{
|
||||
out.write(SEQUENCE | CONSTRUCTED);
|
||||
out.write(0x80);
|
||||
|
||||
Enumeration e = getObjects();
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
out.writeObject(e.nextElement());
|
||||
}
|
||||
|
||||
out.write(0x00);
|
||||
out.write(0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.encode(out);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
class BERFactory
|
||||
{
|
||||
static final BERSequence EMPTY_SEQUENCE = new BERSequence();
|
||||
static final BERSet EMPTY_SET = new BERSet();
|
||||
|
||||
static BERSequence createSequence(ASN1EncodableVector v)
|
||||
{
|
||||
return v.size() < 1 ? EMPTY_SEQUENCE : new BERSequence(v);
|
||||
}
|
||||
|
||||
static BERSet createSet(ASN1EncodableVector v)
|
||||
{
|
||||
return v.size() < 1 ? EMPTY_SET : new BERSet(v);
|
||||
}
|
||||
|
||||
static BERSet createSet(ASN1EncodableVector v, boolean needsSorting)
|
||||
{
|
||||
return v.size() < 1 ? EMPTY_SET : new BERSet(v, needsSorting);
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class BERGenerator
|
||||
extends ASN1Generator
|
||||
{
|
||||
private boolean _tagged = false;
|
||||
private boolean _isExplicit;
|
||||
private int _tagNo;
|
||||
|
||||
protected BERGenerator(
|
||||
OutputStream out)
|
||||
{
|
||||
super(out);
|
||||
}
|
||||
|
||||
public BERGenerator(
|
||||
OutputStream out,
|
||||
int tagNo,
|
||||
boolean isExplicit)
|
||||
{
|
||||
super(out);
|
||||
|
||||
_tagged = true;
|
||||
_isExplicit = isExplicit;
|
||||
_tagNo = tagNo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getRawOutputStream()
|
||||
{
|
||||
return _out;
|
||||
}
|
||||
|
||||
private void writeHdr(
|
||||
int tag)
|
||||
throws IOException
|
||||
{
|
||||
_out.write(tag);
|
||||
_out.write(0x80);
|
||||
}
|
||||
|
||||
protected void writeBERHeader(
|
||||
int tag)
|
||||
throws IOException
|
||||
{
|
||||
if (_tagged)
|
||||
{
|
||||
int tagNum = _tagNo | DERTags.TAGGED;
|
||||
|
||||
if (_isExplicit)
|
||||
{
|
||||
writeHdr(tagNum | DERTags.CONSTRUCTED);
|
||||
writeHdr(tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tag & DERTags.CONSTRUCTED) != 0)
|
||||
{
|
||||
writeHdr(tagNum | DERTags.CONSTRUCTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
writeHdr(tagNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeHdr(tag);
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeBERBody(
|
||||
InputStream contentStream)
|
||||
throws IOException
|
||||
{
|
||||
int ch;
|
||||
|
||||
while ((ch = contentStream.read()) >= 0)
|
||||
{
|
||||
_out.write(ch);
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeBEREnd()
|
||||
throws IOException
|
||||
{
|
||||
_out.write(0x00);
|
||||
_out.write(0x00);
|
||||
|
||||
if (_tagged && _isExplicit) // write extra end for tag header
|
||||
{
|
||||
_out.write(0x00);
|
||||
_out.write(0x00);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,214 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* @deprecated use ASN1InputStream
|
||||
*/
|
||||
@Deprecated
|
||||
public class BERInputStream
|
||||
extends DERInputStream
|
||||
{
|
||||
private static final DERObject END_OF_STREAM = new DERObject()
|
||||
{
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
throw new IOException("Eeek!");
|
||||
}
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(
|
||||
Object o)
|
||||
{
|
||||
return o == this;
|
||||
}
|
||||
};
|
||||
public BERInputStream(
|
||||
InputStream is)
|
||||
{
|
||||
super(is);
|
||||
}
|
||||
|
||||
/**
|
||||
* read a string of bytes representing an indefinite length object.
|
||||
*/
|
||||
private byte[] readIndefiniteLengthFully()
|
||||
throws IOException
|
||||
{
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
int b, b1;
|
||||
|
||||
b1 = read();
|
||||
|
||||
while ((b = read()) >= 0)
|
||||
{
|
||||
if (b1 == 0 && b == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
bOut.write(b1);
|
||||
b1 = b;
|
||||
}
|
||||
|
||||
return bOut.toByteArray();
|
||||
}
|
||||
|
||||
private BERConstructedOctetString buildConstructedOctetString()
|
||||
throws IOException
|
||||
{
|
||||
Vector octs = new Vector();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
DERObject o = readObject();
|
||||
|
||||
if (o == END_OF_STREAM)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
octs.addElement(o);
|
||||
}
|
||||
|
||||
return new BERConstructedOctetString(octs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DERObject readObject()
|
||||
throws IOException
|
||||
{
|
||||
int tag = read();
|
||||
if (tag == -1)
|
||||
{
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
int length = readLength();
|
||||
|
||||
if (length < 0) // indefinite length method
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case NULL:
|
||||
return null;
|
||||
case SEQUENCE | CONSTRUCTED:
|
||||
BERConstructedSequence seq = new BERConstructedSequence();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
DERObject obj = readObject();
|
||||
|
||||
if (obj == END_OF_STREAM)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
seq.addObject(obj);
|
||||
}
|
||||
return seq;
|
||||
case OCTET_STRING | CONSTRUCTED:
|
||||
return buildConstructedOctetString();
|
||||
case SET | CONSTRUCTED:
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
DERObject obj = readObject();
|
||||
|
||||
if (obj == END_OF_STREAM)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
v.add(obj);
|
||||
}
|
||||
return new BERSet(v);
|
||||
default:
|
||||
//
|
||||
// with tagged object tag number is bottom 5 bits
|
||||
//
|
||||
if ((tag & TAGGED) != 0)
|
||||
{
|
||||
if ((tag & 0x1f) == 0x1f)
|
||||
{
|
||||
throw new IOException("unsupported high tag encountered");
|
||||
}
|
||||
|
||||
//
|
||||
// simple type - implicit... return an octet string
|
||||
//
|
||||
if ((tag & CONSTRUCTED) == 0)
|
||||
{
|
||||
byte[] bytes = readIndefiniteLengthFully();
|
||||
|
||||
return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
|
||||
}
|
||||
|
||||
//
|
||||
// either constructed or explicitly tagged
|
||||
//
|
||||
DERObject dObj = readObject();
|
||||
|
||||
if (dObj == END_OF_STREAM) // empty tag!
|
||||
{
|
||||
return new DERTaggedObject(tag & 0x1f);
|
||||
}
|
||||
|
||||
DERObject next = readObject();
|
||||
|
||||
//
|
||||
// explicitly tagged (probably!) - if it isn't we'd have to
|
||||
// tell from the context
|
||||
//
|
||||
if (next == END_OF_STREAM)
|
||||
{
|
||||
return new BERTaggedObject(tag & 0x1f, dObj);
|
||||
}
|
||||
|
||||
//
|
||||
// another implicit object, we'll create a sequence...
|
||||
//
|
||||
seq = new BERConstructedSequence();
|
||||
|
||||
seq.addObject(dObj);
|
||||
|
||||
do
|
||||
{
|
||||
seq.addObject(next);
|
||||
next = readObject();
|
||||
}
|
||||
while (next != END_OF_STREAM);
|
||||
|
||||
return new BERTaggedObject(false, tag & 0x1f, seq);
|
||||
}
|
||||
|
||||
throw new IOException("unknown BER object encountered");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tag == 0 && length == 0) // end of contents marker.
|
||||
{
|
||||
return END_OF_STREAM;
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
readFully(bytes);
|
||||
|
||||
return buildObject(tag, bytes);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A BER NULL object.
|
||||
*/
|
||||
public class BERNull
|
||||
extends DERNull
|
||||
{
|
||||
public static final BERNull INSTANCE = new BERNull();
|
||||
|
||||
public BERNull()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
|
||||
{
|
||||
out.write(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.encode(out);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class BEROctetStringGenerator
|
||||
extends BERGenerator
|
||||
{
|
||||
public BEROctetStringGenerator(OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
super(out);
|
||||
|
||||
writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING);
|
||||
}
|
||||
|
||||
public BEROctetStringGenerator(
|
||||
OutputStream out,
|
||||
int tagNo,
|
||||
boolean isExplicit)
|
||||
throws IOException
|
||||
{
|
||||
super(out, tagNo, isExplicit);
|
||||
|
||||
writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING);
|
||||
}
|
||||
|
||||
public OutputStream getOctetOutputStream()
|
||||
{
|
||||
return getOctetOutputStream(new byte[1000]); // limit for CER encoding.
|
||||
}
|
||||
|
||||
public OutputStream getOctetOutputStream(
|
||||
byte[] buf)
|
||||
{
|
||||
return new BufferedBEROctetStream(buf);
|
||||
}
|
||||
|
||||
private class BufferedBEROctetStream
|
||||
extends OutputStream
|
||||
{
|
||||
private byte[] _buf;
|
||||
private int _off;
|
||||
private DEROutputStream _derOut;
|
||||
|
||||
BufferedBEROctetStream(
|
||||
byte[] buf)
|
||||
{
|
||||
_buf = buf;
|
||||
_off = 0;
|
||||
_derOut = new DEROutputStream(_out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(
|
||||
int b)
|
||||
throws IOException
|
||||
{
|
||||
_buf[_off++] = (byte)b;
|
||||
|
||||
if (_off == _buf.length)
|
||||
{
|
||||
DEROctetString.encode(_derOut, _buf);
|
||||
_off = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
int numToCopy = Math.min(len, _buf.length - _off);
|
||||
System.arraycopy(b, off, _buf, _off, numToCopy);
|
||||
|
||||
_off += numToCopy;
|
||||
if (_off < _buf.length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
DEROctetString.encode(_derOut, _buf);
|
||||
_off = 0;
|
||||
|
||||
off += numToCopy;
|
||||
len -= numToCopy;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
if (_off != 0)
|
||||
{
|
||||
byte[] bytes = new byte[_off];
|
||||
System.arraycopy(_buf, 0, bytes, 0, _off);
|
||||
|
||||
DEROctetString.encode(_derOut, bytes);
|
||||
}
|
||||
|
||||
writeBEREnd();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class BEROctetStringParser
|
||||
implements ASN1OctetStringParser
|
||||
{
|
||||
private ASN1StreamParser _parser;
|
||||
|
||||
BEROctetStringParser(
|
||||
ASN1StreamParser parser)
|
||||
{
|
||||
_parser = parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated will be removed
|
||||
*/
|
||||
@Deprecated
|
||||
protected BEROctetStringParser(
|
||||
ASN1ObjectParser parser)
|
||||
{
|
||||
_parser = parser._aIn;
|
||||
}
|
||||
|
||||
public InputStream getOctetStream()
|
||||
{
|
||||
return new ConstructedOctetStream(_parser);
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new BERConstructedOctetString(Streams.readAll(getOctetStream()));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class BEROutputStream
|
||||
extends DEROutputStream
|
||||
{
|
||||
public BEROutputStream(
|
||||
OutputStream os)
|
||||
{
|
||||
super(os);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeObject(
|
||||
Object obj)
|
||||
throws IOException
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
writeNull();
|
||||
}
|
||||
else if (obj instanceof DERObject)
|
||||
{
|
||||
((DERObject)obj).encode(this);
|
||||
}
|
||||
else if (obj instanceof DEREncodable)
|
||||
{
|
||||
((DEREncodable)obj).getDERObject().encode(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("object not BEREncodable");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class BERSequence
|
||||
extends DERSequence
|
||||
{
|
||||
/**
|
||||
* create an empty sequence
|
||||
*/
|
||||
public BERSequence()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* create a sequence containing one object
|
||||
*/
|
||||
public BERSequence(
|
||||
DEREncodable obj)
|
||||
{
|
||||
super(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a sequence containing a vector of objects.
|
||||
*/
|
||||
public BERSequence(
|
||||
DEREncodableVector v)
|
||||
{
|
||||
super(v);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
|
||||
{
|
||||
out.write(SEQUENCE | CONSTRUCTED);
|
||||
out.write(0x80);
|
||||
|
||||
Enumeration e = getObjects();
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
out.writeObject(e.nextElement());
|
||||
}
|
||||
|
||||
out.write(0x00);
|
||||
out.write(0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.encode(out);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class BERSequenceGenerator
|
||||
extends BERGenerator
|
||||
{
|
||||
public BERSequenceGenerator(
|
||||
OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
super(out);
|
||||
|
||||
writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE);
|
||||
}
|
||||
|
||||
public BERSequenceGenerator(
|
||||
OutputStream out,
|
||||
int tagNo,
|
||||
boolean isExplicit)
|
||||
throws IOException
|
||||
{
|
||||
super(out, tagNo, isExplicit);
|
||||
|
||||
writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE);
|
||||
}
|
||||
|
||||
public void addObject(
|
||||
DEREncodable object)
|
||||
throws IOException
|
||||
{
|
||||
object.getDERObject().encode(new BEROutputStream(_out));
|
||||
}
|
||||
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
writeBEREnd();
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BERSequenceParser
|
||||
implements ASN1SequenceParser
|
||||
{
|
||||
private ASN1StreamParser _parser;
|
||||
|
||||
BERSequenceParser(ASN1StreamParser parser)
|
||||
{
|
||||
this._parser = parser;
|
||||
}
|
||||
|
||||
public DEREncodable readObject()
|
||||
throws IOException
|
||||
{
|
||||
return _parser.readObject();
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new BERSequence(_parser.readVector());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalStateException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class BERSet
|
||||
extends DERSet
|
||||
{
|
||||
/**
|
||||
* create an empty sequence
|
||||
*/
|
||||
public BERSet()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* create a set containing one object
|
||||
*/
|
||||
public BERSet(
|
||||
DEREncodable obj)
|
||||
{
|
||||
super(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v - a vector of objects making up the set.
|
||||
*/
|
||||
public BERSet(
|
||||
DEREncodableVector v)
|
||||
{
|
||||
super(v, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v - a vector of objects making up the set.
|
||||
*/
|
||||
BERSet(
|
||||
DEREncodableVector v,
|
||||
boolean needsSorting)
|
||||
{
|
||||
super(v, needsSorting);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
|
||||
{
|
||||
out.write(SET | CONSTRUCTED);
|
||||
out.write(0x80);
|
||||
|
||||
Enumeration e = getObjects();
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
out.writeObject(e.nextElement());
|
||||
}
|
||||
|
||||
out.write(0x00);
|
||||
out.write(0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.encode(out);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BERSetParser
|
||||
implements ASN1SetParser
|
||||
{
|
||||
private ASN1StreamParser _parser;
|
||||
|
||||
BERSetParser(ASN1StreamParser parser)
|
||||
{
|
||||
this._parser = parser;
|
||||
}
|
||||
|
||||
public DEREncodable readObject()
|
||||
throws IOException
|
||||
{
|
||||
return _parser.readObject();
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new BERSet(_parser.readVector(), false);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ASN1ParsingException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* BER TaggedObject - in ASN.1 notation this is any object preceded by
|
||||
* a [n] where n is some number - these are assumed to follow the construction
|
||||
* rules (as with sequences).
|
||||
*/
|
||||
public class BERTaggedObject
|
||||
extends DERTaggedObject
|
||||
{
|
||||
/**
|
||||
* @param tagNo the tag number for this object.
|
||||
* @param obj the tagged object.
|
||||
*/
|
||||
public BERTaggedObject(
|
||||
int tagNo,
|
||||
DEREncodable obj)
|
||||
{
|
||||
super(tagNo, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param explicit true if an explicitly tagged object.
|
||||
* @param tagNo the tag number for this object.
|
||||
* @param obj the tagged object.
|
||||
*/
|
||||
public BERTaggedObject(
|
||||
boolean explicit,
|
||||
int tagNo,
|
||||
DEREncodable obj)
|
||||
{
|
||||
super(explicit, tagNo, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* create an implicitly tagged object that contains a zero
|
||||
* length sequence.
|
||||
*/
|
||||
public BERTaggedObject(
|
||||
int tagNo)
|
||||
{
|
||||
super(false, tagNo, new BERSequence());
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
|
||||
{
|
||||
out.writeTag(CONSTRUCTED | TAGGED, tagNo);
|
||||
out.write(0x80);
|
||||
|
||||
if (!empty)
|
||||
{
|
||||
if (!explicit)
|
||||
{
|
||||
Enumeration e;
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
if (obj instanceof BERConstructedOctetString)
|
||||
{
|
||||
e = ((BERConstructedOctetString)obj).getObjects();
|
||||
}
|
||||
else
|
||||
{
|
||||
ASN1OctetString octs = (ASN1OctetString)obj;
|
||||
BERConstructedOctetString berO = new BERConstructedOctetString(octs.getOctets());
|
||||
e = berO.getObjects();
|
||||
}
|
||||
}
|
||||
else if (obj instanceof ASN1Sequence)
|
||||
{
|
||||
e = ((ASN1Sequence)obj).getObjects();
|
||||
}
|
||||
else if (obj instanceof ASN1Set)
|
||||
{
|
||||
e = ((ASN1Set)obj).getObjects();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("not implemented: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
out.writeObject(e.nextElement());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out.writeObject(obj);
|
||||
}
|
||||
}
|
||||
|
||||
out.write(0x00);
|
||||
out.write(0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.encode(out);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class BERTaggedObjectParser
|
||||
implements ASN1TaggedObjectParser
|
||||
{
|
||||
private int _baseTag;
|
||||
private int _tagNumber;
|
||||
private InputStream _contentStream;
|
||||
|
||||
private boolean _indefiniteLength;
|
||||
|
||||
protected BERTaggedObjectParser(
|
||||
int baseTag,
|
||||
int tagNumber,
|
||||
InputStream contentStream)
|
||||
{
|
||||
_baseTag = baseTag;
|
||||
_tagNumber = tagNumber;
|
||||
_contentStream = contentStream;
|
||||
_indefiniteLength = contentStream instanceof IndefiniteLengthInputStream;
|
||||
}
|
||||
|
||||
public boolean isConstructed()
|
||||
{
|
||||
return (_baseTag & DERTags.CONSTRUCTED) != 0;
|
||||
}
|
||||
|
||||
public int getTagNo()
|
||||
{
|
||||
return _tagNumber;
|
||||
}
|
||||
|
||||
public DEREncodable getObjectParser(
|
||||
int tag,
|
||||
boolean isExplicit)
|
||||
throws IOException
|
||||
{
|
||||
if (isExplicit)
|
||||
{
|
||||
return new ASN1StreamParser(_contentStream).readObject();
|
||||
}
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case DERTags.SET:
|
||||
if (_indefiniteLength)
|
||||
{
|
||||
return new BERSetParser(new ASN1StreamParser(_contentStream));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DERSetParser(new ASN1StreamParser(_contentStream));
|
||||
}
|
||||
case DERTags.SEQUENCE:
|
||||
if (_indefiniteLength)
|
||||
{
|
||||
return new BERSequenceParser(new ASN1StreamParser(_contentStream));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DERSequenceParser(new ASN1StreamParser(_contentStream));
|
||||
}
|
||||
case DERTags.OCTET_STRING:
|
||||
// TODO Is the handling of definite length constructed encodings correct?
|
||||
if (_indefiniteLength || this.isConstructed())
|
||||
{
|
||||
return new BEROctetStringParser(new ASN1StreamParser(_contentStream));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DEROctetStringParser((DefiniteLengthInputStream)_contentStream);
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("implicit tagging not implemented");
|
||||
}
|
||||
|
||||
private ASN1EncodableVector rLoadVector(InputStream in)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ASN1StreamParser(in).readVector();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ASN1ParsingException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
if (_indefiniteLength)
|
||||
{
|
||||
ASN1EncodableVector v = rLoadVector(_contentStream);
|
||||
|
||||
return v.size() == 1
|
||||
? new BERTaggedObject(true, _tagNumber, v.get(0))
|
||||
: new BERTaggedObject(false, _tagNumber, BERFactory.createSequence(v));
|
||||
}
|
||||
|
||||
if (this.isConstructed())
|
||||
{
|
||||
ASN1EncodableVector v = rLoadVector(_contentStream);
|
||||
|
||||
return v.size() == 1
|
||||
? new DERTaggedObject(true, _tagNumber, v.get(0))
|
||||
: new DERTaggedObject(false, _tagNumber, DERFactory.createSequence(v));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_contentStream;
|
||||
return new DERTaggedObject(false, _tagNumber, new DEROctetString(defIn.toByteArray()));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalStateException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
class ConstructedOctetStream
|
||||
extends InputStream
|
||||
{
|
||||
private final ASN1StreamParser _parser;
|
||||
|
||||
private boolean _first = true;
|
||||
private InputStream _currentStream;
|
||||
|
||||
ConstructedOctetStream(
|
||||
ASN1StreamParser parser)
|
||||
{
|
||||
_parser = parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
if (_currentStream == null)
|
||||
{
|
||||
if (!_first)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
|
||||
|
||||
if (s == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
_first = false;
|
||||
_currentStream = s.getOctetStream();
|
||||
}
|
||||
|
||||
int totalRead = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int numRead = _currentStream.read(b, off + totalRead, len - totalRead);
|
||||
|
||||
if (numRead >= 0)
|
||||
{
|
||||
totalRead += numRead;
|
||||
|
||||
if (totalRead == len)
|
||||
{
|
||||
return totalRead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASN1OctetStringParser aos = (ASN1OctetStringParser)_parser.readObject();
|
||||
|
||||
if (aos == null)
|
||||
{
|
||||
_currentStream = null;
|
||||
return totalRead < 1 ? -1 : totalRead;
|
||||
}
|
||||
|
||||
_currentStream = aos.getOctetStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
if (_currentStream == null)
|
||||
{
|
||||
if (!_first)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
|
||||
|
||||
if (s == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
_first = false;
|
||||
_currentStream = s.getOctetStream();
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int b = _currentStream.read();
|
||||
|
||||
if (b >= 0)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
|
||||
ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
|
||||
|
||||
if (s == null)
|
||||
{
|
||||
_currentStream = null;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_currentStream = s.getOctetStream();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,228 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bouncycastle.util.Arrays;
|
||||
|
||||
/**
|
||||
* Base class for an application specific object
|
||||
*/
|
||||
public class DERApplicationSpecific
|
||||
extends ASN1Object
|
||||
{
|
||||
private final boolean isConstructed;
|
||||
private final int tag;
|
||||
private final byte[] octets;
|
||||
|
||||
DERApplicationSpecific(
|
||||
boolean isConstructed,
|
||||
int tag,
|
||||
byte[] octets)
|
||||
{
|
||||
this.isConstructed = isConstructed;
|
||||
this.tag = tag;
|
||||
this.octets = octets;
|
||||
}
|
||||
|
||||
public DERApplicationSpecific(
|
||||
int tag,
|
||||
byte[] octets)
|
||||
{
|
||||
this(false, tag, octets);
|
||||
}
|
||||
|
||||
public DERApplicationSpecific(
|
||||
int tag,
|
||||
DEREncodable object)
|
||||
throws IOException
|
||||
{
|
||||
this(true, tag, object);
|
||||
}
|
||||
|
||||
public DERApplicationSpecific(
|
||||
boolean explicit,
|
||||
int tag,
|
||||
DEREncodable object)
|
||||
throws IOException
|
||||
{
|
||||
byte[] data = object.getDERObject().getDEREncoded();
|
||||
|
||||
this.isConstructed = explicit;
|
||||
this.tag = tag;
|
||||
|
||||
if (explicit)
|
||||
{
|
||||
this.octets = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
int lenBytes = getLengthOfLength(data);
|
||||
byte[] tmp = new byte[data.length - lenBytes];
|
||||
System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
|
||||
this.octets = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
|
||||
{
|
||||
this.tag = tagNo;
|
||||
this.isConstructed = true;
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
|
||||
for (int i = 0; i != vec.size(); i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
bOut.write(((ASN1Encodable)vec.get(i)).getEncoded());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ASN1ParsingException("malformed object: " + e, e);
|
||||
}
|
||||
}
|
||||
this.octets = bOut.toByteArray();
|
||||
}
|
||||
|
||||
private int getLengthOfLength(byte[] data)
|
||||
{
|
||||
int count = 2; // TODO: assumes only a 1 byte tag number
|
||||
|
||||
while((data[count - 1] & 0x80) != 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean isConstructed()
|
||||
{
|
||||
return isConstructed;
|
||||
}
|
||||
|
||||
public byte[] getContents()
|
||||
{
|
||||
return octets;
|
||||
}
|
||||
|
||||
public int getApplicationTag()
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the enclosed object assuming explicit tagging.
|
||||
*
|
||||
* @return the resulting object
|
||||
* @throws IOException if reconstruction fails.
|
||||
*/
|
||||
public DERObject getObject()
|
||||
throws IOException
|
||||
{
|
||||
return new ASN1InputStream(getContents()).readObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the enclosed object assuming implicit tagging.
|
||||
*
|
||||
* @param derTagNo the type tag that should be applied to the object's contents.
|
||||
* @return the resulting object
|
||||
* @throws IOException if reconstruction fails.
|
||||
*/
|
||||
public DERObject getObject(int derTagNo)
|
||||
throws IOException
|
||||
{
|
||||
if (derTagNo >= 0x1f)
|
||||
{
|
||||
throw new IOException("unsupported tag number");
|
||||
}
|
||||
|
||||
byte[] orig = this.getEncoded();
|
||||
byte[] tmp = replaceTagNumber(derTagNo, orig);
|
||||
|
||||
if ((orig[0] & DERTags.CONSTRUCTED) != 0)
|
||||
{
|
||||
tmp[0] |= DERTags.CONSTRUCTED;
|
||||
}
|
||||
|
||||
return new ASN1InputStream(tmp).readObject();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream)
|
||||
*/
|
||||
@Override
|
||||
void encode(DEROutputStream out) throws IOException
|
||||
{
|
||||
int classBits = DERTags.APPLICATION;
|
||||
if (isConstructed)
|
||||
{
|
||||
classBits |= DERTags.CONSTRUCTED;
|
||||
}
|
||||
|
||||
out.writeEncoded(classBits, tag, octets);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERApplicationSpecific))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DERApplicationSpecific other = (DERApplicationSpecific)o;
|
||||
|
||||
return isConstructed == other.isConstructed
|
||||
&& tag == other.tag
|
||||
&& Arrays.areEqual(octets, other.octets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
|
||||
}
|
||||
|
||||
private byte[] replaceTagNumber(int newTag, byte[] input)
|
||||
throws IOException
|
||||
{
|
||||
int tagNo = input[0] & 0x1f;
|
||||
int index = 1;
|
||||
//
|
||||
// with tagged object tag number is bottom 5 bits, or stored at the start of the content
|
||||
//
|
||||
if (tagNo == 0x1f)
|
||||
{
|
||||
tagNo = 0;
|
||||
|
||||
int b = input[index++] & 0xff;
|
||||
|
||||
// X.690-0207 8.1.2.4.2
|
||||
// "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
|
||||
if ((b & 0x7f) == 0) // Note: -1 will pass
|
||||
{
|
||||
throw new ASN1ParsingException("corrupted stream - invalid high tag number found");
|
||||
}
|
||||
|
||||
while ((b >= 0) && ((b & 0x80) != 0))
|
||||
{
|
||||
tagNo |= (b & 0x7f);
|
||||
tagNo <<= 7;
|
||||
b = input[index++] & 0xff;
|
||||
}
|
||||
|
||||
tagNo |= (b & 0x7f);
|
||||
}
|
||||
|
||||
byte[] tmp = new byte[input.length - index + 1];
|
||||
|
||||
System.arraycopy(input, index, tmp, 1, tmp.length - 1);
|
||||
|
||||
tmp[0] = (byte)newTag;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DER BMPString object.
|
||||
*/
|
||||
public class DERBMPString
|
||||
extends ASN1Object
|
||||
implements DERString
|
||||
{
|
||||
String string;
|
||||
|
||||
/**
|
||||
* return a BMP String from the given object.
|
||||
*
|
||||
* @param obj the object we want converted.
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERBMPString getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERBMPString)
|
||||
{
|
||||
return (DERBMPString)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERBMPString(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return a BMP String from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERBMPString getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* basic constructor - byte encoded string.
|
||||
*/
|
||||
public DERBMPString(
|
||||
byte[] string)
|
||||
{
|
||||
char[] cs = new char[string.length / 2];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
|
||||
}
|
||||
|
||||
this.string = new String(cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor
|
||||
*/
|
||||
public DERBMPString(
|
||||
String string)
|
||||
{
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERBMPString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DERBMPString s = (DERBMPString)o;
|
||||
|
||||
return this.getString().equals(s.getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
char[] c = string.toCharArray();
|
||||
byte[] b = new byte[c.length * 2];
|
||||
|
||||
for (int i = 0; i != c.length; i++)
|
||||
{
|
||||
b[2 * i] = (byte)(c[i] >> 8);
|
||||
b[2 * i + 1] = (byte)c[i];
|
||||
}
|
||||
|
||||
out.writeEncoded(BMP_STRING, b);
|
||||
}
|
||||
}
|
@ -1,270 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import org.bouncycastle.util.Arrays;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DERBitString
|
||||
extends ASN1Object
|
||||
implements DERString
|
||||
{
|
||||
private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
protected byte[] data;
|
||||
protected int padBits;
|
||||
|
||||
/**
|
||||
* return the correct number of pad bits for a bit string defined in
|
||||
* a 32 bit constant
|
||||
*/
|
||||
static protected int getPadBits(
|
||||
int bitString)
|
||||
{
|
||||
int val = 0;
|
||||
for (int i = 3; i >= 0; i--)
|
||||
{
|
||||
//
|
||||
// this may look a little odd, but if it isn't done like this pre jdk1.2
|
||||
// JVM's break!
|
||||
//
|
||||
if (i != 0)
|
||||
{
|
||||
if ((bitString >> (i * 8)) != 0)
|
||||
{
|
||||
val = (bitString >> (i * 8)) & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bitString != 0)
|
||||
{
|
||||
val = bitString & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (val == 0)
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
|
||||
|
||||
int bits = 1;
|
||||
|
||||
while (((val <<= 1) & 0xFF) != 0)
|
||||
{
|
||||
bits++;
|
||||
}
|
||||
|
||||
return 8 - bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the correct number of bytes for a bit string defined in
|
||||
* a 32 bit constant
|
||||
*/
|
||||
static protected byte[] getBytes(int bitString)
|
||||
{
|
||||
int bytes = 4;
|
||||
for (int i = 3; i >= 1; i--)
|
||||
{
|
||||
if ((bitString & (0xFF << (i * 8))) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes--;
|
||||
}
|
||||
|
||||
byte[] result = new byte[bytes];
|
||||
for (int i = 0; i < bytes; i++)
|
||||
{
|
||||
result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a Bit String from the passed in object
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERBitString getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERBitString)
|
||||
{
|
||||
return (DERBitString)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
byte[] bytes = ((ASN1OctetString)obj).getOctets();
|
||||
int padBits = bytes[0];
|
||||
byte[] data = new byte[bytes.length - 1];
|
||||
|
||||
System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
|
||||
|
||||
return new DERBitString(data, padBits);
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return a Bit String from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERBitString getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
protected DERBitString(
|
||||
byte data,
|
||||
int padBits)
|
||||
{
|
||||
this.data = new byte[1];
|
||||
this.data[0] = data;
|
||||
this.padBits = padBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data the octets making up the bit string.
|
||||
* @param padBits the number of extra bits at the end of the string.
|
||||
*/
|
||||
public DERBitString(
|
||||
byte[] data,
|
||||
int padBits)
|
||||
{
|
||||
this.data = data;
|
||||
this.padBits = padBits;
|
||||
}
|
||||
|
||||
public DERBitString(
|
||||
byte[] data)
|
||||
{
|
||||
this(data, 0);
|
||||
}
|
||||
|
||||
public DERBitString(
|
||||
DEREncodable obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.data = obj.getDERObject().getEncoded(ASN1Encodable.DER);
|
||||
this.padBits = 0;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalArgumentException("Error processing object : " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getBytes()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getPadBits()
|
||||
{
|
||||
return padBits;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the value of the bit string as an int (truncating if necessary)
|
||||
*/
|
||||
public int intValue()
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
for (int i = 0; i != data.length && i != 4; i++)
|
||||
{
|
||||
value |= (data[i] & 0xff) << (8 * i);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
byte[] bytes = new byte[getBytes().length + 1];
|
||||
|
||||
bytes[0] = (byte)getPadBits();
|
||||
System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
|
||||
|
||||
out.writeEncoded(BIT_STRING, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return padBits ^ Arrays.hashCode(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERBitString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DERBitString other = (DERBitString)o;
|
||||
|
||||
return this.padBits == other.padBits
|
||||
&& Arrays.areEqual(this.data, other.data);
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer("#");
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
|
||||
|
||||
try
|
||||
{
|
||||
aOut.writeObject(this);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException("internal error encoding BitString");
|
||||
}
|
||||
|
||||
byte[] string = bOut.toByteArray();
|
||||
|
||||
for (int i = 0; i != string.length; i++)
|
||||
{
|
||||
buf.append(table[(string[i] >>> 4) & 0xf]);
|
||||
buf.append(table[string[i] & 0xf]);
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getString();
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DERBoolean
|
||||
extends ASN1Object
|
||||
{
|
||||
byte value;
|
||||
|
||||
public static final DERBoolean FALSE = new DERBoolean(false);
|
||||
public static final DERBoolean TRUE = new DERBoolean(true);
|
||||
|
||||
/**
|
||||
* return a boolean from the passed in object.
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERBoolean getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERBoolean)
|
||||
{
|
||||
return (DERBoolean)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERBoolean(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return a DERBoolean from the passed in boolean.
|
||||
*/
|
||||
public static DERBoolean getInstance(
|
||||
boolean value)
|
||||
{
|
||||
return (value ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* return a Boolean from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERBoolean getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
public DERBoolean(
|
||||
byte[] value)
|
||||
{
|
||||
this.value = value[0];
|
||||
}
|
||||
|
||||
public DERBoolean(
|
||||
boolean value)
|
||||
{
|
||||
this.value = (value) ? (byte)0xff : (byte)0;
|
||||
}
|
||||
|
||||
public boolean isTrue()
|
||||
{
|
||||
return (value != 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
byte[] bytes = new byte[1];
|
||||
|
||||
bytes[0] = value;
|
||||
|
||||
out.writeEncoded(BOOLEAN, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if ((o == null) || !(o instanceof DERBoolean))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (value == ((DERBoolean)o).value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return (value != 0) ? "TRUE" : "FALSE";
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* @deprecated use DERSequence.
|
||||
*/
|
||||
@Deprecated
|
||||
public class DERConstructedSequence
|
||||
extends ASN1Sequence
|
||||
{
|
||||
@Override
|
||||
public void addObject(
|
||||
DEREncodable obj)
|
||||
{
|
||||
super.addObject(obj);
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
/*
|
||||
* A note on the implementation:
|
||||
* <p>
|
||||
* As DER requires the constructed, definite-length model to
|
||||
* be used for structured types, this varies slightly from the
|
||||
* ASN.1 descriptions given. Rather than just outputing SEQUENCE,
|
||||
* we also have to specify CONSTRUCTED, and the objects length.
|
||||
*/
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
DEROutputStream dOut = new DEROutputStream(bOut);
|
||||
Enumeration e = this.getObjects();
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
Object obj = e.nextElement();
|
||||
|
||||
dOut.writeObject(obj);
|
||||
}
|
||||
|
||||
dOut.close();
|
||||
|
||||
byte[] bytes = bOut.toByteArray();
|
||||
|
||||
out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated use DERSet
|
||||
*/
|
||||
@Deprecated
|
||||
public class DERConstructedSet
|
||||
extends ASN1Set
|
||||
{
|
||||
public DERConstructedSet()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param obj - a single object that makes up the set.
|
||||
*/
|
||||
public DERConstructedSet(
|
||||
DEREncodable obj)
|
||||
{
|
||||
this.addObject(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v - a vector of objects making up the set.
|
||||
*/
|
||||
public DERConstructedSet(
|
||||
DEREncodableVector v)
|
||||
{
|
||||
for (int i = 0; i != v.size(); i++)
|
||||
{
|
||||
this.addObject(v.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addObject(
|
||||
DEREncodable obj)
|
||||
{
|
||||
super.addObject(obj);
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
/*
|
||||
* A note on the implementation:
|
||||
* <p>
|
||||
* As DER requires the constructed, definite-length model to
|
||||
* be used for structured types, this varies slightly from the
|
||||
* ASN.1 descriptions given. Rather than just outputing SET,
|
||||
* we also have to specify CONSTRUCTED, and the objects length.
|
||||
*/
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
DEROutputStream dOut = new DEROutputStream(bOut);
|
||||
Enumeration e = this.getObjects();
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
Object obj = e.nextElement();
|
||||
|
||||
dOut.writeObject(obj);
|
||||
}
|
||||
|
||||
dOut.close();
|
||||
|
||||
byte[] bytes = bOut.toByteArray();
|
||||
|
||||
out.writeEncoded(SET | CONSTRUCTED, bytes);
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
public interface DEREncodable
|
||||
{
|
||||
public DERObject getDERObject();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* a general class for building up a vector of DER encodable objects -
|
||||
* this will eventually be superceded by ASN1EncodableVector so you should
|
||||
* use that class in preference.
|
||||
*/
|
||||
public class DEREncodableVector
|
||||
{
|
||||
Vector v = new Vector();
|
||||
|
||||
/**
|
||||
* @deprecated use ASN1EncodableVector instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public DEREncodableVector()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void add(
|
||||
DEREncodable obj)
|
||||
{
|
||||
v.addElement(obj);
|
||||
}
|
||||
|
||||
public DEREncodable get(
|
||||
int i)
|
||||
{
|
||||
return (DEREncodable)v.elementAt(i);
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return v.size();
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import org.bouncycastle.util.Arrays;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class DEREnumerated
|
||||
extends ASN1Object
|
||||
{
|
||||
byte[] bytes;
|
||||
|
||||
/**
|
||||
* return an integer from the passed in object
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DEREnumerated getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DEREnumerated)
|
||||
{
|
||||
return (DEREnumerated)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DEREnumerated(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return an Enumerated from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DEREnumerated getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
public DEREnumerated(
|
||||
int value)
|
||||
{
|
||||
bytes = BigInteger.valueOf(value).toByteArray();
|
||||
}
|
||||
|
||||
public DEREnumerated(
|
||||
BigInteger value)
|
||||
{
|
||||
bytes = value.toByteArray();
|
||||
}
|
||||
|
||||
public DEREnumerated(
|
||||
byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public BigInteger getValue()
|
||||
{
|
||||
return new BigInteger(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(ENUMERATED, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DEREnumerated))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DEREnumerated other = (DEREnumerated)o;
|
||||
|
||||
return Arrays.areEqual(this.bytes, other.bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Arrays.hashCode(bytes);
|
||||
}
|
||||
}
|
@ -1,270 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Class representing the DER-type External
|
||||
*/
|
||||
public class DERExternal
|
||||
extends ASN1Object
|
||||
{
|
||||
private DERObjectIdentifier directReference;
|
||||
private DERInteger indirectReference;
|
||||
private ASN1Object dataValueDescriptor;
|
||||
private int encoding;
|
||||
private DERObject externalContent;
|
||||
|
||||
public DERExternal(ASN1EncodableVector vector)
|
||||
{
|
||||
int offset = 0;
|
||||
DERObject enc = vector.get(offset).getDERObject();
|
||||
if (enc instanceof DERObjectIdentifier)
|
||||
{
|
||||
directReference = (DERObjectIdentifier)enc;
|
||||
offset++;
|
||||
enc = vector.get(offset).getDERObject();
|
||||
}
|
||||
if (enc instanceof DERInteger)
|
||||
{
|
||||
indirectReference = (DERInteger) enc;
|
||||
offset++;
|
||||
enc = vector.get(offset).getDERObject();
|
||||
}
|
||||
if (!(enc instanceof DERTaggedObject))
|
||||
{
|
||||
dataValueDescriptor = (ASN1Object) enc;
|
||||
offset++;
|
||||
enc = vector.get(offset).getDERObject();
|
||||
}
|
||||
if (!(enc instanceof DERTaggedObject))
|
||||
{
|
||||
throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External");
|
||||
}
|
||||
DERTaggedObject obj = (DERTaggedObject)enc;
|
||||
setEncoding(obj.getTagNo());
|
||||
externalContent = obj.getObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of DERExternal
|
||||
* See X.690 for more informations about the meaning of these parameters
|
||||
* @param directReference The direct reference or <code>null</code> if not set.
|
||||
* @param indirectReference The indirect reference or <code>null</code> if not set.
|
||||
* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
|
||||
* @param externalData The external data in its encoded form.
|
||||
*/
|
||||
public DERExternal(DERObjectIdentifier directReference, DERInteger indirectReference, ASN1Object dataValueDescriptor, DERTaggedObject externalData)
|
||||
{
|
||||
this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.getDERObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of DERExternal.
|
||||
* See X.690 for more informations about the meaning of these parameters
|
||||
* @param directReference The direct reference or <code>null</code> if not set.
|
||||
* @param indirectReference The indirect reference or <code>null</code> if not set.
|
||||
* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
|
||||
* @param encoding The encoding to be used for the external data
|
||||
* @param externalData The external data
|
||||
*/
|
||||
public DERExternal(DERObjectIdentifier directReference, DERInteger indirectReference, ASN1Object dataValueDescriptor, int encoding, DERObject externalData)
|
||||
{
|
||||
setDirectReference(directReference);
|
||||
setIndirectReference(indirectReference);
|
||||
setDataValueDescriptor(dataValueDescriptor);
|
||||
setEncoding(encoding);
|
||||
setExternalContent(externalData.getDERObject());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int ret = 0;
|
||||
if (directReference != null)
|
||||
{
|
||||
ret = directReference.hashCode();
|
||||
}
|
||||
if (indirectReference != null)
|
||||
{
|
||||
ret ^= indirectReference.hashCode();
|
||||
}
|
||||
if (dataValueDescriptor != null)
|
||||
{
|
||||
ret ^= dataValueDescriptor.hashCode();
|
||||
}
|
||||
ret ^= externalContent.hashCode();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream)
|
||||
*/
|
||||
@Override
|
||||
void encode(DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
if (directReference != null)
|
||||
{
|
||||
baos.write(directReference.getDEREncoded());
|
||||
}
|
||||
if (indirectReference != null)
|
||||
{
|
||||
baos.write(indirectReference.getDEREncoded());
|
||||
}
|
||||
if (dataValueDescriptor != null)
|
||||
{
|
||||
baos.write(dataValueDescriptor.getDEREncoded());
|
||||
}
|
||||
DERTaggedObject obj = new DERTaggedObject(encoding, externalContent);
|
||||
baos.write(obj.getDEREncoded());
|
||||
out.writeEncoded(DERTags.CONSTRUCTED, DERTags.EXTERNAL, baos.toByteArray());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.bouncycastle.asn1.ASN1Object#asn1Equals(org.bouncycastle.asn1.DERObject)
|
||||
*/
|
||||
@Override
|
||||
boolean asn1Equals(DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERExternal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
DERExternal other = (DERExternal)o;
|
||||
if (directReference != null)
|
||||
{
|
||||
if (other.directReference == null || !other.directReference.equals(directReference))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (indirectReference != null)
|
||||
{
|
||||
if (other.indirectReference == null || !other.indirectReference.equals(indirectReference))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (dataValueDescriptor != null)
|
||||
{
|
||||
if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return externalContent.equals(other.externalContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data value descriptor
|
||||
* @return The descriptor
|
||||
*/
|
||||
public ASN1Object getDataValueDescriptor()
|
||||
{
|
||||
return dataValueDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the direct reference of the external element
|
||||
* @return The reference
|
||||
*/
|
||||
public DERObjectIdentifier getDirectReference()
|
||||
{
|
||||
return directReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encoding of the content. Valid values are
|
||||
* <ul>
|
||||
* <li><code>0</code> single-ASN1-type</li>
|
||||
* <li><code>1</code> OCTET STRING</li>
|
||||
* <li><code>2</code> BIT STRING</li>
|
||||
* </ul>
|
||||
* @return The encoding
|
||||
*/
|
||||
public int getEncoding()
|
||||
{
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content of this element
|
||||
* @return The content
|
||||
*/
|
||||
public DERObject getExternalContent()
|
||||
{
|
||||
return externalContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the indirect reference of this element
|
||||
* @return The reference
|
||||
*/
|
||||
public DERInteger getIndirectReference()
|
||||
{
|
||||
return indirectReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data value descriptor
|
||||
* @param dataValueDescriptor The descriptor
|
||||
*/
|
||||
private void setDataValueDescriptor(ASN1Object dataValueDescriptor)
|
||||
{
|
||||
this.dataValueDescriptor = dataValueDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the direct reference of the external element
|
||||
* @param directReferemce The reference
|
||||
*/
|
||||
private void setDirectReference(DERObjectIdentifier directReferemce)
|
||||
{
|
||||
this.directReference = directReferemce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the encoding of the content. Valid values are
|
||||
* <ul>
|
||||
* <li><code>0</code> single-ASN1-type</li>
|
||||
* <li><code>1</code> OCTET STRING</li>
|
||||
* <li><code>2</code> BIT STRING</li>
|
||||
* </ul>
|
||||
* @param encoding The encoding
|
||||
*/
|
||||
private void setEncoding(int encoding)
|
||||
{
|
||||
if (encoding < 0 || encoding > 2)
|
||||
{
|
||||
throw new IllegalArgumentException("invalid encoding value: " + encoding);
|
||||
}
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content of this element
|
||||
* @param externalContent The content
|
||||
*/
|
||||
private void setExternalContent(DERObject externalContent)
|
||||
{
|
||||
this.externalContent = externalContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the indirect reference of this element
|
||||
* @param indirectReference The reference
|
||||
*/
|
||||
private void setIndirectReference(DERInteger indirectReference)
|
||||
{
|
||||
this.indirectReference = indirectReference;
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DERExternalParser
|
||||
implements DEREncodable
|
||||
{
|
||||
private ASN1StreamParser _parser;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public DERExternalParser(ASN1StreamParser parser)
|
||||
{
|
||||
this._parser = parser;
|
||||
}
|
||||
|
||||
public DEREncodable readObject()
|
||||
throws IOException
|
||||
{
|
||||
return _parser.readObject();
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new DERExternal(_parser.readVector());
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new ASN1ParsingException("unable to get DER object", ioe);
|
||||
}
|
||||
catch (IllegalArgumentException ioe)
|
||||
{
|
||||
throw new ASN1ParsingException("unable to get DER object", ioe);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
class DERFactory
|
||||
{
|
||||
static final DERSequence EMPTY_SEQUENCE = new DERSequence();
|
||||
static final DERSet EMPTY_SET = new DERSet();
|
||||
|
||||
static DERSequence createSequence(ASN1EncodableVector v)
|
||||
{
|
||||
return v.size() < 1 ? EMPTY_SEQUENCE : new DERSequence(v);
|
||||
}
|
||||
|
||||
static DERSet createSet(ASN1EncodableVector v)
|
||||
{
|
||||
return v.size() < 1 ? EMPTY_SET : new DERSet(v);
|
||||
}
|
||||
|
||||
static DERSet createSet(ASN1EncodableVector v, boolean needsSorting)
|
||||
{
|
||||
return v.size() < 1 ? EMPTY_SET : new DERSet(v, needsSorting);
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DERGeneralString
|
||||
extends ASN1Object implements DERString
|
||||
{
|
||||
private String string;
|
||||
|
||||
public static DERGeneralString getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERGeneralString)
|
||||
{
|
||||
return (DERGeneralString) obj;
|
||||
}
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERGeneralString(((ASN1OctetString) obj).getOctets());
|
||||
}
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject) obj).getObject());
|
||||
}
|
||||
throw new IllegalArgumentException("illegal object in getInstance: "
|
||||
+ obj.getClass().getName());
|
||||
}
|
||||
|
||||
public static DERGeneralString getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
public DERGeneralString(byte[] string)
|
||||
{
|
||||
char[] cs = new char[string.length];
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
cs[i] = (char)(string[i] & 0xff);
|
||||
}
|
||||
this.string = new String(cs);
|
||||
}
|
||||
|
||||
public DERGeneralString(String string)
|
||||
{
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
public byte[] getOctets()
|
||||
{
|
||||
char[] cs = string.toCharArray();
|
||||
byte[] bs = new byte[cs.length];
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
bs[i] = (byte) cs[i];
|
||||
}
|
||||
return bs;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(GENERAL_STRING, this.getOctets());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERGeneralString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DERGeneralString s = (DERGeneralString) o;
|
||||
return this.getString().equals(s.getString());
|
||||
}
|
||||
}
|
@ -1,317 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Generalized time object.
|
||||
*/
|
||||
public class DERGeneralizedTime
|
||||
extends ASN1Object
|
||||
{
|
||||
String time;
|
||||
|
||||
/**
|
||||
* return a generalized time from the passed in object
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERGeneralizedTime getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERGeneralizedTime)
|
||||
{
|
||||
return (DERGeneralizedTime)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERGeneralizedTime(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return a Generalized Time object from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERGeneralizedTime getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
|
||||
* for local time, or Z+-HHMM on the end, for difference between local
|
||||
* time and UTC time. The fractional second amount f must consist of at
|
||||
* least one number with trailing zeroes removed.
|
||||
*
|
||||
* @param time the time string.
|
||||
* @exception IllegalArgumentException if String is an illegal format.
|
||||
*/
|
||||
public DERGeneralizedTime(
|
||||
String time)
|
||||
{
|
||||
this.time = time;
|
||||
try
|
||||
{
|
||||
this.getDate();
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
throw new IllegalArgumentException("invalid date string: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* base constructer from a java.util.date object
|
||||
*/
|
||||
public DERGeneralizedTime(
|
||||
Date time)
|
||||
{
|
||||
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
|
||||
|
||||
dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
|
||||
|
||||
this.time = dateF.format(time);
|
||||
}
|
||||
|
||||
DERGeneralizedTime(
|
||||
byte[] bytes)
|
||||
{
|
||||
//
|
||||
// explicitly convert to characters
|
||||
//
|
||||
char[] dateC = new char[bytes.length];
|
||||
|
||||
for (int i = 0; i != dateC.length; i++)
|
||||
{
|
||||
dateC[i] = (char)(bytes[i] & 0xff);
|
||||
}
|
||||
|
||||
this.time = new String(dateC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time.
|
||||
* @return The time string as it appeared in the encoded object.
|
||||
*/
|
||||
public String getTimeString()
|
||||
{
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the time - always in the form of
|
||||
* YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
|
||||
* <p>
|
||||
* Normally in a certificate we would expect "Z" rather than "GMT",
|
||||
* however adding the "GMT" means we can just use:
|
||||
* <pre>
|
||||
* dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
|
||||
* </pre>
|
||||
* To read in the time and get a date which is compatible with our local
|
||||
* time zone.
|
||||
*/
|
||||
public String getTime()
|
||||
{
|
||||
//
|
||||
// standardise the format.
|
||||
//
|
||||
if (time.charAt(time.length() - 1) == 'Z')
|
||||
{
|
||||
return time.substring(0, time.length() - 1) + "GMT+00:00";
|
||||
}
|
||||
else
|
||||
{
|
||||
int signPos = time.length() - 5;
|
||||
char sign = time.charAt(signPos);
|
||||
if (sign == '-' || sign == '+')
|
||||
{
|
||||
return time.substring(0, signPos)
|
||||
+ "GMT"
|
||||
+ time.substring(signPos, signPos + 3)
|
||||
+ ":"
|
||||
+ time.substring(signPos + 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
signPos = time.length() - 3;
|
||||
sign = time.charAt(signPos);
|
||||
if (sign == '-' || sign == '+')
|
||||
{
|
||||
return time.substring(0, signPos)
|
||||
+ "GMT"
|
||||
+ time.substring(signPos)
|
||||
+ ":00";
|
||||
}
|
||||
}
|
||||
}
|
||||
return time + calculateGMTOffset();
|
||||
}
|
||||
|
||||
private String calculateGMTOffset()
|
||||
{
|
||||
String sign = "+";
|
||||
TimeZone timeZone = TimeZone.getDefault();
|
||||
int offset = timeZone.getRawOffset();
|
||||
if (offset < 0)
|
||||
{
|
||||
sign = "-";
|
||||
offset = -offset;
|
||||
}
|
||||
int hours = offset / (60 * 60 * 1000);
|
||||
int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
|
||||
|
||||
try
|
||||
{
|
||||
if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
|
||||
{
|
||||
hours += sign.equals("+") ? 1 : -1;
|
||||
}
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
// we'll do our best and ignore daylight savings
|
||||
}
|
||||
|
||||
return "GMT" + sign + convert(hours) + ":" + convert(minutes);
|
||||
}
|
||||
|
||||
private String convert(int time)
|
||||
{
|
||||
if (time < 10)
|
||||
{
|
||||
return "0" + time;
|
||||
}
|
||||
|
||||
return Integer.toString(time);
|
||||
}
|
||||
|
||||
public Date getDate()
|
||||
throws ParseException
|
||||
{
|
||||
SimpleDateFormat dateF;
|
||||
String d = time;
|
||||
|
||||
if (time.endsWith("Z"))
|
||||
{
|
||||
if (hasFractionalSeconds())
|
||||
{
|
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
|
||||
}
|
||||
else
|
||||
{
|
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
|
||||
}
|
||||
|
||||
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
|
||||
}
|
||||
else if (time.indexOf('-') > 0 || time.indexOf('+') > 0)
|
||||
{
|
||||
d = this.getTime();
|
||||
if (hasFractionalSeconds())
|
||||
{
|
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
|
||||
}
|
||||
else
|
||||
{
|
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
|
||||
}
|
||||
|
||||
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hasFractionalSeconds())
|
||||
{
|
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
|
||||
}
|
||||
else
|
||||
{
|
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
}
|
||||
|
||||
dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
|
||||
}
|
||||
|
||||
if (hasFractionalSeconds())
|
||||
{
|
||||
// java misinterprets extra digits as being milliseconds...
|
||||
String frac = d.substring(14);
|
||||
int index;
|
||||
for (index = 1; index < frac.length(); index++)
|
||||
{
|
||||
char ch = frac.charAt(index);
|
||||
if (!('0' <= ch && ch <= '9'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index - 1 > 3)
|
||||
{
|
||||
frac = frac.substring(0, 4) + frac.substring(index);
|
||||
d = d.substring(0, 14) + frac;
|
||||
}
|
||||
}
|
||||
|
||||
return dateF.parse(d);
|
||||
}
|
||||
|
||||
private boolean hasFractionalSeconds()
|
||||
{
|
||||
return time.indexOf('.') == 14;
|
||||
}
|
||||
|
||||
private byte[] getOctets()
|
||||
{
|
||||
char[] cs = time.toCharArray();
|
||||
byte[] bs = new byte[cs.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
bs[i] = (byte)cs[i];
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(GENERALIZED_TIME, this.getOctets());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERGeneralizedTime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return time.equals(((DERGeneralizedTime)o).time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return time.hashCode();
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public abstract class DERGenerator
|
||||
extends ASN1Generator
|
||||
{
|
||||
private boolean _tagged = false;
|
||||
private boolean _isExplicit;
|
||||
private int _tagNo;
|
||||
|
||||
protected DERGenerator(
|
||||
OutputStream out)
|
||||
{
|
||||
super(out);
|
||||
}
|
||||
|
||||
public DERGenerator(
|
||||
OutputStream out,
|
||||
int tagNo,
|
||||
boolean isExplicit)
|
||||
{
|
||||
super(out);
|
||||
|
||||
_tagged = true;
|
||||
_isExplicit = isExplicit;
|
||||
_tagNo = tagNo;
|
||||
}
|
||||
|
||||
private void writeLength(
|
||||
OutputStream out,
|
||||
int length)
|
||||
throws IOException
|
||||
{
|
||||
if (length > 127)
|
||||
{
|
||||
int size = 1;
|
||||
int val = length;
|
||||
|
||||
while ((val >>>= 8) != 0)
|
||||
{
|
||||
size++;
|
||||
}
|
||||
|
||||
out.write((byte)(size | 0x80));
|
||||
|
||||
for (int i = (size - 1) * 8; i >= 0; i -= 8)
|
||||
{
|
||||
out.write((byte)(length >> i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write((byte)length);
|
||||
}
|
||||
}
|
||||
|
||||
void writeDEREncoded(
|
||||
OutputStream out,
|
||||
int tag,
|
||||
byte[] bytes)
|
||||
throws IOException
|
||||
{
|
||||
out.write(tag);
|
||||
writeLength(out, bytes.length);
|
||||
out.write(bytes);
|
||||
}
|
||||
|
||||
void writeDEREncoded(
|
||||
int tag,
|
||||
byte[] bytes)
|
||||
throws IOException
|
||||
{
|
||||
if (_tagged)
|
||||
{
|
||||
int tagNum = _tagNo | DERTags.TAGGED;
|
||||
|
||||
if (_isExplicit)
|
||||
{
|
||||
int newTag = _tagNo | DERTags.CONSTRUCTED | DERTags.TAGGED;
|
||||
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
|
||||
writeDEREncoded(bOut, tag, bytes);
|
||||
|
||||
writeDEREncoded(_out, newTag, bOut.toByteArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tag & DERTags.CONSTRUCTED) != 0)
|
||||
{
|
||||
writeDEREncoded(_out, tagNum | DERTags.CONSTRUCTED, bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
writeDEREncoded(_out, tagNum, bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeDEREncoded(_out, tag, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
void writeDEREncoded(
|
||||
OutputStream out,
|
||||
int tag,
|
||||
InputStream in)
|
||||
throws IOException
|
||||
{
|
||||
writeDEREncoded(out, tag, Streams.readAll(in));
|
||||
}
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DER IA5String object - this is an ascii string.
|
||||
*/
|
||||
public class DERIA5String
|
||||
extends ASN1Object
|
||||
implements DERString
|
||||
{
|
||||
String string;
|
||||
|
||||
/**
|
||||
* return a IA5 string from the passed in object
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERIA5String getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERIA5String)
|
||||
{
|
||||
return (DERIA5String)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERIA5String(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return an IA5 String from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERIA5String getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - with bytes.
|
||||
*/
|
||||
public DERIA5String(
|
||||
byte[] string)
|
||||
{
|
||||
char[] cs = new char[string.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
cs[i] = (char)(string[i] & 0xff);
|
||||
}
|
||||
|
||||
this.string = new String(cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - without validation.
|
||||
*/
|
||||
public DERIA5String(
|
||||
String string)
|
||||
{
|
||||
this(string, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with optional validation.
|
||||
*
|
||||
* @param string the base string to wrap.
|
||||
* @param validate whether or not to check the string.
|
||||
* @throws IllegalArgumentException if validate is true and the string
|
||||
* contains characters that should not be in an IA5String.
|
||||
*/
|
||||
public DERIA5String(
|
||||
String string,
|
||||
boolean validate)
|
||||
{
|
||||
if (string == null)
|
||||
{
|
||||
throw new NullPointerException("string cannot be null");
|
||||
}
|
||||
if (validate && !isIA5String(string))
|
||||
{
|
||||
throw new IllegalArgumentException("string contains illegal characters");
|
||||
}
|
||||
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
public byte[] getOctets()
|
||||
{
|
||||
char[] cs = string.toCharArray();
|
||||
byte[] bs = new byte[cs.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
bs[i] = (byte)cs[i];
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(IA5_STRING, this.getOctets());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERIA5String))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DERIA5String s = (DERIA5String)o;
|
||||
|
||||
return this.getString().equals(s.getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the passed in String can be represented without
|
||||
* loss as an IA5String, false otherwise.
|
||||
*
|
||||
* @return true if in printable set, false otherwise.
|
||||
*/
|
||||
public static boolean isIA5String(
|
||||
String str)
|
||||
{
|
||||
for (int i = str.length() - 1; i >= 0; i--)
|
||||
{
|
||||
char ch = str.charAt(i);
|
||||
|
||||
if (ch > 0x007f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,274 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Don't use this class. It will eventually disappear, use ASN1InputStream.
|
||||
* <br>
|
||||
* This class is scheduled for removal.
|
||||
* @deprecated use ASN1InputStream
|
||||
*/
|
||||
@Deprecated
|
||||
public class DERInputStream
|
||||
extends FilterInputStream implements DERTags
|
||||
{
|
||||
/**
|
||||
* @deprecated use ASN1InputStream
|
||||
*/
|
||||
@Deprecated
|
||||
public DERInputStream(
|
||||
InputStream is)
|
||||
{
|
||||
super(is);
|
||||
}
|
||||
|
||||
protected int readLength()
|
||||
throws IOException
|
||||
{
|
||||
int length = read();
|
||||
if (length < 0)
|
||||
{
|
||||
throw new IOException("EOF found when length expected");
|
||||
}
|
||||
|
||||
if (length == 0x80)
|
||||
{
|
||||
return -1; // indefinite-length encoding
|
||||
}
|
||||
|
||||
if (length > 127)
|
||||
{
|
||||
int size = length & 0x7f;
|
||||
|
||||
if (size > 4)
|
||||
{
|
||||
throw new IOException("DER length more than 4 bytes");
|
||||
}
|
||||
|
||||
length = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
int next = read();
|
||||
|
||||
if (next < 0)
|
||||
{
|
||||
throw new IOException("EOF found reading length");
|
||||
}
|
||||
|
||||
length = (length << 8) + next;
|
||||
}
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
throw new IOException("corrupted stream - negative length found");
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
protected void readFully(
|
||||
byte[] bytes)
|
||||
throws IOException
|
||||
{
|
||||
int left = bytes.length;
|
||||
|
||||
if (left == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (left > 0)
|
||||
{
|
||||
int l = read(bytes, bytes.length - left, left);
|
||||
|
||||
if (l < 0)
|
||||
{
|
||||
throw new EOFException("unexpected end of stream");
|
||||
}
|
||||
|
||||
left -= l;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* build an object given its tag and a byte stream to construct it
|
||||
* from.
|
||||
*/
|
||||
protected DERObject buildObject(
|
||||
int tag,
|
||||
byte[] bytes)
|
||||
throws IOException
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case NULL:
|
||||
return null;
|
||||
case SEQUENCE | CONSTRUCTED:
|
||||
ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
|
||||
BERInputStream dIn = new BERInputStream(bIn);
|
||||
DERConstructedSequence seq = new DERConstructedSequence();
|
||||
|
||||
try
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
DERObject obj = dIn.readObject();
|
||||
|
||||
seq.addObject(obj);
|
||||
}
|
||||
}
|
||||
catch (EOFException ex)
|
||||
{
|
||||
return seq;
|
||||
}
|
||||
case SET | CONSTRUCTED:
|
||||
bIn = new ByteArrayInputStream(bytes);
|
||||
dIn = new BERInputStream(bIn);
|
||||
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
try
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
DERObject obj = dIn.readObject();
|
||||
|
||||
v.add(obj);
|
||||
}
|
||||
}
|
||||
catch (EOFException ex)
|
||||
{
|
||||
return new DERConstructedSet(v);
|
||||
}
|
||||
case BOOLEAN:
|
||||
return new DERBoolean(bytes);
|
||||
case INTEGER:
|
||||
return new DERInteger(bytes);
|
||||
case ENUMERATED:
|
||||
return new DEREnumerated(bytes);
|
||||
case OBJECT_IDENTIFIER:
|
||||
return new DERObjectIdentifier(bytes);
|
||||
case BIT_STRING:
|
||||
int padBits = bytes[0];
|
||||
byte[] data = new byte[bytes.length - 1];
|
||||
|
||||
System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
|
||||
|
||||
return new DERBitString(data, padBits);
|
||||
case UTF8_STRING:
|
||||
return new DERUTF8String(bytes);
|
||||
case PRINTABLE_STRING:
|
||||
return new DERPrintableString(bytes);
|
||||
case IA5_STRING:
|
||||
return new DERIA5String(bytes);
|
||||
case T61_STRING:
|
||||
return new DERT61String(bytes);
|
||||
case VISIBLE_STRING:
|
||||
return new DERVisibleString(bytes);
|
||||
case UNIVERSAL_STRING:
|
||||
return new DERUniversalString(bytes);
|
||||
case GENERAL_STRING:
|
||||
return new DERGeneralString(bytes);
|
||||
case BMP_STRING:
|
||||
return new DERBMPString(bytes);
|
||||
case OCTET_STRING:
|
||||
return new DEROctetString(bytes);
|
||||
case UTC_TIME:
|
||||
return new DERUTCTime(bytes);
|
||||
case GENERALIZED_TIME:
|
||||
return new DERGeneralizedTime(bytes);
|
||||
default:
|
||||
//
|
||||
// with tagged object tag number is bottom 5 bits
|
||||
//
|
||||
if ((tag & TAGGED) != 0)
|
||||
{
|
||||
if ((tag & 0x1f) == 0x1f)
|
||||
{
|
||||
throw new IOException("unsupported high tag encountered");
|
||||
}
|
||||
|
||||
if (bytes.length == 0) // empty tag!
|
||||
{
|
||||
if ((tag & CONSTRUCTED) == 0)
|
||||
{
|
||||
return new DERTaggedObject(false, tag & 0x1f, new DERNull());
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// simple type - implicit... return an octet string
|
||||
//
|
||||
if ((tag & CONSTRUCTED) == 0)
|
||||
{
|
||||
return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
|
||||
}
|
||||
|
||||
bIn = new ByteArrayInputStream(bytes);
|
||||
dIn = new BERInputStream(bIn);
|
||||
|
||||
DEREncodable dObj = dIn.readObject();
|
||||
|
||||
//
|
||||
// explicitly tagged (probably!) - if it isn't we'd have to
|
||||
// tell from the context
|
||||
//
|
||||
if (dIn.available() == 0)
|
||||
{
|
||||
return new DERTaggedObject(tag & 0x1f, dObj);
|
||||
}
|
||||
|
||||
//
|
||||
// another implicit object, we'll create a sequence...
|
||||
//
|
||||
seq = new DERConstructedSequence();
|
||||
|
||||
seq.addObject(dObj);
|
||||
|
||||
try
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
dObj = dIn.readObject();
|
||||
|
||||
seq.addObject(dObj);
|
||||
}
|
||||
}
|
||||
catch (EOFException ex)
|
||||
{
|
||||
// ignore --
|
||||
}
|
||||
|
||||
return new DERTaggedObject(false, tag & 0x1f, seq);
|
||||
}
|
||||
|
||||
return new DERUnknownTag(tag, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
public DERObject readObject()
|
||||
throws IOException
|
||||
{
|
||||
int tag = read();
|
||||
if (tag == -1)
|
||||
{
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
int length = readLength();
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
readFully(bytes);
|
||||
|
||||
return buildObject(tag, bytes);
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.bouncycastle.util.Arrays;
|
||||
|
||||
public class DERInteger
|
||||
extends ASN1Object
|
||||
{
|
||||
byte[] bytes;
|
||||
|
||||
/**
|
||||
* return an integer from the passed in object
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERInteger getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERInteger)
|
||||
{
|
||||
return (DERInteger)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERInteger(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return an Integer from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERInteger getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
public DERInteger(
|
||||
int value)
|
||||
{
|
||||
bytes = BigInteger.valueOf(value).toByteArray();
|
||||
}
|
||||
|
||||
public DERInteger(
|
||||
BigInteger value)
|
||||
{
|
||||
bytes = value.toByteArray();
|
||||
}
|
||||
|
||||
public DERInteger(
|
||||
byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public BigInteger getValue()
|
||||
{
|
||||
return new BigInteger(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* in some cases positive values get crammed into a space,
|
||||
* that's not quite big enough...
|
||||
*/
|
||||
public BigInteger getPositiveValue()
|
||||
{
|
||||
return new BigInteger(1, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(INTEGER, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
for (int i = 0; i != bytes.length; i++)
|
||||
{
|
||||
value ^= (bytes[i] & 0xff) << (i % 4);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERInteger))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DERInteger other = (DERInteger)o;
|
||||
|
||||
return Arrays.areEqual(bytes, other.bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getValue().toString();
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A NULL object.
|
||||
*/
|
||||
public class DERNull
|
||||
extends ASN1Null
|
||||
{
|
||||
public static final DERNull INSTANCE = new DERNull();
|
||||
|
||||
byte[] zeroBytes = new byte[0];
|
||||
|
||||
public DERNull()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(NULL, zeroBytes);
|
||||
}
|
||||
}
|
@ -1,181 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
|
||||
*/
|
||||
public class DERNumericString
|
||||
extends ASN1Object
|
||||
implements DERString
|
||||
{
|
||||
String string;
|
||||
|
||||
/**
|
||||
* return a Numeric string from the passed in object
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERNumericString getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERNumericString)
|
||||
{
|
||||
return (DERNumericString)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERNumericString(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return an Numeric String from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERNumericString getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - with bytes.
|
||||
*/
|
||||
public DERNumericString(
|
||||
byte[] string)
|
||||
{
|
||||
char[] cs = new char[string.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
cs[i] = (char)(string[i] & 0xff);
|
||||
}
|
||||
|
||||
this.string = new String(cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - without validation..
|
||||
*/
|
||||
public DERNumericString(
|
||||
String string)
|
||||
{
|
||||
this(string, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with optional validation.
|
||||
*
|
||||
* @param string the base string to wrap.
|
||||
* @param validate whether or not to check the string.
|
||||
* @throws IllegalArgumentException if validate is true and the string
|
||||
* contains characters that should not be in a NumericString.
|
||||
*/
|
||||
public DERNumericString(
|
||||
String string,
|
||||
boolean validate)
|
||||
{
|
||||
if (validate && !isNumericString(string))
|
||||
{
|
||||
throw new IllegalArgumentException("string contains illegal characters");
|
||||
}
|
||||
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
public byte[] getOctets()
|
||||
{
|
||||
char[] cs = string.toCharArray();
|
||||
byte[] bs = new byte[cs.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
bs[i] = (byte)cs[i];
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(NUMERIC_STRING, this.getOctets());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERNumericString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DERNumericString s = (DERNumericString)o;
|
||||
|
||||
return this.getString().equals(s.getString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the string can be represented as a NumericString ('0'..'9', ' ')
|
||||
*
|
||||
* @param str string to validate.
|
||||
* @return true if numeric, fale otherwise.
|
||||
*/
|
||||
public static boolean isNumericString(
|
||||
String str)
|
||||
{
|
||||
for (int i = str.length() - 1; i >= 0; i--)
|
||||
{
|
||||
char ch = str.charAt(i);
|
||||
|
||||
if (ch > 0x007f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (('0' <= ch && ch <= '9') || ch == ' ')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class DERObject
|
||||
extends ASN1Encodable
|
||||
implements DERTags
|
||||
{
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object o);
|
||||
|
||||
abstract void encode(DEROutputStream out)
|
||||
throws IOException;
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class DERObjectIdentifier
|
||||
extends ASN1Object
|
||||
{
|
||||
String identifier;
|
||||
|
||||
/**
|
||||
* return an OID from the passed in object
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERObjectIdentifier getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERObjectIdentifier)
|
||||
{
|
||||
return (DERObjectIdentifier)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return an Object Identifier from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERObjectIdentifier getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
|
||||
DERObjectIdentifier(
|
||||
byte[] bytes)
|
||||
{
|
||||
StringBuffer objId = new StringBuffer();
|
||||
long value = 0;
|
||||
BigInteger bigValue = null;
|
||||
boolean first = true;
|
||||
|
||||
for (int i = 0; i != bytes.length; i++)
|
||||
{
|
||||
int b = bytes[i] & 0xff;
|
||||
|
||||
if (value < 0x80000000000000L)
|
||||
{
|
||||
value = value * 128 + (b & 0x7f);
|
||||
if ((b & 0x80) == 0) // end of number reached
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
switch ((int)value / 40)
|
||||
{
|
||||
case 0:
|
||||
objId.append('0');
|
||||
break;
|
||||
case 1:
|
||||
objId.append('1');
|
||||
value -= 40;
|
||||
break;
|
||||
default:
|
||||
objId.append('2');
|
||||
value -= 80;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
objId.append('.');
|
||||
objId.append(value);
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bigValue == null)
|
||||
{
|
||||
bigValue = BigInteger.valueOf(value);
|
||||
}
|
||||
bigValue = bigValue.shiftLeft(7);
|
||||
bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
|
||||
if ((b & 0x80) == 0)
|
||||
{
|
||||
objId.append('.');
|
||||
objId.append(bigValue);
|
||||
bigValue = null;
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.identifier = objId.toString();
|
||||
}
|
||||
|
||||
public DERObjectIdentifier(
|
||||
String identifier)
|
||||
{
|
||||
if (!isValidIdentifier(identifier))
|
||||
{
|
||||
throw new IllegalArgumentException("string " + identifier + " not an OID");
|
||||
}
|
||||
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return identifier;
|
||||
}
|
||||
|
||||
private void writeField(
|
||||
OutputStream out,
|
||||
long fieldValue)
|
||||
throws IOException
|
||||
{
|
||||
if (fieldValue >= (1L << 7))
|
||||
{
|
||||
if (fieldValue >= (1L << 14))
|
||||
{
|
||||
if (fieldValue >= (1L << 21))
|
||||
{
|
||||
if (fieldValue >= (1L << 28))
|
||||
{
|
||||
if (fieldValue >= (1L << 35))
|
||||
{
|
||||
if (fieldValue >= (1L << 42))
|
||||
{
|
||||
if (fieldValue >= (1L << 49))
|
||||
{
|
||||
if (fieldValue >= (1L << 56))
|
||||
{
|
||||
out.write((int)(fieldValue >> 56) | 0x80);
|
||||
}
|
||||
out.write((int)(fieldValue >> 49) | 0x80);
|
||||
}
|
||||
out.write((int)(fieldValue >> 42) | 0x80);
|
||||
}
|
||||
out.write((int)(fieldValue >> 35) | 0x80);
|
||||
}
|
||||
out.write((int)(fieldValue >> 28) | 0x80);
|
||||
}
|
||||
out.write((int)(fieldValue >> 21) | 0x80);
|
||||
}
|
||||
out.write((int)(fieldValue >> 14) | 0x80);
|
||||
}
|
||||
out.write((int)(fieldValue >> 7) | 0x80);
|
||||
}
|
||||
out.write((int)fieldValue & 0x7f);
|
||||
}
|
||||
|
||||
private void writeField(
|
||||
OutputStream out,
|
||||
BigInteger fieldValue)
|
||||
throws IOException
|
||||
{
|
||||
int byteCount = (fieldValue.bitLength()+6)/7;
|
||||
if (byteCount == 0)
|
||||
{
|
||||
out.write(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
BigInteger tmpValue = fieldValue;
|
||||
byte[] tmp = new byte[byteCount];
|
||||
for (int i = byteCount-1; i >= 0; i--)
|
||||
{
|
||||
tmp[i] = (byte) ((tmpValue.intValue() & 0x7f) | 0x80);
|
||||
tmpValue = tmpValue.shiftRight(7);
|
||||
}
|
||||
tmp[byteCount-1] &= 0x7f;
|
||||
out.write(tmp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
OIDTokenizer tok = new OIDTokenizer(identifier);
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
DEROutputStream dOut = new DEROutputStream(bOut);
|
||||
|
||||
writeField(bOut,
|
||||
Integer.parseInt(tok.nextToken()) * 40
|
||||
+ Integer.parseInt(tok.nextToken()));
|
||||
|
||||
while (tok.hasMoreTokens())
|
||||
{
|
||||
String token = tok.nextToken();
|
||||
if (token.length() < 18)
|
||||
{
|
||||
writeField(bOut, Long.parseLong(token));
|
||||
}
|
||||
else
|
||||
{
|
||||
writeField(bOut, new BigInteger(token));
|
||||
}
|
||||
}
|
||||
|
||||
dOut.close();
|
||||
|
||||
byte[] bytes = bOut.toByteArray();
|
||||
|
||||
out.writeEncoded(OBJECT_IDENTIFIER, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return identifier.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERObjectIdentifier))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return identifier.equals(((DERObjectIdentifier)o).identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getId();
|
||||
}
|
||||
|
||||
private static boolean isValidIdentifier(
|
||||
String identifier)
|
||||
{
|
||||
if (identifier.length() < 3
|
||||
|| identifier.charAt(1) != '.')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char first = identifier.charAt(0);
|
||||
if (first < '0' || first > '2')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean periodAllowed = false;
|
||||
for (int i = identifier.length() - 1; i >= 2; i--)
|
||||
{
|
||||
char ch = identifier.charAt(i);
|
||||
|
||||
if ('0' <= ch && ch <= '9')
|
||||
{
|
||||
periodAllowed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '.')
|
||||
{
|
||||
if (!periodAllowed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
periodAllowed = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return periodAllowed;
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DEROctetString
|
||||
extends ASN1OctetString
|
||||
{
|
||||
/**
|
||||
* @param string the octets making up the octet string.
|
||||
*/
|
||||
public DEROctetString(
|
||||
byte[] string)
|
||||
{
|
||||
super(string);
|
||||
}
|
||||
|
||||
public DEROctetString(
|
||||
DEREncodable obj)
|
||||
{
|
||||
super(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(OCTET_STRING, string);
|
||||
}
|
||||
|
||||
static void encode(
|
||||
DEROutputStream derOut,
|
||||
byte[] bytes)
|
||||
throws IOException
|
||||
{
|
||||
derOut.writeEncoded(DERTags.OCTET_STRING, bytes);
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DEROctetStringParser
|
||||
implements ASN1OctetStringParser
|
||||
{
|
||||
private DefiniteLengthInputStream stream;
|
||||
|
||||
DEROctetStringParser(
|
||||
DefiniteLengthInputStream stream)
|
||||
{
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public InputStream getOctetStream()
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new DEROctetString(stream.toByteArray());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class DEROutputStream
|
||||
extends FilterOutputStream implements DERTags
|
||||
{
|
||||
public DEROutputStream(
|
||||
OutputStream os)
|
||||
{
|
||||
super(os);
|
||||
}
|
||||
|
||||
private void writeLength(
|
||||
int length)
|
||||
throws IOException
|
||||
{
|
||||
if (length > 127)
|
||||
{
|
||||
int size = 1;
|
||||
int val = length;
|
||||
|
||||
while ((val >>>= 8) != 0)
|
||||
{
|
||||
size++;
|
||||
}
|
||||
|
||||
write((byte)(size | 0x80));
|
||||
|
||||
for (int i = (size - 1) * 8; i >= 0; i -= 8)
|
||||
{
|
||||
write((byte)(length >> i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
write((byte)length);
|
||||
}
|
||||
}
|
||||
|
||||
void writeEncoded(
|
||||
int tag,
|
||||
byte[] bytes)
|
||||
throws IOException
|
||||
{
|
||||
write(tag);
|
||||
writeLength(bytes.length);
|
||||
write(bytes);
|
||||
}
|
||||
|
||||
void writeTag(int flags, int tagNo)
|
||||
throws IOException
|
||||
{
|
||||
if (tagNo < 31)
|
||||
{
|
||||
write(flags | tagNo);
|
||||
}
|
||||
else
|
||||
{
|
||||
write(flags | 0x1f);
|
||||
if (tagNo < 128)
|
||||
{
|
||||
write(tagNo);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] stack = new byte[5];
|
||||
int pos = stack.length;
|
||||
|
||||
stack[--pos] = (byte)(tagNo & 0x7F);
|
||||
|
||||
do
|
||||
{
|
||||
tagNo >>= 7;
|
||||
stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
|
||||
}
|
||||
while (tagNo > 127);
|
||||
|
||||
write(stack, pos, stack.length - pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void writeEncoded(int flags, int tagNo, byte[] bytes)
|
||||
throws IOException
|
||||
{
|
||||
writeTag(flags, tagNo);
|
||||
writeLength(bytes.length);
|
||||
write(bytes);
|
||||
}
|
||||
|
||||
protected void writeNull()
|
||||
throws IOException
|
||||
{
|
||||
write(NULL);
|
||||
write(0x00);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] buf)
|
||||
throws IOException
|
||||
{
|
||||
out.write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] buf, int offSet, int len)
|
||||
throws IOException
|
||||
{
|
||||
out.write(buf, offSet, len);
|
||||
}
|
||||
|
||||
public void writeObject(
|
||||
Object obj)
|
||||
throws IOException
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
writeNull();
|
||||
}
|
||||
else if (obj instanceof DERObject)
|
||||
{
|
||||
((DERObject)obj).encode(this);
|
||||
}
|
||||
else if (obj instanceof DEREncodable)
|
||||
{
|
||||
((DEREncodable)obj).getDERObject().encode(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("object not DEREncodable");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,208 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DER PrintableString object.
|
||||
*/
|
||||
public class DERPrintableString
|
||||
extends ASN1Object
|
||||
implements DERString
|
||||
{
|
||||
String string;
|
||||
|
||||
/**
|
||||
* return a printable string from the passed in object.
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERPrintableString getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERPrintableString)
|
||||
{
|
||||
return (DERPrintableString)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERPrintableString(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return a Printable String from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERPrintableString getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - byte encoded string.
|
||||
*/
|
||||
public DERPrintableString(
|
||||
byte[] string)
|
||||
{
|
||||
char[] cs = new char[string.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
cs[i] = (char)(string[i] & 0xff);
|
||||
}
|
||||
|
||||
this.string = new String(cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - this does not validate the string
|
||||
*/
|
||||
public DERPrintableString(
|
||||
String string)
|
||||
{
|
||||
this(string, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with optional validation.
|
||||
*
|
||||
* @param string the base string to wrap.
|
||||
* @param validate whether or not to check the string.
|
||||
* @throws IllegalArgumentException if validate is true and the string
|
||||
* contains characters that should not be in a PrintableString.
|
||||
*/
|
||||
public DERPrintableString(
|
||||
String string,
|
||||
boolean validate)
|
||||
{
|
||||
if (validate && !isPrintableString(string))
|
||||
{
|
||||
throw new IllegalArgumentException("string contains illegal characters");
|
||||
}
|
||||
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
public byte[] getOctets()
|
||||
{
|
||||
char[] cs = string.toCharArray();
|
||||
byte[] bs = new byte[cs.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
bs[i] = (byte)cs[i];
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(PRINTABLE_STRING, this.getOctets());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERPrintableString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DERPrintableString s = (DERPrintableString)o;
|
||||
|
||||
return this.getString().equals(s.getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the passed in String can be represented without
|
||||
* loss as a PrintableString, false otherwise.
|
||||
*
|
||||
* @return true if in printable set, false otherwise.
|
||||
*/
|
||||
public static boolean isPrintableString(
|
||||
String str)
|
||||
{
|
||||
for (int i = str.length() - 1; i >= 0; i--)
|
||||
{
|
||||
char ch = str.charAt(i);
|
||||
|
||||
if (ch > 0x007f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('a' <= ch && ch <= 'z')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('A' <= ch && ch <= 'Z')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('0' <= ch && ch <= '9')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '\'':
|
||||
case '(':
|
||||
case ')':
|
||||
case '+':
|
||||
case '-':
|
||||
case '.':
|
||||
case ':':
|
||||
case '=':
|
||||
case '?':
|
||||
case '/':
|
||||
case ',':
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class DERSequence
|
||||
extends ASN1Sequence
|
||||
{
|
||||
/**
|
||||
* create an empty sequence
|
||||
*/
|
||||
public DERSequence()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* create a sequence containing one object
|
||||
*/
|
||||
public DERSequence(
|
||||
DEREncodable obj)
|
||||
{
|
||||
this.addObject(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a sequence containing a vector of objects.
|
||||
*/
|
||||
public DERSequence(
|
||||
DEREncodableVector v)
|
||||
{
|
||||
for (int i = 0; i != v.size(); i++)
|
||||
{
|
||||
this.addObject(v.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a sequence containing an array of objects.
|
||||
*/
|
||||
public DERSequence(
|
||||
ASN1Encodable[] a)
|
||||
{
|
||||
for (int i = 0; i != a.length; i++)
|
||||
{
|
||||
this.addObject(a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A note on the implementation:
|
||||
* <p>
|
||||
* As DER requires the constructed, definite-length model to
|
||||
* be used for structured types, this varies slightly from the
|
||||
* ASN.1 descriptions given. Rather than just outputing SEQUENCE,
|
||||
* we also have to specify CONSTRUCTED, and the objects length.
|
||||
*/
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
// TODO Intermediate buffer could be avoided if we could calculate expected length
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
DEROutputStream dOut = new DEROutputStream(bOut);
|
||||
Enumeration e = this.getObjects();
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
Object obj = e.nextElement();
|
||||
|
||||
dOut.writeObject(obj);
|
||||
}
|
||||
|
||||
dOut.close();
|
||||
|
||||
byte[] bytes = bOut.toByteArray();
|
||||
|
||||
out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class DERSequenceGenerator
|
||||
extends DERGenerator
|
||||
{
|
||||
private final ByteArrayOutputStream _bOut = new ByteArrayOutputStream();
|
||||
|
||||
public DERSequenceGenerator(
|
||||
OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
super(out);
|
||||
}
|
||||
|
||||
public DERSequenceGenerator(
|
||||
OutputStream out,
|
||||
int tagNo,
|
||||
boolean isExplicit)
|
||||
throws IOException
|
||||
{
|
||||
super(out, tagNo, isExplicit);
|
||||
}
|
||||
|
||||
public void addObject(
|
||||
DEREncodable object)
|
||||
throws IOException
|
||||
{
|
||||
object.getDERObject().encode(new DEROutputStream(_bOut));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getRawOutputStream()
|
||||
{
|
||||
return _bOut;
|
||||
}
|
||||
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
writeDEREncoded(DERTags.CONSTRUCTED | DERTags.SEQUENCE, _bOut.toByteArray());
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DERSequenceParser
|
||||
implements ASN1SequenceParser
|
||||
{
|
||||
private ASN1StreamParser _parser;
|
||||
|
||||
DERSequenceParser(ASN1StreamParser parser)
|
||||
{
|
||||
this._parser = parser;
|
||||
}
|
||||
|
||||
public DEREncodable readObject()
|
||||
throws IOException
|
||||
{
|
||||
return _parser.readObject();
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new DERSequence(_parser.readVector());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalStateException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* A DER encoded set object
|
||||
*/
|
||||
public class DERSet
|
||||
extends ASN1Set
|
||||
{
|
||||
/**
|
||||
* create an empty set
|
||||
*/
|
||||
public DERSet()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param obj - a single object that makes up the set.
|
||||
*/
|
||||
public DERSet(
|
||||
DEREncodable obj)
|
||||
{
|
||||
this.addObject(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v - a vector of objects making up the set.
|
||||
*/
|
||||
public DERSet(
|
||||
DEREncodableVector v)
|
||||
{
|
||||
this(v, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a set from an array of objects.
|
||||
*/
|
||||
public DERSet(
|
||||
ASN1Encodable[] a)
|
||||
{
|
||||
for (int i = 0; i != a.length; i++)
|
||||
{
|
||||
this.addObject(a[i]);
|
||||
}
|
||||
|
||||
this.sort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v - a vector of objects making up the set.
|
||||
*/
|
||||
DERSet(
|
||||
DEREncodableVector v,
|
||||
boolean needsSorting)
|
||||
{
|
||||
for (int i = 0; i != v.size(); i++)
|
||||
{
|
||||
this.addObject(v.get(i));
|
||||
}
|
||||
|
||||
if (needsSorting)
|
||||
{
|
||||
this.sort();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A note on the implementation:
|
||||
* <p>
|
||||
* As DER requires the constructed, definite-length model to
|
||||
* be used for structured types, this varies slightly from the
|
||||
* ASN.1 descriptions given. Rather than just outputing SET,
|
||||
* we also have to specify CONSTRUCTED, and the objects length.
|
||||
*/
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
// TODO Intermediate buffer could be avoided if we could calculate expected length
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
DEROutputStream dOut = new DEROutputStream(bOut);
|
||||
Enumeration e = this.getObjects();
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
Object obj = e.nextElement();
|
||||
|
||||
dOut.writeObject(obj);
|
||||
}
|
||||
|
||||
dOut.close();
|
||||
|
||||
byte[] bytes = bOut.toByteArray();
|
||||
|
||||
out.writeEncoded(SET | CONSTRUCTED, bytes);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DERSetParser
|
||||
implements ASN1SetParser
|
||||
{
|
||||
private ASN1StreamParser _parser;
|
||||
|
||||
DERSetParser(ASN1StreamParser parser)
|
||||
{
|
||||
this._parser = parser;
|
||||
}
|
||||
|
||||
public DEREncodable readObject()
|
||||
throws IOException
|
||||
{
|
||||
return _parser.readObject();
|
||||
}
|
||||
|
||||
public DERObject getDERObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new DERSet(_parser.readVector(), false);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ASN1ParsingException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
/**
|
||||
* basic interface for DER string objects.
|
||||
*/
|
||||
public interface DERString
|
||||
{
|
||||
public String getString();
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DER T61String (also the teletex string)
|
||||
*/
|
||||
public class DERT61String
|
||||
extends ASN1Object
|
||||
implements DERString
|
||||
{
|
||||
String string;
|
||||
|
||||
/**
|
||||
* return a T61 string from the passed in object.
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERT61String getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERT61String)
|
||||
{
|
||||
return (DERT61String)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERT61String(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return an T61 String from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERT61String getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - with bytes.
|
||||
*/
|
||||
public DERT61String(
|
||||
byte[] string)
|
||||
{
|
||||
char[] cs = new char[string.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
cs[i] = (char)(string[i] & 0xff);
|
||||
}
|
||||
|
||||
this.string = new String(cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - with string.
|
||||
*/
|
||||
public DERT61String(
|
||||
String string)
|
||||
{
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(T61_STRING, this.getOctets());
|
||||
}
|
||||
|
||||
public byte[] getOctets()
|
||||
{
|
||||
char[] cs = string.toCharArray();
|
||||
byte[] bs = new byte[cs.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
bs[i] = (byte)cs[i];
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERT61String))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getString().equals(((DERT61String)o).getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getString().hashCode();
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DER TaggedObject - in ASN.1 notation this is any object preceded by
|
||||
* a [n] where n is some number - these are assumed to follow the construction
|
||||
* rules (as with sequences).
|
||||
*/
|
||||
public class DERTaggedObject
|
||||
extends ASN1TaggedObject
|
||||
{
|
||||
private static final byte[] ZERO_BYTES = new byte[0];
|
||||
|
||||
/**
|
||||
* @param tagNo the tag number for this object.
|
||||
* @param obj the tagged object.
|
||||
*/
|
||||
public DERTaggedObject(
|
||||
int tagNo,
|
||||
DEREncodable obj)
|
||||
{
|
||||
super(tagNo, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param explicit true if an explicitly tagged object.
|
||||
* @param tagNo the tag number for this object.
|
||||
* @param obj the tagged object.
|
||||
*/
|
||||
public DERTaggedObject(
|
||||
boolean explicit,
|
||||
int tagNo,
|
||||
DEREncodable obj)
|
||||
{
|
||||
super(explicit, tagNo, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* create an implicitly tagged object that contains a zero
|
||||
* length sequence.
|
||||
*/
|
||||
public DERTaggedObject(
|
||||
int tagNo)
|
||||
{
|
||||
super(false, tagNo, new DERSequence());
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
if (!empty)
|
||||
{
|
||||
byte[] bytes = obj.getDERObject().getEncoded(DER);
|
||||
|
||||
if (explicit)
|
||||
{
|
||||
out.writeEncoded(CONSTRUCTED | TAGGED, tagNo, bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// need to mark constructed types...
|
||||
//
|
||||
int flags;
|
||||
if ((bytes[0] & CONSTRUCTED) != 0)
|
||||
{
|
||||
flags = CONSTRUCTED | TAGGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags = TAGGED;
|
||||
}
|
||||
|
||||
out.writeTag(flags, tagNo);
|
||||
out.write(bytes, 1, bytes.length - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out.writeEncoded(CONSTRUCTED | TAGGED, tagNo, ZERO_BYTES);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
public interface DERTags
|
||||
{
|
||||
public static final int BOOLEAN = 0x01;
|
||||
public static final int INTEGER = 0x02;
|
||||
public static final int BIT_STRING = 0x03;
|
||||
public static final int OCTET_STRING = 0x04;
|
||||
public static final int NULL = 0x05;
|
||||
public static final int OBJECT_IDENTIFIER = 0x06;
|
||||
public static final int EXTERNAL = 0x08;
|
||||
public static final int ENUMERATED = 0x0a;
|
||||
public static final int SEQUENCE = 0x10;
|
||||
public static final int SEQUENCE_OF = 0x10; // for completeness
|
||||
public static final int SET = 0x11;
|
||||
public static final int SET_OF = 0x11; // for completeness
|
||||
|
||||
|
||||
public static final int NUMERIC_STRING = 0x12;
|
||||
public static final int PRINTABLE_STRING = 0x13;
|
||||
public static final int T61_STRING = 0x14;
|
||||
public static final int VIDEOTEX_STRING = 0x15;
|
||||
public static final int IA5_STRING = 0x16;
|
||||
public static final int UTC_TIME = 0x17;
|
||||
public static final int GENERALIZED_TIME = 0x18;
|
||||
public static final int GRAPHIC_STRING = 0x19;
|
||||
public static final int VISIBLE_STRING = 0x1a;
|
||||
public static final int GENERAL_STRING = 0x1b;
|
||||
public static final int UNIVERSAL_STRING = 0x1c;
|
||||
public static final int BMP_STRING = 0x1e;
|
||||
public static final int UTF8_STRING = 0x0c;
|
||||
|
||||
public static final int CONSTRUCTED = 0x20;
|
||||
public static final int APPLICATION = 0x40;
|
||||
public static final int TAGGED = 0x80;
|
||||
}
|
@ -1,258 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.SimpleTimeZone;
|
||||
|
||||
/**
|
||||
* UTC time object.
|
||||
*/
|
||||
public class DERUTCTime
|
||||
extends ASN1Object
|
||||
{
|
||||
String time;
|
||||
|
||||
/**
|
||||
* return an UTC Time from the passed in object.
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERUTCTime getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERUTCTime)
|
||||
{
|
||||
return (DERUTCTime)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERUTCTime(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return an UTC Time from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERUTCTime getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
|
||||
* never encoded. When you're creating one of these objects from scratch, that's
|
||||
* what you want to use, otherwise we'll try to deal with whatever gets read from
|
||||
* the input stream... (this is why the input format is different from the getTime()
|
||||
* method output).
|
||||
* <p>
|
||||
*
|
||||
* @param time the time string.
|
||||
*/
|
||||
public DERUTCTime(
|
||||
String time)
|
||||
{
|
||||
this.time = time;
|
||||
try
|
||||
{
|
||||
this.getDate();
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
throw new IllegalArgumentException("invalid date string: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* base constructer from a java.util.date object
|
||||
*/
|
||||
public DERUTCTime(
|
||||
Date time)
|
||||
{
|
||||
SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
|
||||
|
||||
dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
|
||||
|
||||
this.time = dateF.format(time);
|
||||
}
|
||||
|
||||
DERUTCTime(
|
||||
byte[] bytes)
|
||||
{
|
||||
//
|
||||
// explicitly convert to characters
|
||||
//
|
||||
char[] dateC = new char[bytes.length];
|
||||
|
||||
for (int i = 0; i != dateC.length; i++)
|
||||
{
|
||||
dateC[i] = (char)(bytes[i] & 0xff);
|
||||
}
|
||||
|
||||
this.time = new String(dateC);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the time as a date based on whatever a 2 digit year will return. For
|
||||
* standardised processing use getAdjustedDate().
|
||||
*
|
||||
* @return the resulting date
|
||||
* @exception ParseException if the date string cannot be parsed.
|
||||
*/
|
||||
public Date getDate()
|
||||
throws ParseException
|
||||
{
|
||||
SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
|
||||
|
||||
return dateF.parse(getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* return the time as an adjusted date
|
||||
* in the range of 1950 - 2049.
|
||||
*
|
||||
* @return a date in the range of 1950 to 2049.
|
||||
* @exception ParseException if the date string cannot be parsed.
|
||||
*/
|
||||
public Date getAdjustedDate()
|
||||
throws ParseException
|
||||
{
|
||||
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
|
||||
|
||||
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
|
||||
|
||||
return dateF.parse(getAdjustedTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* return the time - always in the form of
|
||||
* YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
|
||||
* <p>
|
||||
* Normally in a certificate we would expect "Z" rather than "GMT",
|
||||
* however adding the "GMT" means we can just use:
|
||||
* <pre>
|
||||
* dateF = new SimpleDateFormat("yyMMddHHmmssz");
|
||||
* </pre>
|
||||
* To read in the time and get a date which is compatible with our local
|
||||
* time zone.
|
||||
* <p>
|
||||
* <b>Note:</b> In some cases, due to the local date processing, this
|
||||
* may lead to unexpected results. If you want to stick the normal
|
||||
* convention of 1950 to 2049 use the getAdjustedTime() method.
|
||||
*/
|
||||
public String getTime()
|
||||
{
|
||||
//
|
||||
// standardise the format.
|
||||
//
|
||||
if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
|
||||
{
|
||||
if (time.length() == 11)
|
||||
{
|
||||
return time.substring(0, 10) + "00GMT+00:00";
|
||||
}
|
||||
else
|
||||
{
|
||||
return time.substring(0, 12) + "GMT+00:00";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = time.indexOf('-');
|
||||
if (index < 0)
|
||||
{
|
||||
index = time.indexOf('+');
|
||||
}
|
||||
String d = time;
|
||||
|
||||
if (index == time.length() - 3)
|
||||
{
|
||||
d += "00";
|
||||
}
|
||||
|
||||
if (index == 10)
|
||||
{
|
||||
return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return a time string as an adjusted date with a 4 digit year. This goes
|
||||
* in the range of 1950 - 2049.
|
||||
*/
|
||||
public String getAdjustedTime()
|
||||
{
|
||||
String d = this.getTime();
|
||||
|
||||
if (d.charAt(0) < '5')
|
||||
{
|
||||
return "20" + d;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "19" + d;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getOctets()
|
||||
{
|
||||
char[] cs = time.toCharArray();
|
||||
byte[] bs = new byte[cs.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
bs[i] = (byte)cs[i];
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(UTC_TIME, this.getOctets());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERUTCTime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return time.equals(((DERUTCTime)o).time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return time.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return time;
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import org.bouncycastle.util.Strings;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DER UTF8String object.
|
||||
*/
|
||||
public class DERUTF8String
|
||||
extends ASN1Object
|
||||
implements DERString
|
||||
{
|
||||
String string;
|
||||
|
||||
/**
|
||||
* return an UTF8 string from the passed in object.
|
||||
*
|
||||
* @exception IllegalArgumentException
|
||||
* if the object cannot be converted.
|
||||
*/
|
||||
public static DERUTF8String getInstance(Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERUTF8String)
|
||||
{
|
||||
return (DERUTF8String)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERUTF8String(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: "
|
||||
+ obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return an UTF8 String from a tagged object.
|
||||
*
|
||||
* @param obj
|
||||
* the tagged object holding the object we want
|
||||
* @param explicit
|
||||
* true if the object is meant to be explicitly tagged false
|
||||
* otherwise.
|
||||
* @exception IllegalArgumentException
|
||||
* if the tagged object cannot be converted.
|
||||
*/
|
||||
public static DERUTF8String getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - byte encoded string.
|
||||
*/
|
||||
DERUTF8String(byte[] string)
|
||||
{
|
||||
this.string = Strings.fromUTF8ByteArray(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor
|
||||
*/
|
||||
public DERUTF8String(String string)
|
||||
{
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERUTF8String))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DERUTF8String s = (DERUTF8String)o;
|
||||
|
||||
return this.getString().equals(s.getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(UTF8_STRING, Strings.toUTF8ByteArray(string));
|
||||
}
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DER UniversalString object.
|
||||
*/
|
||||
public class DERUniversalString
|
||||
extends ASN1Object
|
||||
implements DERString
|
||||
{
|
||||
private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
private byte[] string;
|
||||
|
||||
/**
|
||||
* return a Universal String from the passed in object.
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERUniversalString getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERUniversalString)
|
||||
{
|
||||
return (DERUniversalString)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERUniversalString(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return a Universal String from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERUniversalString getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - byte encoded string.
|
||||
*/
|
||||
public DERUniversalString(
|
||||
byte[] string)
|
||||
{
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer("#");
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
|
||||
|
||||
try
|
||||
{
|
||||
aOut.writeObject(this);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException("internal error encoding BitString");
|
||||
}
|
||||
|
||||
byte[] string = bOut.toByteArray();
|
||||
|
||||
for (int i = 0; i != string.length; i++)
|
||||
{
|
||||
buf.append(table[(string[i] >>> 4) & 0xf]);
|
||||
buf.append(table[string[i] & 0xf]);
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getString();
|
||||
}
|
||||
|
||||
public byte[] getOctets()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(UNIVERSAL_STRING, this.getOctets());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERUniversalString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getString().equals(((DERUniversalString)o).getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getString().hashCode();
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bouncycastle.util.Arrays;
|
||||
|
||||
/**
|
||||
* We insert one of these when we find a tag we don't recognise.
|
||||
*/
|
||||
public class DERUnknownTag
|
||||
extends DERObject
|
||||
{
|
||||
private boolean isConstructed;
|
||||
private int tag;
|
||||
private byte[] data;
|
||||
|
||||
/**
|
||||
* @param tag the tag value.
|
||||
* @param data the contents octets.
|
||||
*/
|
||||
public DERUnknownTag(
|
||||
int tag,
|
||||
byte[] data)
|
||||
{
|
||||
this(false, tag, data);
|
||||
}
|
||||
|
||||
public DERUnknownTag(
|
||||
boolean isConstructed,
|
||||
int tag,
|
||||
byte[] data)
|
||||
{
|
||||
this.isConstructed = isConstructed;
|
||||
this.tag = tag;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean isConstructed()
|
||||
{
|
||||
return isConstructed;
|
||||
}
|
||||
|
||||
public int getTag()
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
public byte[] getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(isConstructed ? DERTags.CONSTRUCTED : 0, tag, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(
|
||||
Object o)
|
||||
{
|
||||
if (!(o instanceof DERUnknownTag))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DERUnknownTag other = (DERUnknownTag)o;
|
||||
|
||||
return isConstructed == other.isConstructed
|
||||
&& tag == other.tag
|
||||
&& Arrays.areEqual(data, other.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return (isConstructed ? ~0 : 0) ^ tag ^ Arrays.hashCode(data);
|
||||
}
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DER VisibleString object.
|
||||
*/
|
||||
public class DERVisibleString
|
||||
extends ASN1Object
|
||||
implements DERString
|
||||
{
|
||||
String string;
|
||||
|
||||
/**
|
||||
* return a Visible String from the passed in object.
|
||||
*
|
||||
* @exception IllegalArgumentException if the object cannot be converted.
|
||||
*/
|
||||
public static DERVisibleString getInstance(
|
||||
Object obj)
|
||||
{
|
||||
if (obj == null || obj instanceof DERVisibleString)
|
||||
{
|
||||
return (DERVisibleString)obj;
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1OctetString)
|
||||
{
|
||||
return new DERVisibleString(((ASN1OctetString)obj).getOctets());
|
||||
}
|
||||
|
||||
if (obj instanceof ASN1TaggedObject)
|
||||
{
|
||||
return getInstance(((ASN1TaggedObject)obj).getObject());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* return a Visible String from a tagged object.
|
||||
*
|
||||
* @param obj the tagged object holding the object we want
|
||||
* @param explicit true if the object is meant to be explicitly
|
||||
* tagged false otherwise.
|
||||
* @exception IllegalArgumentException if the tagged object cannot
|
||||
* be converted.
|
||||
*/
|
||||
public static DERVisibleString getInstance(
|
||||
ASN1TaggedObject obj,
|
||||
boolean explicit)
|
||||
{
|
||||
return getInstance(obj.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor - byte encoded string.
|
||||
*/
|
||||
public DERVisibleString(
|
||||
byte[] string)
|
||||
{
|
||||
char[] cs = new char[string.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
cs[i] = (char)(string[i] & 0xff);
|
||||
}
|
||||
|
||||
this.string = new String(cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* basic constructor
|
||||
*/
|
||||
public DERVisibleString(
|
||||
String string)
|
||||
{
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public String getString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
public byte[] getOctets()
|
||||
{
|
||||
char[] cs = string.toCharArray();
|
||||
byte[] bs = new byte[cs.length];
|
||||
|
||||
for (int i = 0; i != cs.length; i++)
|
||||
{
|
||||
bs[i] = (byte)cs[i];
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(VISIBLE_STRING, this.getOctets());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean asn1Equals(
|
||||
DERObject o)
|
||||
{
|
||||
if (!(o instanceof DERVisibleString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getString().equals(((DERVisibleString)o).getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getString().hashCode();
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
|
||||
class DefiniteLengthInputStream
|
||||
extends LimitedInputStream
|
||||
{
|
||||
private static final byte[] EMPTY_BYTES = new byte[0];
|
||||
|
||||
private final int _originalLength;
|
||||
private int _remaining;
|
||||
|
||||
DefiniteLengthInputStream(
|
||||
InputStream in,
|
||||
int length)
|
||||
{
|
||||
super(in);
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
throw new IllegalArgumentException("negative lengths not allowed");
|
||||
}
|
||||
|
||||
this._originalLength = length;
|
||||
this._remaining = length;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
setParentEofDetect(true);
|
||||
}
|
||||
}
|
||||
|
||||
int getRemaining()
|
||||
{
|
||||
return _remaining;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
if (_remaining == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int b = _in.read();
|
||||
|
||||
if (b < 0)
|
||||
{
|
||||
throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
|
||||
}
|
||||
|
||||
if (--_remaining == 0)
|
||||
{
|
||||
setParentEofDetect(true);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buf, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
if (_remaining == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int toRead = Math.min(len, _remaining);
|
||||
int numRead = _in.read(buf, off, toRead);
|
||||
|
||||
if (numRead < 0)
|
||||
{
|
||||
throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
|
||||
}
|
||||
|
||||
if ((_remaining -= numRead) == 0)
|
||||
{
|
||||
setParentEofDetect(true);
|
||||
}
|
||||
|
||||
return numRead;
|
||||
}
|
||||
|
||||
byte[] toByteArray()
|
||||
throws IOException
|
||||
{
|
||||
if (_remaining == 0)
|
||||
{
|
||||
return EMPTY_BYTES;
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[_remaining];
|
||||
if ((_remaining -= Streams.readFully(_in, bytes)) != 0)
|
||||
{
|
||||
throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
|
||||
}
|
||||
setParentEofDetect(true);
|
||||
return bytes;
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
class IndefiniteLengthInputStream
|
||||
extends LimitedInputStream
|
||||
{
|
||||
private int _b1;
|
||||
private int _b2;
|
||||
private boolean _eofReached = false;
|
||||
private boolean _eofOn00 = true;
|
||||
|
||||
IndefiniteLengthInputStream(
|
||||
InputStream in)
|
||||
throws IOException
|
||||
{
|
||||
super(in);
|
||||
|
||||
_b1 = in.read();
|
||||
_b2 = in.read();
|
||||
|
||||
if (_b2 < 0)
|
||||
{
|
||||
// Corrupted stream
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
checkForEof();
|
||||
}
|
||||
|
||||
void setEofOn00(
|
||||
boolean eofOn00)
|
||||
{
|
||||
_eofOn00 = eofOn00;
|
||||
checkForEof();
|
||||
}
|
||||
|
||||
private boolean checkForEof()
|
||||
{
|
||||
if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
|
||||
{
|
||||
_eofReached = true;
|
||||
setParentEofDetect(true);
|
||||
}
|
||||
return _eofReached;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
// Only use this optimisation if we aren't checking for 00
|
||||
if (_eofOn00 || len < 3)
|
||||
{
|
||||
return super.read(b, off, len);
|
||||
}
|
||||
|
||||
if (_eofReached)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int numRead = _in.read(b, off + 2, len - 2);
|
||||
|
||||
if (numRead < 0)
|
||||
{
|
||||
// Corrupted stream
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
b[off] = (byte)_b1;
|
||||
b[off + 1] = (byte)_b2;
|
||||
|
||||
_b1 = _in.read();
|
||||
_b2 = _in.read();
|
||||
|
||||
if (_b2 < 0)
|
||||
{
|
||||
// Corrupted stream
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
return numRead + 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
if (checkForEof())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int b = _in.read();
|
||||
|
||||
if (b < 0)
|
||||
{
|
||||
// Corrupted stream
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
int v = _b1;
|
||||
|
||||
_b1 = _b2;
|
||||
_b2 = b;
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.io.IOException;
|
||||
|
||||
class LazyDERConstructionEnumeration
|
||||
implements Enumeration
|
||||
{
|
||||
private ASN1InputStream aIn;
|
||||
private Object nextObj;
|
||||
|
||||
public LazyDERConstructionEnumeration(byte[] encoded)
|
||||
{
|
||||
aIn = new ASN1InputStream(encoded, true);
|
||||
nextObj = readObject();
|
||||
}
|
||||
|
||||
public boolean hasMoreElements()
|
||||
{
|
||||
return nextObj != null;
|
||||
}
|
||||
|
||||
public Object nextElement()
|
||||
{
|
||||
Object o = nextObj;
|
||||
|
||||
nextObj = readObject();
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
private Object readObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return aIn.readObject();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ASN1ParsingException("malformed DER construction: " + e, e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class LazyDERSequence
|
||||
extends DERSequence
|
||||
{
|
||||
private byte[] encoded;
|
||||
private boolean parsed = false;
|
||||
private int size = -1;
|
||||
|
||||
LazyDERSequence(
|
||||
byte[] encoded)
|
||||
throws IOException
|
||||
{
|
||||
this.encoded = encoded;
|
||||
}
|
||||
|
||||
private void parse()
|
||||
{
|
||||
Enumeration en = new LazyDERConstructionEnumeration(encoded);
|
||||
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
addObject((DEREncodable)en.nextElement());
|
||||
}
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DEREncodable getObjectAt(int index)
|
||||
{
|
||||
if (!parsed)
|
||||
{
|
||||
parse();
|
||||
}
|
||||
|
||||
return super.getObjectAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration getObjects()
|
||||
{
|
||||
if (parsed)
|
||||
{
|
||||
return super.getObjects();
|
||||
}
|
||||
|
||||
return new LazyDERConstructionEnumeration(encoded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
if (size < 0)
|
||||
{
|
||||
Enumeration en = new LazyDERConstructionEnumeration(encoded);
|
||||
|
||||
size = 0;
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
en.nextElement();
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encode(
|
||||
DEROutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeEncoded(SEQUENCE | CONSTRUCTED, encoded);
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
abstract class LimitedInputStream
|
||||
extends InputStream
|
||||
{
|
||||
protected final InputStream _in;
|
||||
|
||||
LimitedInputStream(
|
||||
InputStream in)
|
||||
{
|
||||
this._in = in;
|
||||
}
|
||||
|
||||
protected void setParentEofDetect(boolean on)
|
||||
{
|
||||
if (_in instanceof IndefiniteLengthInputStream)
|
||||
{
|
||||
((IndefiniteLengthInputStream)_in).setEofOn00(on);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package org.bouncycastle.asn1;
|
||||
|
||||
/**
|
||||
* class for breaking up an OID into it's component tokens, ala
|
||||
* java.util.StringTokenizer. We need this class as some of the
|
||||
* lightweight Java environment don't support classes like
|
||||
* StringTokenizer.
|
||||
*/
|
||||
public class OIDTokenizer
|
||||
{
|
||||
private String oid;
|
||||
private int index;
|
||||
|
||||
public OIDTokenizer(
|
||||
String oid)
|
||||
{
|
||||
this.oid = oid;
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
public boolean hasMoreTokens()
|
||||
{
|
||||
return (index != -1);
|
||||
}
|
||||
|
||||
public String nextToken()
|
||||
{
|
||||
if (index == -1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String token;
|
||||
int end = oid.indexOf('.', index);
|
||||
|
||||
if (end == -1)
|
||||
{
|
||||
token = oid.substring(index);
|
||||
index = -1;
|
||||
return token;
|
||||
}
|
||||
|
||||
token = oid.substring(index, end);
|
||||
|
||||
index = end + 1;
|
||||
return token;
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package org.bouncycastle.asn1.bc;
|
||||
|
||||
import org.bouncycastle.asn1.DERObjectIdentifier;
|
||||
|
||||
public interface BCObjectIdentifiers
|
||||
{
|
||||
/**
|
||||
* iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle
|
||||
*
|
||||
* 1.3.6.1.4.1.22554
|
||||
*/
|
||||
public static final DERObjectIdentifier bc = new DERObjectIdentifier("1.3.6.1.4.1.22554");
|
||||
|
||||
/**
|
||||
* pbe(1) algorithms
|
||||
*/
|
||||
public static final DERObjectIdentifier bc_pbe = new DERObjectIdentifier(bc.getId() + ".1");
|
||||
|
||||
/**
|
||||
* SHA-1(1)
|
||||
*/
|
||||
public static final DERObjectIdentifier bc_pbe_sha1 = new DERObjectIdentifier(bc_pbe.getId() + ".1");
|
||||
|
||||
/**
|
||||
* SHA-2(2) . (SHA-256(1)|SHA-384(2)|SHA-512(3)|SHA-224(4))
|
||||
*/
|
||||
public static final DERObjectIdentifier bc_pbe_sha256 = new DERObjectIdentifier(bc_pbe.getId() + ".2.1");
|
||||
public static final DERObjectIdentifier bc_pbe_sha384 = new DERObjectIdentifier(bc_pbe.getId() + ".2.2");
|
||||
public static final DERObjectIdentifier bc_pbe_sha512 = new DERObjectIdentifier(bc_pbe.getId() + ".2.3");
|
||||
public static final DERObjectIdentifier bc_pbe_sha224 = new DERObjectIdentifier(bc_pbe.getId() + ".2.4");
|
||||
|
||||
/**
|
||||
* PKCS-5(1)|PKCS-12(2)
|
||||
*/
|
||||
public static final DERObjectIdentifier bc_pbe_sha1_pkcs5 = new DERObjectIdentifier(bc_pbe_sha1.getId() + ".1");
|
||||
public static final DERObjectIdentifier bc_pbe_sha1_pkcs12 = new DERObjectIdentifier(bc_pbe_sha1.getId() + ".2");
|
||||
|
||||
public static final DERObjectIdentifier bc_pbe_sha256_pkcs5 = new DERObjectIdentifier(bc_pbe_sha256.getId() + ".1");
|
||||
public static final DERObjectIdentifier bc_pbe_sha256_pkcs12 = new DERObjectIdentifier(bc_pbe_sha256.getId() + ".2");
|
||||
|
||||
/**
|
||||
* AES(1) . (CBC-128(2)|CBC-192(22)|CBC-256(42))
|
||||
*/
|
||||
public static final DERObjectIdentifier bc_pbe_sha1_pkcs12_aes128_cbc = new DERObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.2");
|
||||
public static final DERObjectIdentifier bc_pbe_sha1_pkcs12_aes192_cbc = new DERObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.22");
|
||||
public static final DERObjectIdentifier bc_pbe_sha1_pkcs12_aes256_cbc = new DERObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.42");
|
||||
|
||||
public static final DERObjectIdentifier bc_pbe_sha256_pkcs12_aes128_cbc = new DERObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.2");
|
||||
public static final DERObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = new DERObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.22");
|
||||
public static final DERObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = new DERObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.42");
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
|
||||
public class CAKeyUpdAnnContent
|
||||
extends ASN1Encodable
|
||||
{
|
||||
private CMPCertificate oldWithNew;
|
||||
private CMPCertificate newWithOld;
|
||||
private CMPCertificate newWithNew;
|
||||
|
||||
private CAKeyUpdAnnContent(ASN1Sequence seq)
|
||||
{
|
||||
oldWithNew = CMPCertificate.getInstance(seq.getObjectAt(0));
|
||||
newWithOld = CMPCertificate.getInstance(seq.getObjectAt(1));
|
||||
newWithNew = CMPCertificate.getInstance(seq.getObjectAt(2));
|
||||
}
|
||||
|
||||
public static CAKeyUpdAnnContent getInstance(Object o)
|
||||
{
|
||||
if (o instanceof CAKeyUpdAnnContent)
|
||||
{
|
||||
return (CAKeyUpdAnnContent)o;
|
||||
}
|
||||
|
||||
if (o instanceof ASN1Sequence)
|
||||
{
|
||||
return new CAKeyUpdAnnContent((ASN1Sequence)o);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public CMPCertificate getOldWithNew()
|
||||
{
|
||||
return oldWithNew;
|
||||
}
|
||||
|
||||
public CMPCertificate getNewWithOld()
|
||||
{
|
||||
return newWithOld;
|
||||
}
|
||||
|
||||
public CMPCertificate getNewWithNew()
|
||||
{
|
||||
return newWithNew;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* CAKeyUpdAnnContent ::= SEQUENCE {
|
||||
* oldWithNew CMPCertificate, -- old pub signed with new priv
|
||||
* newWithOld CMPCertificate, -- new pub signed with old priv
|
||||
* newWithNew CMPCertificate -- new pub signed with new priv
|
||||
* }
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
v.add(oldWithNew);
|
||||
v.add(newWithOld);
|
||||
v.add(newWithNew);
|
||||
|
||||
return new DERSequence(v);
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Choice;
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.x509.X509CertificateStructure;
|
||||
|
||||
public class CMPCertificate
|
||||
extends ASN1Encodable
|
||||
implements ASN1Choice
|
||||
{
|
||||
private X509CertificateStructure x509v3PKCert;
|
||||
|
||||
public CMPCertificate(X509CertificateStructure x509v3PKCert)
|
||||
{
|
||||
if (x509v3PKCert.getVersion() != 3)
|
||||
{
|
||||
throw new IllegalArgumentException("only version 3 certificates allowed");
|
||||
}
|
||||
|
||||
this.x509v3PKCert = x509v3PKCert;
|
||||
}
|
||||
|
||||
public static CMPCertificate getInstance(Object o)
|
||||
{
|
||||
if (o instanceof CMPCertificate)
|
||||
{
|
||||
return (CMPCertificate)o;
|
||||
}
|
||||
|
||||
if (o instanceof X509CertificateStructure)
|
||||
{
|
||||
return new CMPCertificate((X509CertificateStructure)o);
|
||||
}
|
||||
|
||||
if (o instanceof ASN1Sequence)
|
||||
{
|
||||
return new CMPCertificate(X509CertificateStructure.getInstance(o));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public X509CertificateStructure getX509v3PKCert()
|
||||
{
|
||||
return x509v3PKCert;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* CMPCertificate ::= CHOICE {
|
||||
* x509v3PKCert Certificate
|
||||
* }
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
return x509v3PKCert.toASN1Object();
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.x509.CertificateList;
|
||||
|
||||
public class CRLAnnContent
|
||||
extends ASN1Encodable
|
||||
{
|
||||
private ASN1Sequence content;
|
||||
|
||||
private CRLAnnContent(ASN1Sequence seq)
|
||||
{
|
||||
content = seq;
|
||||
}
|
||||
|
||||
public static CRLAnnContent getInstance(Object o)
|
||||
{
|
||||
if (o instanceof CRLAnnContent)
|
||||
{
|
||||
return (CRLAnnContent)o;
|
||||
}
|
||||
|
||||
if (o instanceof ASN1Sequence)
|
||||
{
|
||||
return new CRLAnnContent((ASN1Sequence)o);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public CertificateList[] toCertificateListArray()
|
||||
{
|
||||
CertificateList[] result = new CertificateList[content.size()];
|
||||
|
||||
for (int i = 0; i != result.length; i++)
|
||||
{
|
||||
result[i] = CertificateList.getInstance(content.getObjectAt(i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* CRLAnnContent ::= SEQUENCE OF CertificateList
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
return content;
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
|
||||
public class CertConfirmContent
|
||||
extends ASN1Encodable
|
||||
{
|
||||
private ASN1Sequence content;
|
||||
|
||||
private CertConfirmContent(ASN1Sequence seq)
|
||||
{
|
||||
content = seq;
|
||||
}
|
||||
|
||||
public static CertConfirmContent getInstance(Object o)
|
||||
{
|
||||
if (o instanceof CertConfirmContent)
|
||||
{
|
||||
return (CertConfirmContent)o;
|
||||
}
|
||||
|
||||
if (o instanceof ASN1Sequence)
|
||||
{
|
||||
return new CertConfirmContent((ASN1Sequence)o);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public CertStatus[] toCertStatusArray()
|
||||
{
|
||||
CertStatus[] result = new CertStatus[content.size()];
|
||||
|
||||
for (int i = 0; i != result.length; i++)
|
||||
{
|
||||
result[i] = CertStatus.getInstance(content.getObjectAt(i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* CertConfirmContent ::= SEQUENCE OF CertStatus
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
return content;
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Choice;
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERTaggedObject;
|
||||
import org.bouncycastle.asn1.crmf.EncryptedValue;
|
||||
|
||||
public class CertOrEncCert
|
||||
extends ASN1Encodable
|
||||
implements ASN1Choice
|
||||
{
|
||||
private CMPCertificate certificate;
|
||||
private EncryptedValue encryptedCert;
|
||||
|
||||
private CertOrEncCert(ASN1TaggedObject tagged)
|
||||
{
|
||||
if (tagged.getTagNo() == 0)
|
||||
{
|
||||
certificate = CMPCertificate.getInstance(tagged.getObject());
|
||||
}
|
||||
else if (tagged.getTagNo() == 1)
|
||||
{
|
||||
encryptedCert = EncryptedValue.getInstance(tagged.getObject());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("unknown tag: " + tagged.getTagNo());
|
||||
}
|
||||
}
|
||||
|
||||
public static CertOrEncCert getInstance(Object o)
|
||||
{
|
||||
if (o instanceof CertOrEncCert)
|
||||
{
|
||||
return (CertOrEncCert)o;
|
||||
}
|
||||
|
||||
if (o instanceof ASN1TaggedObject)
|
||||
{
|
||||
return new CertOrEncCert((ASN1TaggedObject)o);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public CMPCertificate getCertificate()
|
||||
{
|
||||
return certificate;
|
||||
}
|
||||
|
||||
public EncryptedValue getEncryptedCert()
|
||||
{
|
||||
return encryptedCert;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* CertOrEncCert ::= CHOICE {
|
||||
* certificate [0] CMPCertificate,
|
||||
* encryptedCert [1] EncryptedValue
|
||||
* }
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
if (certificate != null)
|
||||
{
|
||||
return new DERTaggedObject(true, 0, certificate);
|
||||
}
|
||||
|
||||
return new DERTaggedObject(true, 1, encryptedCert);
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.DERTaggedObject;
|
||||
|
||||
public class CertRepMessage
|
||||
extends ASN1Encodable
|
||||
{
|
||||
private ASN1Sequence caPubs;
|
||||
private ASN1Sequence response;
|
||||
|
||||
private CertRepMessage(ASN1Sequence seq)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (seq.size() > 1)
|
||||
{
|
||||
caPubs = ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(index++), true);
|
||||
}
|
||||
|
||||
response = ASN1Sequence.getInstance(seq.getObjectAt(index));
|
||||
}
|
||||
|
||||
public static CertRepMessage getInstance(Object o)
|
||||
{
|
||||
if (o instanceof CertRepMessage)
|
||||
{
|
||||
return (CertRepMessage)o;
|
||||
}
|
||||
|
||||
if (o instanceof ASN1Sequence)
|
||||
{
|
||||
return new CertRepMessage((ASN1Sequence)o);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public CMPCertificate[] getCaPubs()
|
||||
{
|
||||
if (caPubs == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
CMPCertificate[] results = new CMPCertificate[caPubs.size()];
|
||||
|
||||
for (int i = 0; i != results.length; i++)
|
||||
{
|
||||
results[i] = CMPCertificate.getInstance(caPubs.getObjectAt(i));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public CertResponse[] getResponse()
|
||||
{
|
||||
CertResponse[] results = new CertResponse[response.size()];
|
||||
|
||||
for (int i = 0; i != results.length; i++)
|
||||
{
|
||||
results[i] = CertResponse.getInstance(response.getObjectAt(i));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* CertRepMessage ::= SEQUENCE {
|
||||
* caPubs [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
|
||||
* OPTIONAL,
|
||||
* response SEQUENCE OF CertResponse
|
||||
* }
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
if (caPubs != null)
|
||||
{
|
||||
v.add(new DERTaggedObject(true, 1, caPubs));
|
||||
}
|
||||
|
||||
v.add(response);
|
||||
|
||||
return new DERSequence(v);
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DEREncodable;
|
||||
import org.bouncycastle.asn1.DERInteger;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
|
||||
public class CertResponse
|
||||
extends ASN1Encodable
|
||||
{
|
||||
private DERInteger certReqId;
|
||||
private PKIStatusInfo status;
|
||||
private CertifiedKeyPair certifiedKeyPair;
|
||||
private ASN1OctetString rspInfo;
|
||||
|
||||
private CertResponse(ASN1Sequence seq)
|
||||
{
|
||||
certReqId = DERInteger.getInstance(seq.getObjectAt(0));
|
||||
status = PKIStatusInfo.getInstance(seq.getObjectAt(1));
|
||||
|
||||
if (seq.size() >= 3)
|
||||
{
|
||||
if (seq.size() == 3)
|
||||
{
|
||||
DEREncodable o = seq.getObjectAt(2);
|
||||
if (o instanceof ASN1OctetString)
|
||||
{
|
||||
rspInfo = ASN1OctetString.getInstance(o);
|
||||
}
|
||||
else
|
||||
{
|
||||
certifiedKeyPair = CertifiedKeyPair.getInstance(o);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
certifiedKeyPair = CertifiedKeyPair.getInstance(seq.getObjectAt(2));
|
||||
rspInfo = ASN1OctetString.getInstance(seq.getObjectAt(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static CertResponse getInstance(Object o)
|
||||
{
|
||||
if (o instanceof CertResponse)
|
||||
{
|
||||
return (CertResponse)o;
|
||||
}
|
||||
|
||||
if (o instanceof ASN1Sequence)
|
||||
{
|
||||
return new CertResponse((ASN1Sequence)o);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public DERInteger getCertReqId()
|
||||
{
|
||||
return certReqId;
|
||||
}
|
||||
|
||||
public PKIStatusInfo getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public CertifiedKeyPair getCertifiedKeyPair()
|
||||
{
|
||||
return certifiedKeyPair;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* CertResponse ::= SEQUENCE {
|
||||
* certReqId INTEGER,
|
||||
* -- to match this response with corresponding request (a value
|
||||
* -- of -1 is to be used if certReqId is not specified in the
|
||||
* -- corresponding request)
|
||||
* status PKIStatusInfo,
|
||||
* certifiedKeyPair CertifiedKeyPair OPTIONAL,
|
||||
* rspInfo OCTET STRING OPTIONAL
|
||||
* -- analogous to the id-regInfo-utf8Pairs string defined
|
||||
* -- for regInfo in CertReqMsg [CRMF]
|
||||
* }
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
v.add(certReqId);
|
||||
v.add(status);
|
||||
|
||||
if (certifiedKeyPair != null)
|
||||
{
|
||||
v.add(certifiedKeyPair);
|
||||
}
|
||||
|
||||
if (rspInfo != null)
|
||||
{
|
||||
v.add(rspInfo);
|
||||
}
|
||||
|
||||
return new DERSequence(v);
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERInteger;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
|
||||
public class CertStatus
|
||||
extends ASN1Encodable
|
||||
{
|
||||
private ASN1OctetString certHash;
|
||||
private DERInteger certReqId;
|
||||
private PKIStatusInfo statusInfo;
|
||||
|
||||
private CertStatus(ASN1Sequence seq)
|
||||
{
|
||||
certHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
|
||||
certReqId = DERInteger.getInstance(seq.getObjectAt(1));
|
||||
|
||||
if (seq.size() > 2)
|
||||
{
|
||||
statusInfo = PKIStatusInfo.getInstance(seq.getObjectAt(2));
|
||||
}
|
||||
}
|
||||
|
||||
public static CertStatus getInstance(Object o)
|
||||
{
|
||||
if (o instanceof CertStatus)
|
||||
{
|
||||
return (CertStatus)o;
|
||||
}
|
||||
|
||||
if (o instanceof ASN1Sequence)
|
||||
{
|
||||
return new CertStatus((ASN1Sequence)o);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public DERInteger getCertReqId()
|
||||
{
|
||||
return certReqId;
|
||||
}
|
||||
|
||||
public PKIStatusInfo getStatusInfo()
|
||||
{
|
||||
return statusInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* CertStatus ::= SEQUENCE {
|
||||
* certHash OCTET STRING,
|
||||
* -- the hash of the certificate, using the same hash algorithm
|
||||
* -- as is used to create and verify the certificate signature
|
||||
* certReqId INTEGER,
|
||||
* -- to match this confirmation with the corresponding req/rep
|
||||
* statusInfo PKIStatusInfo OPTIONAL
|
||||
* }
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
v.add(certHash);
|
||||
v.add(certReqId);
|
||||
|
||||
if (statusInfo != null)
|
||||
{
|
||||
v.add(statusInfo);
|
||||
}
|
||||
|
||||
return new DERSequence(v);
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.DERTaggedObject;
|
||||
import org.bouncycastle.asn1.crmf.EncryptedValue;
|
||||
import org.bouncycastle.asn1.crmf.PKIPublicationInfo;
|
||||
|
||||
public class CertifiedKeyPair
|
||||
extends ASN1Encodable
|
||||
{
|
||||
private CertOrEncCert certOrEncCert;
|
||||
private EncryptedValue privateKey;
|
||||
private PKIPublicationInfo publicationInfo;
|
||||
|
||||
private CertifiedKeyPair(ASN1Sequence seq)
|
||||
{
|
||||
certOrEncCert = CertOrEncCert.getInstance(seq.getObjectAt(0));
|
||||
|
||||
if (seq.size() >= 2)
|
||||
{
|
||||
if (seq.size() == 2)
|
||||
{
|
||||
ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
|
||||
if (tagged.getTagNo() == 0)
|
||||
{
|
||||
privateKey = EncryptedValue.getInstance(tagged.getObject());
|
||||
}
|
||||
else
|
||||
{
|
||||
publicationInfo = PKIPublicationInfo.getInstance(tagged.getObject());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
privateKey = EncryptedValue.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(1)));
|
||||
publicationInfo = PKIPublicationInfo.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static CertifiedKeyPair getInstance(Object o)
|
||||
{
|
||||
if (o instanceof CertifiedKeyPair)
|
||||
{
|
||||
return (CertifiedKeyPair)o;
|
||||
}
|
||||
|
||||
if (o instanceof ASN1Sequence)
|
||||
{
|
||||
return new CertifiedKeyPair((ASN1Sequence)o);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public CertOrEncCert getCertOrEncCert()
|
||||
{
|
||||
return certOrEncCert;
|
||||
}
|
||||
|
||||
public EncryptedValue getPrivateKey()
|
||||
{
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public PKIPublicationInfo getPublicationInfo()
|
||||
{
|
||||
return publicationInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* CertifiedKeyPair ::= SEQUENCE {
|
||||
* certOrEncCert CertOrEncCert,
|
||||
* privateKey [0] EncryptedValue OPTIONAL,
|
||||
* -- see [CRMF] for comment on encoding
|
||||
* publicationInfo [1] PKIPublicationInfo OPTIONAL
|
||||
* }
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
v.add(certOrEncCert);
|
||||
|
||||
if (privateKey != null)
|
||||
{
|
||||
v.add(new DERTaggedObject(true, 0, privateKey));
|
||||
}
|
||||
|
||||
if (publicationInfo != null)
|
||||
{
|
||||
v.add(new DERTaggedObject(true, 1, publicationInfo));
|
||||
}
|
||||
|
||||
return new DERSequence(v);
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
package org.bouncycastle.asn1.cmp;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1EncodableVector;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERObject;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||
|
||||
public class Challenge
|
||||
extends ASN1Encodable
|
||||
{
|
||||
private AlgorithmIdentifier owf;
|
||||
private ASN1OctetString witness;
|
||||
private ASN1OctetString challenge;
|
||||
|
||||
private Challenge(ASN1Sequence seq)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (seq.size() == 3)
|
||||
{
|
||||
owf = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
|
||||
}
|
||||
|
||||
witness = ASN1OctetString.getInstance(seq.getObjectAt(index++));
|
||||
challenge = ASN1OctetString.getInstance(seq.getObjectAt(index));
|
||||
}
|
||||
|
||||
public static Challenge getInstance(Object o)
|
||||
{
|
||||
if (o instanceof Challenge)
|
||||
{
|
||||
return (Challenge)o;
|
||||
}
|
||||
|
||||
if (o instanceof ASN1Sequence)
|
||||
{
|
||||
return new Challenge((ASN1Sequence)o);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
|
||||
}
|
||||
|
||||
public AlgorithmIdentifier getOwf()
|
||||
{
|
||||
return owf;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Challenge ::= SEQUENCE {
|
||||
* owf AlgorithmIdentifier OPTIONAL,
|
||||
*
|
||||
* -- MUST be present in the first Challenge; MAY be omitted in
|
||||
* -- any subsequent Challenge in POPODecKeyChallContent (if
|
||||
* -- omitted, then the owf used in the immediately preceding
|
||||
* -- Challenge is to be used).
|
||||
*
|
||||
* witness OCTET STRING,
|
||||
* -- the result of applying the one-way function (owf) to a
|
||||
* -- randomly-generated INTEGER, A. [Note that a different
|
||||
* -- INTEGER MUST be used for each Challenge.]
|
||||
* challenge OCTET STRING
|
||||
* -- the encryption (under the public key for which the cert.
|
||||
* -- request is being made) of Rand, where Rand is specified as
|
||||
* -- Rand ::= SEQUENCE {
|
||||
* -- int INTEGER,
|
||||
* -- - the randomly-generated INTEGER A (above)
|
||||
* -- sender GeneralName
|
||||
* -- - the sender's name (as included in PKIHeader)
|
||||
* -- }
|
||||
* }
|
||||
* </pre>
|
||||
* @return a basic ASN.1 object representation.
|
||||
*/
|
||||
@Override
|
||||
public DERObject toASN1Object()
|
||||
{
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
|
||||
addOptional(v, owf);
|
||||
v.add(witness);
|
||||
v.add(challenge);
|
||||
|
||||
return new DERSequence(v);
|
||||
}
|
||||
|
||||
private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
v.add(obj);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user