diff options
Diffstat (limited to 'pkix/src/main/jdk1.1/org/bouncycastle/cert')
10 files changed, 1567 insertions, 0 deletions
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/cmp/GeneralPKIMessage.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/cmp/GeneralPKIMessage.java new file mode 100644 index 00000000..08c42c7d --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/cmp/GeneralPKIMessage.java @@ -0,0 +1,82 @@ +package org.bouncycastle.cert.cmp; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.cmp.PKIBody; +import org.bouncycastle.asn1.cmp.PKIHeader; +import org.bouncycastle.asn1.cmp.PKIMessage; +import org.bouncycastle.cert.CertIOException; + +/** + * General wrapper for a generic PKIMessage + */ +public class GeneralPKIMessage +{ + private PKIMessage pkiMessage; + + private static PKIMessage parseBytes(byte[] encoding) + throws IOException + { + try + { + return PKIMessage.getInstance(ASN1Primitive.fromByteArray(encoding)); + } + catch (ClassCastException e) + { + throw new CertIOException("malformed data: " + e.getMessage(), e); + } + catch (IllegalArgumentException e) + { + throw new CertIOException("malformed data: " + e.getMessage(), e); + } + } + + /** + * Create a PKIMessage from the passed in bytes. + * + * @param encoding BER/DER encoding of the PKIMessage + * @throws IOException in the event of corrupted data, or an incorrect structure. + */ + public GeneralPKIMessage(byte[] encoding) + throws IOException + { + this(parseBytes(encoding)); + } + + /** + * Wrap a PKIMessage ASN.1 structure. + * + * @param pkiMessage base PKI message. + */ + public GeneralPKIMessage(PKIMessage pkiMessage) + { + this.pkiMessage = pkiMessage; + } + + public PKIHeader getHeader() + { + return pkiMessage.getHeader(); + } + + public PKIBody getBody() + { + return pkiMessage.getBody(); + } + + /** + * Return true if this message has protection bits on it. A return value of true + * indicates the message can be used to construct a ProtectedPKIMessage. + * + * @return true if message has protection, false otherwise. + */ + public boolean hasProtection() + { + return pkiMessage.getHeader().getProtectionAlg() != null; + } + + public PKIMessage toASN1Structure() + { + return pkiMessage; + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/CertificateRequestMessage.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/CertificateRequestMessage.java new file mode 100644 index 00000000..ae328d68 --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/CertificateRequestMessage.java @@ -0,0 +1,309 @@ +package org.bouncycastle.cert.crmf; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.DERUTF8String; +import org.bouncycastle.asn1.crmf.AttributeTypeAndValue; +import org.bouncycastle.asn1.crmf.CRMFObjectIdentifiers; +import org.bouncycastle.asn1.crmf.CertReqMsg; +import org.bouncycastle.asn1.crmf.CertTemplate; +import org.bouncycastle.asn1.crmf.Controls; +import org.bouncycastle.asn1.crmf.PKIArchiveOptions; +import org.bouncycastle.asn1.crmf.PKMACValue; +import org.bouncycastle.asn1.crmf.POPOSigningKey; +import org.bouncycastle.asn1.crmf.ProofOfPossession; +import org.bouncycastle.cert.CertIOException; +import org.bouncycastle.operator.ContentVerifier; +import org.bouncycastle.operator.ContentVerifierProvider; +import org.bouncycastle.operator.OperatorCreationException; + +/** + * Carrier for a CRMF CertReqMsg. + */ +public class CertificateRequestMessage +{ + public static final int popRaVerified = ProofOfPossession.TYPE_RA_VERIFIED; + public static final int popSigningKey = ProofOfPossession.TYPE_SIGNING_KEY; + public static final int popKeyEncipherment = ProofOfPossession.TYPE_KEY_ENCIPHERMENT; + public static final int popKeyAgreement = ProofOfPossession.TYPE_KEY_AGREEMENT; + + private CertReqMsg certReqMsg; + private Controls controls; + + private static CertReqMsg parseBytes(byte[] encoding) + throws IOException + { + try + { + return CertReqMsg.getInstance(ASN1Primitive.fromByteArray(encoding)); + } + catch (ClassCastException e) + { + throw new CertIOException("malformed data: " + e.getMessage(), e); + } + catch (IllegalArgumentException e) + { + throw new CertIOException("malformed data: " + e.getMessage(), e); + } + } + + /** + * Create a CertificateRequestMessage from the passed in bytes. + * + * @param certReqMsg BER/DER encoding of the CertReqMsg structure. + * @throws IOException in the event of corrupted data, or an incorrect structure. + */ + public CertificateRequestMessage(byte[] certReqMsg) + throws IOException + { + this(parseBytes(certReqMsg)); + } + + public CertificateRequestMessage(CertReqMsg certReqMsg) + { + this.certReqMsg = certReqMsg; + this.controls = certReqMsg.getCertReq().getControls(); + } + + /** + * Return the underlying ASN.1 object defining this CertificateRequestMessage object. + * + * @return a CertReqMsg. + */ + public CertReqMsg toASN1Structure() + { + return certReqMsg; + } + + /** + * Return the certificate template contained in this message. + * + * @return a CertTemplate structure. + */ + public CertTemplate getCertTemplate() + { + return this.certReqMsg.getCertReq().getCertTemplate(); + } + + /** + * Return whether or not this request has control values associated with it. + * + * @return true if there are control values present, false otherwise. + */ + public boolean hasControls() + { + return controls != null; + } + + /** + * Return whether or not this request has a specific type of control value. + * + * @param type the type OID for the control value we are checking for. + * @return true if a control value of type is present, false otherwise. + */ + public boolean hasControl(ASN1ObjectIdentifier type) + { + return findControl(type) != null; + } + + /** + * Return a control value of the specified type. + * + * @param type the type OID for the control value we are checking for. + * @return the control value if present, null otherwise. + */ + public Control getControl(ASN1ObjectIdentifier type) + { + AttributeTypeAndValue found = findControl(type); + + if (found != null) + { + if (found.getType().equals(CRMFObjectIdentifiers.id_regCtrl_pkiArchiveOptions)) + { + return new PKIArchiveControl(PKIArchiveOptions.getInstance(found.getValue())); + } + if (found.getType().equals(CRMFObjectIdentifiers.id_regCtrl_regToken)) + { + return new RegTokenControl(DERUTF8String.getInstance(found.getValue())); + } + if (found.getType().equals(CRMFObjectIdentifiers.id_regCtrl_authenticator)) + { + return new AuthenticatorControl(DERUTF8String.getInstance(found.getValue())); + } + } + + return null; + } + + private AttributeTypeAndValue findControl(ASN1ObjectIdentifier type) + { + if (controls == null) + { + return null; + } + + AttributeTypeAndValue[] tAndVs = controls.toAttributeTypeAndValueArray(); + AttributeTypeAndValue found = null; + + for (int i = 0; i != tAndVs.length; i++) + { + if (tAndVs[i].getType().equals(type)) + { + found = tAndVs[i]; + break; + } + } + + return found; + } + + /** + * Return whether or not this request message has a proof-of-possession field in it. + * + * @return true if proof-of-possession is present, false otherwise. + */ + public boolean hasProofOfPossession() + { + return this.certReqMsg.getPopo() != null; + } + + /** + * Return the type of the proof-of-possession this request message provides. + * + * @return one of: popRaVerified, popSigningKey, popKeyEncipherment, popKeyAgreement + */ + public int getProofOfPossessionType() + { + return this.certReqMsg.getPopo().getType(); + } + + /** + * Return whether or not the proof-of-possession (POP) is of the type popSigningKey and + * it has a public key MAC associated with it. + * + * @return true if POP is popSigningKey and a PKMAC is present, false otherwise. + */ + public boolean hasSigningKeyProofOfPossessionWithPKMAC() + { + ProofOfPossession pop = certReqMsg.getPopo(); + + if (pop.getType() == popSigningKey) + { + POPOSigningKey popoSign = POPOSigningKey.getInstance(pop.getObject()); + + return popoSign.getPoposkInput().getPublicKeyMAC() != null; + } + + return false; + } + + /** + * Return whether or not a signing key proof-of-possession (POP) is valid. + * + * @param verifierProvider a provider that can produce content verifiers for the signature contained in this POP. + * @return true if the POP is valid, false otherwise. + * @throws CRMFException if there is a problem in verification or content verifier creation. + * @throws IllegalStateException if POP not appropriate. + */ + public boolean isValidSigningKeyPOP(ContentVerifierProvider verifierProvider) + throws CRMFException, IllegalStateException + { + ProofOfPossession pop = certReqMsg.getPopo(); + + if (pop.getType() == popSigningKey) + { + POPOSigningKey popoSign = POPOSigningKey.getInstance(pop.getObject()); + + if (popoSign.getPoposkInput() != null && popoSign.getPoposkInput().getPublicKeyMAC() != null) + { + throw new IllegalStateException("verification requires password check"); + } + + return verifySignature(verifierProvider, popoSign); + } + else + { + throw new IllegalStateException("not Signing Key type of proof of possession"); + } + } + + /** + * Return whether or not a signing key proof-of-possession (POP), with an associated PKMAC, is valid. + * + * @param verifierProvider a provider that can produce content verifiers for the signature contained in this POP. + * @param macBuilder a suitable PKMACBuilder to create the MAC verifier. + * @param password the password used to key the MAC calculation. + * @return true if the POP is valid, false otherwise. + * @throws CRMFException if there is a problem in verification or content verifier creation. + * @throws IllegalStateException if POP not appropriate. + */ + public boolean isValidSigningKeyPOP(ContentVerifierProvider verifierProvider, PKMACBuilder macBuilder, char[] password) + throws CRMFException, IllegalStateException + { + ProofOfPossession pop = certReqMsg.getPopo(); + + if (pop.getType() == popSigningKey) + { + POPOSigningKey popoSign = POPOSigningKey.getInstance(pop.getObject()); + + if (popoSign.getPoposkInput() == null || popoSign.getPoposkInput().getSender() != null) + { + throw new IllegalStateException("no PKMAC present in proof of possession"); + } + + PKMACValue pkMAC = popoSign.getPoposkInput().getPublicKeyMAC(); + PKMACValueVerifier macVerifier = new PKMACValueVerifier(macBuilder); + + if (macVerifier.isValid(pkMAC, password, this.getCertTemplate().getPublicKey())) + { + return verifySignature(verifierProvider, popoSign); + } + + return false; + } + else + { + throw new IllegalStateException("not Signing Key type of proof of possession"); + } + } + + private boolean verifySignature(ContentVerifierProvider verifierProvider, POPOSigningKey popoSign) + throws CRMFException + { + ContentVerifier verifier; + + try + { + verifier = verifierProvider.get(popoSign.getAlgorithmIdentifier()); + } + catch (OperatorCreationException e) + { + throw new CRMFException("unable to create verifier: " + e.getMessage(), e); + } + + if (popoSign.getPoposkInput() != null) + { + CRMFUtil.derEncodeToStream(popoSign.getPoposkInput(), verifier.getOutputStream()); + } + else + { + CRMFUtil.derEncodeToStream(certReqMsg.getCertReq(), verifier.getOutputStream()); + } + + return verifier.verify(popoSign.getSignature().getBytes()); + } + + /** + * Return the ASN.1 encoding of the certReqMsg we wrap. + * + * @return a byte array containing the binary encoding of the certReqMsg. + * @throws IOException if there is an exception creating the encoding. + */ + public byte[] getEncoded() + throws IOException + { + return certReqMsg.getEncoded(); + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/FixedLengthMGF1Padder.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/FixedLengthMGF1Padder.java new file mode 100644 index 00000000..f100cb67 --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/FixedLengthMGF1Padder.java @@ -0,0 +1,120 @@ +package org.bouncycastle.cert.crmf; + +import java.security.SecureRandom; + +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.crypto.digests.SHA1Digest; +import org.bouncycastle.crypto.generators.MGF1BytesGenerator; +import org.bouncycastle.crypto.params.MGFParameters; + +/** + * An encrypted value padder that uses MGF1 as the basis of the padding. + */ +public class FixedLengthMGF1Padder + implements EncryptedValuePadder +{ + private int length; + private SecureRandom random; + private Digest dig = new SHA1Digest(); + + /** + * Create a padder to so that padded output will always be at least + * length bytes long. + * + * @param length fixed length for padded output. + */ + public FixedLengthMGF1Padder(int length) + { + this(length, null); + } + + /** + * Create a padder to so that padded output will always be at least + * length bytes long, using the passed in source of randomness to + * provide the random material for the padder. + * + * @param length fixed length for padded output. + * @param random a source of randomness. + */ + public FixedLengthMGF1Padder(int length, SecureRandom random) + { + this.length = length; + this.random = random; + } + + public byte[] getPaddedData(byte[] data) + { + byte[] bytes = new byte[length]; + byte[] seed = new byte[dig.getDigestSize()]; + byte[] mask = new byte[length - dig.getDigestSize()]; + + if (random == null) + { + random = new SecureRandom(); + } + + random.nextBytes(seed); + + MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig); + + maskGen.init(new MGFParameters(seed)); + + maskGen.generateBytes(mask, 0, mask.length); + + System.arraycopy(seed, 0, bytes, 0, seed.length); + System.arraycopy(data, 0, bytes, seed.length, data.length); + + for (int i = seed.length + data.length + 1; i != bytes.length; i++) + { + bytes[i] = (byte)(1 + Math.abs(random.nextInt()) % 254); + } + + for (int i = 0; i != mask.length; i++) + { + bytes[i + seed.length] ^= mask[i]; + } + + return bytes; + } + + public byte[] getUnpaddedData(byte[] paddedData) + { + byte[] seed = new byte[dig.getDigestSize()]; + byte[] mask = new byte[length - dig.getDigestSize()]; + + System.arraycopy(paddedData, 0, seed, 0, seed.length); + + MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig); + + maskGen.init(new MGFParameters(seed)); + + maskGen.generateBytes(mask, 0, mask.length); + + for (int i = 0; i != mask.length; i++) + { + paddedData[i + seed.length] ^= mask[i]; + } + + int end = 0; + + for (int i = paddedData.length - 1; i != seed.length; i--) + { + if (paddedData[i] == 0) + { + end = i; + break; + } + } + + if (end == 0) + { + throw new IllegalStateException("bad padding in encoding"); + } + + byte[] data = new byte[end - seed.length]; + + System.arraycopy(paddedData, seed.length, data, 0, data.length); + + return data; + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java new file mode 100644 index 00000000..0b451644 --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java @@ -0,0 +1,485 @@ +package org.bouncycastle.cert.crmf.jcajce; + +import java.io.IOException; +import java.security.AlgorithmParameterGenerator; +import java.security.AlgorithmParameters; +import java.security.GeneralSecurityException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; +import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.Mac; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.RC2ParameterSpec; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Null; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.iana.IANAObjectIdentifiers; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import org.bouncycastle.cert.crmf.CRMFException; +import org.bouncycastle.cms.CMSAlgorithm; +import org.bouncycastle.cms.CMSEnvelopedDataGenerator; +import org.bouncycastle.jcajce.JcaJceHelper; + +class CRMFHelper +{ + protected static final Map BASE_CIPHER_NAMES = new HashMap(); + protected static final Map CIPHER_ALG_NAMES = new HashMap(); + protected static final Map DIGEST_ALG_NAMES = new HashMap(); + protected static final Map KEY_ALG_NAMES = new HashMap(); + protected static final Map MAC_ALG_NAMES = new HashMap(); + + static + { + BASE_CIPHER_NAMES.put(PKCSObjectIdentifiers.des_EDE3_CBC, "DESEDE"); + BASE_CIPHER_NAMES.put(NISTObjectIdentifiers.id_aes128_CBC, "AES"); + BASE_CIPHER_NAMES.put(NISTObjectIdentifiers.id_aes192_CBC, "AES"); + BASE_CIPHER_NAMES.put(NISTObjectIdentifiers.id_aes256_CBC, "AES"); + + CIPHER_ALG_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDE/CBC/PKCS5Padding"); + CIPHER_ALG_NAMES.put(CMSAlgorithm.AES128_CBC, "AES/CBC/PKCS5Padding"); + CIPHER_ALG_NAMES.put(CMSAlgorithm.AES192_CBC, "AES/CBC/PKCS5Padding"); + CIPHER_ALG_NAMES.put(CMSAlgorithm.AES256_CBC, "AES/CBC/PKCS5Padding"); + CIPHER_ALG_NAMES.put(new ASN1ObjectIdentifier(PKCSObjectIdentifiers.rsaEncryption.getId()), "RSA/ECB/PKCS1Padding"); + + DIGEST_ALG_NAMES.put(OIWObjectIdentifiers.idSHA1, "SHA1"); + DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha224, "SHA224"); + DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha256, "SHA256"); + DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha384, "SHA384"); + DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha512, "SHA512"); + + MAC_ALG_NAMES.put(IANAObjectIdentifiers.hmacSHA1, "HMACSHA1"); + MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA1, "HMACSHA1"); + MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA224, "HMACSHA224"); + MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA256, "HMACSHA256"); + MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA384, "HMACSHA384"); + MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA512, "HMACSHA512"); + + KEY_ALG_NAMES.put(PKCSObjectIdentifiers.rsaEncryption, "RSA"); + KEY_ALG_NAMES.put(X9ObjectIdentifiers.id_dsa, "DSA"); + } + + private JcaJceHelper helper; + + CRMFHelper(JcaJceHelper helper) + { + this.helper = helper; + } + + PublicKey toPublicKey(SubjectPublicKeyInfo subjectPublicKeyInfo) + throws CRMFException + { + + try + { + X509EncodedKeySpec xspec = new X509EncodedKeySpec(new DERBitString(subjectPublicKeyInfo).getBytes()); + AlgorithmIdentifier keyAlg = subjectPublicKeyInfo.getAlgorithmId(); + return createKeyFactory(keyAlg.getAlgorithm()).generatePublic(xspec); + } + catch (IOException e) + { + throw new CRMFException("invalid key: " + e.getMessage(), e); + } + catch (InvalidKeySpecException e) + { + throw new CRMFException("invalid key: " + e.getMessage(), e); + } + } + + Cipher createCipher(ASN1ObjectIdentifier algorithm) + throws CRMFException + { + try + { + String cipherName = (String)CIPHER_ALG_NAMES.get(algorithm); + + if (cipherName != null) + { + try + { + // this is reversed as the Sun policy files now allow unlimited strength RSA + return helper.createCipher(cipherName); + } + catch (NoSuchAlgorithmException e) + { + // Ignore + } + } + return helper.createCipher(algorithm.getId()); + } + catch (NoSuchPaddingException e) + { + throw new CRMFException("cannot create cipher: " + e.getMessage(), e); + } + catch (NoSuchAlgorithmException e) + { + throw new CRMFException("cannot create cipher: " + e.getMessage(), e); + } + catch (NoSuchProviderException e) + { + throw new CRMFException("cannot create cipher: " + e.getMessage(), e); + } + } + + public KeyGenerator createKeyGenerator(ASN1ObjectIdentifier algorithm) + throws CRMFException + { + try + { + String cipherName = (String)BASE_CIPHER_NAMES.get(algorithm); + + if (cipherName != null) + { + try + { + // this is reversed as the Sun policy files now allow unlimited strength RSA + return helper.createKeyGenerator(cipherName); + } + catch (NoSuchAlgorithmException e) + { + // Ignore + } + } + return helper.createKeyGenerator(algorithm.getId()); + } + catch (NoSuchAlgorithmException e) + { + throw new CRMFException("cannot create key generator: " + e.getMessage(), e); + } + catch (NoSuchProviderException e) + { + throw new CRMFException("cannot create key generator: " + e.getMessage(), e); + } + } + + Cipher createContentCipher(final Key sKey, final AlgorithmIdentifier encryptionAlgID) + throws CRMFException + { + return (Cipher)execute(new JCECallback() + { + public Object doInJCE() + throws CRMFException, InvalidAlgorithmParameterException, + InvalidKeyException, InvalidParameterSpecException, NoSuchAlgorithmException, + NoSuchPaddingException, NoSuchProviderException + { + Cipher cipher = createCipher(encryptionAlgID.getAlgorithm()); + ASN1Primitive sParams = (ASN1Primitive)encryptionAlgID.getParameters(); + String encAlg = encryptionAlgID.getAlgorithm().getId(); + + if (sParams != null && !(sParams instanceof ASN1Null)) + { + try + { + AlgorithmParameters params = createAlgorithmParameters(encryptionAlgID.getAlgorithm()); + + try + { + params.init(sParams.getEncoded(), "ASN.1"); + } + catch (IOException e) + { + throw new CRMFException("error decoding algorithm parameters.", e); + } + + cipher.init(Cipher.DECRYPT_MODE, sKey, params); + } + catch (NoSuchAlgorithmException e) + { + if (encAlg.equals(CMSEnvelopedDataGenerator.DES_EDE3_CBC) + || encAlg.equals(CMSEnvelopedDataGenerator.IDEA_CBC) + || encAlg.equals(CMSEnvelopedDataGenerator.AES128_CBC) + || encAlg.equals(CMSEnvelopedDataGenerator.AES192_CBC) + || encAlg.equals(CMSEnvelopedDataGenerator.AES256_CBC)) + { + cipher.init(Cipher.DECRYPT_MODE, sKey, new IvParameterSpec( + ASN1OctetString.getInstance(sParams).getOctets())); + } + else + { + throw e; + } + } + } + else + { + if (encAlg.equals(CMSEnvelopedDataGenerator.DES_EDE3_CBC) + || encAlg.equals(CMSEnvelopedDataGenerator.IDEA_CBC) + || encAlg.equals(CMSEnvelopedDataGenerator.CAST5_CBC)) + { + cipher.init(Cipher.DECRYPT_MODE, sKey, new IvParameterSpec(new byte[8])); + } + else + { + cipher.init(Cipher.DECRYPT_MODE, sKey); + } + } + + return cipher; + } + }); + } + + AlgorithmParameters createAlgorithmParameters(ASN1ObjectIdentifier algorithm) + throws NoSuchAlgorithmException, NoSuchProviderException + { + String algorithmName = (String)BASE_CIPHER_NAMES.get(algorithm); + + if (algorithmName != null) + { + try + { + // this is reversed as the Sun policy files now allow unlimited strength RSA + return helper.createAlgorithmParameters(algorithmName); + } + catch (NoSuchAlgorithmException e) + { + // Ignore + } + } + return helper.createAlgorithmParameters(algorithm.getId()); + } + + KeyFactory createKeyFactory(ASN1ObjectIdentifier algorithm) + throws CRMFException + { + try + { + String algName = (String)KEY_ALG_NAMES.get(algorithm); + + if (algName != null) + { + try + { + // this is reversed as the Sun policy files now allow unlimited strength RSA + return helper.createKeyFactory(algName); + } + catch (NoSuchAlgorithmException e) + { + // Ignore + } + } + return helper.createKeyFactory(algorithm.getId()); + } + catch (NoSuchProviderException e) + { + throw new CRMFException("cannot create cipher: " + e.getMessage(), e); + } + catch (NoSuchAlgorithmException e) + { + throw new CRMFException("cannot create cipher: " + e.getMessage(), e); + } + } + + MessageDigest createDigest(ASN1ObjectIdentifier algorithm) + throws CRMFException + { + try + { + String digestName = (String)DIGEST_ALG_NAMES.get(algorithm); + + if (digestName != null) + { + try + { + // this is reversed as the Sun policy files now allow unlimited strength RSA + return helper.createDigest(digestName); + } + catch (NoSuchAlgorithmException e) + { + // Ignore + } + } + return helper.createDigest(algorithm.getId()); + } + catch (NoSuchAlgorithmException e) + { + throw new CRMFException("cannot create cipher: " + e.getMessage(), e); + } + catch (NoSuchProviderException e) + { + throw new CRMFException("cannot create cipher: " + e.getMessage(), e); + } + } + + Mac createMac(ASN1ObjectIdentifier algorithm) + throws CRMFException + { + try + { + String macName = (String)MAC_ALG_NAMES.get(algorithm); + + if (macName != null) + { + try + { + // this is reversed as the Sun policy files now allow unlimited strength RSA + return helper.createMac(macName); + } + catch (NoSuchAlgorithmException e) + { + // Ignore + } + } + return helper.createMac(algorithm.getId()); + } + catch (NoSuchProviderException e) + { + throw new CRMFException("cannot create mac: " + e.getMessage(), e); + } + catch (NoSuchAlgorithmException e) + { + throw new CRMFException("cannot create mac: " + e.getMessage(), e); + } + } + + AlgorithmParameterGenerator createAlgorithmParameterGenerator(ASN1ObjectIdentifier algorithm) + throws GeneralSecurityException + { + String algorithmName = (String)BASE_CIPHER_NAMES.get(algorithm); + + try + { + if (algorithmName != null) + { + try + { + // this is reversed as the Sun policy files now allow unlimited strength RSA + return helper.createAlgorithmParameterGenerator(algorithmName); + } + catch (NoSuchAlgorithmException e) + { + // Ignore + } + } + return helper.createAlgorithmParameterGenerator(algorithm.getId()); + } + catch (NoSuchAlgorithmException e) + { + throw new GeneralSecurityException(e.toString()); + } + catch (NoSuchProviderException e) + { + throw new GeneralSecurityException(e.toString()); + } + } + + AlgorithmParameters generateParameters(ASN1ObjectIdentifier encryptionOID, SecretKey encKey, SecureRandom rand) + throws CRMFException + { + try + { + AlgorithmParameterGenerator pGen = createAlgorithmParameterGenerator(encryptionOID); + + if (encryptionOID.equals(CMSEnvelopedDataGenerator.RC2_CBC)) + { + byte[] iv = new byte[8]; + + rand.nextBytes(iv); + + try + { + pGen.init(new RC2ParameterSpec(encKey.getEncoded().length * 8, iv), rand); + } + catch (InvalidAlgorithmParameterException e) + { + throw new CRMFException("parameters generation error: " + e, e); + } + } + + return pGen.generateParameters(); + } + catch (GeneralSecurityException e) + { + throw new CRMFException("exception creating algorithm parameter generator: " + e, e); + } + } + + AlgorithmIdentifier getAlgorithmIdentifier(ASN1ObjectIdentifier encryptionOID, AlgorithmParameters params) + throws CRMFException + { + ASN1Encodable asn1Params; + if (params != null) + { + try + { + asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1")); + } + catch (IOException e) + { + throw new CRMFException("cannot encode parameters: " + e.getMessage(), e); + } + } + else + { + asn1Params = DERNull.INSTANCE; + } + + return new AlgorithmIdentifier( + encryptionOID, + asn1Params); + } + + static Object execute(JCECallback callback) throws CRMFException + { + try + { + return callback.doInJCE(); + } + catch (NoSuchAlgorithmException e) + { + throw new CRMFException("can't find algorithm.", e); + } + catch (InvalidKeyException e) + { + throw new CRMFException("key invalid in message.", e); + } + catch (NoSuchProviderException e) + { + throw new CRMFException("can't find provider.", e); + } + catch (NoSuchPaddingException e) + { + throw new CRMFException("required padding not supported.", e); + } + catch (InvalidAlgorithmParameterException e) + { + throw new CRMFException("algorithm parameters invalid.", e); + } + catch (InvalidParameterSpecException e) + { + throw new CRMFException("MAC algorithm parameter spec invalid.", e); + } + } + + static interface JCECallback + { + Object doInJCE() + throws CRMFException, InvalidAlgorithmParameterException, InvalidKeyException, InvalidParameterSpecException, + NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException; + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java new file mode 100644 index 00000000..5560fa78 --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java @@ -0,0 +1,121 @@ +package org.bouncycastle.cert.crmf.jcajce; + +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.ProviderException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.cert.crmf.CRMFException; +import org.bouncycastle.cert.crmf.ValueDecryptorGenerator; +import org.bouncycastle.jcajce.DefaultJcaJceHelper; +import org.bouncycastle.jcajce.NamedJcaJceHelper; +import org.bouncycastle.jcajce.ProviderJcaJceHelper; +import org.bouncycastle.operator.InputDecryptor; + +public class JceAsymmetricValueDecryptorGenerator + implements ValueDecryptorGenerator +{ + private PrivateKey recipientKey; + private CRMFHelper helper = new CRMFHelper(new DefaultJcaJceHelper()); + + public JceAsymmetricValueDecryptorGenerator(PrivateKey recipientKey) + { + this.recipientKey = recipientKey; + } + + public JceAsymmetricValueDecryptorGenerator setProvider(Provider provider) + { + this.helper = new CRMFHelper(new ProviderJcaJceHelper(provider)); + + return this; + } + + public JceAsymmetricValueDecryptorGenerator setProvider(String providerName) + { + this.helper = new CRMFHelper(new NamedJcaJceHelper(providerName)); + + return this; + } + + private Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey) + throws CRMFException + { + try + { + Key sKey = null; + + Cipher keyCipher = helper.createCipher(keyEncryptionAlgorithm.getAlgorithm()); + + try + { + keyCipher.init(Cipher.UNWRAP_MODE, recipientKey); + sKey = keyCipher.unwrap(encryptedContentEncryptionKey, contentEncryptionAlgorithm.getAlgorithm().getId(), Cipher.SECRET_KEY); + } + catch (NoSuchAlgorithmException e) + { + } + catch (IllegalStateException e) + { + } + catch (UnsupportedOperationException e) + { + } + catch (ProviderException e) + { + } + + // some providers do not support UNWRAP (this appears to be only for asymmetric algorithms) + if (sKey == null) + { + keyCipher.init(Cipher.DECRYPT_MODE, recipientKey); + sKey = new SecretKeySpec(keyCipher.doFinal(encryptedContentEncryptionKey), contentEncryptionAlgorithm.getAlgorithm().getId()); + } + + return sKey; + } + catch (InvalidKeyException e) + { + throw new CRMFException("key invalid in message.", e); + } + catch (IllegalBlockSizeException e) + { + throw new CRMFException("illegal blocksize in message.", e); + } + catch (BadPaddingException e) + { + throw new CRMFException("bad padding in message.", e); + } + } + + public InputDecryptor getValueDecryptor(AlgorithmIdentifier keyEncryptionAlgorithm, final AlgorithmIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey) + throws CRMFException + { + Key secretKey = extractSecretKey(keyEncryptionAlgorithm, contentEncryptionAlgorithm, encryptedContentEncryptionKey); + + final Cipher dataCipher = helper.createContentCipher(secretKey, contentEncryptionAlgorithm); + + return new InputDecryptor() + { + public AlgorithmIdentifier getAlgorithmIdentifier() + { + return contentEncryptionAlgorithm; + } + + public InputStream getInputStream(InputStream dataIn) + { + return new CipherInputStream(dataIn, dataCipher); + } + }; + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java new file mode 100644 index 00000000..e47fb146 --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java @@ -0,0 +1,140 @@ +package org.bouncycastle.cert.crmf.jcajce; + +import java.io.OutputStream; +import java.security.AlgorithmParameters; +import java.security.GeneralSecurityException; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.InvalidKeyException; + +import javax.crypto.Cipher; +import javax.crypto.CipherOutputStream; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.cert.crmf.CRMFException; +import org.bouncycastle.jcajce.DefaultJcaJceHelper; +import org.bouncycastle.jcajce.NamedJcaJceHelper; +import org.bouncycastle.jcajce.ProviderJcaJceHelper; +import org.bouncycastle.operator.GenericKey; +import org.bouncycastle.operator.OutputEncryptor; + +public class JceCRMFEncryptorBuilder +{ + private ASN1ObjectIdentifier encryptionOID; + private int keySize; + + private CRMFHelper helper = new CRMFHelper(new DefaultJcaJceHelper()); + private SecureRandom random; + + public JceCRMFEncryptorBuilder(ASN1ObjectIdentifier encryptionOID) + { + this(encryptionOID, -1); + } + + public JceCRMFEncryptorBuilder(ASN1ObjectIdentifier encryptionOID, int keySize) + { + this.encryptionOID = encryptionOID; + this.keySize = keySize; + } + + public JceCRMFEncryptorBuilder setProvider(Provider provider) + { + this.helper = new CRMFHelper(new ProviderJcaJceHelper(provider)); + + return this; + } + + public JceCRMFEncryptorBuilder setProvider(String providerName) + { + this.helper = new CRMFHelper(new NamedJcaJceHelper(providerName)); + + return this; + } + + public JceCRMFEncryptorBuilder setSecureRandom(SecureRandom random) + { + this.random = random; + + return this; + } + + public OutputEncryptor build() + throws CRMFException + { + return new CRMFOutputEncryptor(encryptionOID, keySize, random); + } + + private class CRMFOutputEncryptor + implements OutputEncryptor + { + private SecretKey encKey; + private AlgorithmIdentifier algorithmIdentifier; + private Cipher cipher; + + CRMFOutputEncryptor(ASN1ObjectIdentifier encryptionOID, int keySize, SecureRandom random) + throws CRMFException + { + KeyGenerator keyGen = helper.createKeyGenerator(encryptionOID); + + if (random == null) + { + random = new SecureRandom(); + } + + if (keySize < 0) + { + keyGen.init(random); + } + else + { + keyGen.init(keySize, random); + } + + cipher = helper.createCipher(encryptionOID); + encKey = keyGen.generateKey(); + AlgorithmParameters params = helper.generateParameters(encryptionOID, encKey, random); + + try + { + cipher.init(Cipher.ENCRYPT_MODE, encKey, params, random); + } + catch (InvalidKeyException e) + { + throw new CRMFException("unable to initialize cipher: " + e.getMessage(), e); + } + catch (GeneralSecurityException e) + { + throw new CRMFException("unable to initialize cipher: " + e.getMessage(), e); + } + + // + // If params are null we try and second guess on them as some providers don't provide + // algorithm parameter generation explicity but instead generate them under the hood. + // + if (params == null) + { + params = cipher.getParameters(); + } + + algorithmIdentifier = helper.getAlgorithmIdentifier(encryptionOID, params); + } + + public AlgorithmIdentifier getAlgorithmIdentifier() + { + return algorithmIdentifier; + } + + public OutputStream getOutputStream(OutputStream dOut) + { + return new CipherOutputStream(dOut, cipher); + } + + public GenericKey getKey() + { + return new GenericKey(encKey); + } + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java new file mode 100644 index 00000000..da9f15f4 --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java @@ -0,0 +1,70 @@ +package org.bouncycastle.cert.crmf.jcajce; + +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.Provider; +import java.security.InvalidKeyException; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.cert.crmf.CRMFException; +import org.bouncycastle.cert.crmf.PKMACValuesCalculator; +import org.bouncycastle.jcajce.DefaultJcaJceHelper; +import org.bouncycastle.jcajce.NamedJcaJceHelper; +import org.bouncycastle.jcajce.ProviderJcaJceHelper; + +public class JcePKMACValuesCalculator + implements PKMACValuesCalculator +{ + private MessageDigest digest; + private Mac mac; + private CRMFHelper helper; + + public JcePKMACValuesCalculator() + { + this.helper = new CRMFHelper(new DefaultJcaJceHelper()); + } + + public JcePKMACValuesCalculator setProvider(Provider provider) + { + this.helper = new CRMFHelper(new ProviderJcaJceHelper(provider)); + + return this; + } + + public JcePKMACValuesCalculator setProvider(String providerName) + { + this.helper = new CRMFHelper(new NamedJcaJceHelper(providerName)); + + return this; + } + + public void setup(AlgorithmIdentifier digAlg, AlgorithmIdentifier macAlg) + throws CRMFException + { + digest = helper.createDigest(digAlg.getAlgorithm()); + mac = helper.createMac(macAlg.getAlgorithm()); + } + + public byte[] calculateDigest(byte[] data) + { + return digest.digest(data); + } + + public byte[] calculateMac(byte[] pwd, byte[] data) + throws CRMFException + { + try + { + mac.init(new SecretKeySpec(pwd, mac.getAlgorithm())); + + return mac.doFinal(data); + } + catch (InvalidKeyException e) + { + throw new CRMFException("failure in setup: " + e.getMessage(), e); + } + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/jcajce/JcaCertStoreBuilder.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/jcajce/JcaCertStoreBuilder.java new file mode 100644 index 00000000..6462bf57 --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/jcajce/JcaCertStoreBuilder.java @@ -0,0 +1,149 @@ +package org.bouncycastle.cert.jcajce; + +import java.security.GeneralSecurityException; +import java.security.Provider; +import java.security.NoSuchProviderException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CRLException; +import java.security.cert.CertStore; +import java.security.cert.CertificateException; +import java.security.cert.CollectionCertStoreParameters; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.bouncycastle.cert.X509CRLHolder; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.util.Store; + +/** + * Builder to create a CertStore from certificate and CRL stores. + */ +public class JcaCertStoreBuilder +{ + private List certs = new ArrayList(); + private List crls = new ArrayList(); + private Object provider; + private JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter(); + private JcaX509CRLConverter crlConverter = new JcaX509CRLConverter(); + + /** + * Add a store full of X509CertificateHolder objects. + * + * @param certStore a store of X509CertificateHolder objects. + */ + public JcaCertStoreBuilder addCertificates(Store certStore) + { + certs.addAll(certStore.getMatches(null)); + + return this; + } + + /** + * Add a single certificate. + * + * @param cert the X509 certificate holder containing the certificate. + */ + public JcaCertStoreBuilder addCertificate(X509CertificateHolder cert) + { + certs.add(cert); + + return this; + } + + /** + * Add a store full of X509CRLHolder objects. + * @param crlStore a store of X509CRLHolder objects. + */ + public JcaCertStoreBuilder addCRLs(Store crlStore) + { + crls.addAll(crlStore.getMatches(null)); + + return this; + } + + /** + * Add a single CRL. + * + * @param crl the X509 CRL holder containing the CRL. + */ + public JcaCertStoreBuilder addCRL(X509CRLHolder crl) + { + crls.add(crl); + + return this; + } + + public JcaCertStoreBuilder setProvider(String providerName) + throws GeneralSecurityException + { + certificateConverter.setProvider(providerName); + crlConverter.setProvider(providerName); + this.provider = providerName; + + return this; + } + + public JcaCertStoreBuilder setProvider(Provider provider) + throws GeneralSecurityException + { + certificateConverter.setProvider(provider); + crlConverter.setProvider(provider); + this.provider = provider; + + return this; + } + + /** + * Build the CertStore from the current inputs. + * + * @return a CertStore. + * @throws GeneralSecurityException + */ + public CertStore build() + throws GeneralSecurityException + { + CollectionCertStoreParameters params = convertHolders(certificateConverter, crlConverter); + + try +{ + if (provider instanceof String) + { + return CertStore.getInstance("Collection", params, (String)provider); + } + + if (provider instanceof Provider) + { + return CertStore.getInstance("Collection", params, (Provider)provider); + } + + return CertStore.getInstance("Collection", params); +} +catch (NoSuchAlgorithmException e) +{ + throw new GeneralSecurityException(e.toString()); +} +catch (NoSuchProviderException e) +{ + throw new GeneralSecurityException(e.toString()); +} + } + + private CollectionCertStoreParameters convertHolders(JcaX509CertificateConverter certificateConverter, JcaX509CRLConverter crlConverter) + throws CertificateException, CRLException + { + List jcaObjs = new ArrayList(certs.size() + crls.size()); + + for (Iterator it = certs.iterator(); it.hasNext();) + { + jcaObjs.add(certificateConverter.getCertificate((X509CertificateHolder)it.next())); + } + + for (Iterator it = crls.iterator(); it.hasNext();) + { + jcaObjs.add(crlConverter.getCRL((X509CRLHolder)it.next())); + } + + return new CollectionCertStoreParameters(jcaObjs); + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/selector/jcajce/JcaSelectorConverter.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/selector/jcajce/JcaSelectorConverter.java new file mode 100644 index 00000000..3570053c --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/selector/jcajce/JcaSelectorConverter.java @@ -0,0 +1,34 @@ +package org.bouncycastle.cert.selector.jcajce; + +import java.security.cert.X509CertSelector; + +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.cert.selector.X509CertificateHolderSelector; + +public class JcaSelectorConverter +{ + public JcaSelectorConverter() + { + + } + + public X509CertificateHolderSelector getCertificateHolderSelector(X509CertSelector certSelector) + { +try +{ + if (certSelector.getSubjectKeyIdentifier() != null) + { + return new X509CertificateHolderSelector(X500Name.getInstance(certSelector.getIssuerAsBytes()), certSelector.getSerialNumber(), ASN1OctetString.getInstance(certSelector.getSubjectKeyIdentifier()).getOctets()); + } + else + { + return new X509CertificateHolderSelector(X500Name.getInstance(certSelector.getIssuerAsBytes()), certSelector.getSerialNumber()); + } +} +catch (Exception e) +{ +throw new IllegalArgumentException("conversion failed: " + e.toString()); +} + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cert/selector/jcajce/JcaX509CertSelectorConverter.java b/pkix/src/main/jdk1.1/org/bouncycastle/cert/selector/jcajce/JcaX509CertSelectorConverter.java new file mode 100644 index 00000000..22a35371 --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/cert/selector/jcajce/JcaX509CertSelectorConverter.java @@ -0,0 +1,57 @@ +package org.bouncycastle.cert.selector.jcajce; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.X509CertSelector; + +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.cert.selector.X509CertificateHolderSelector; + +public class JcaX509CertSelectorConverter +{ + public JcaX509CertSelectorConverter() + { + } + + protected X509CertSelector doConversion(X500Name issuer, BigInteger serialNumber, byte[] subjectKeyIdentifier) + { + X509CertSelector selector = new X509CertSelector(); + + if (issuer != null) + { + try + { + selector.setIssuer(issuer.getEncoded()); + } + catch (IOException e) + { + throw new IllegalArgumentException("unable to convert issuer: " + e.getMessage()); + } + } + + if (serialNumber != null) + { + selector.setSerialNumber(serialNumber); + } + + if (subjectKeyIdentifier != null) + { + try + { + selector.setSubjectKeyIdentifier(new DEROctetString(subjectKeyIdentifier).getEncoded()); + } + catch (IOException e) + { + throw new IllegalArgumentException("unable to convert issuer: " + e.getMessage()); + } + } + + return selector; + } + + public X509CertSelector getCertSelector(X509CertificateHolderSelector holderSelector) + { + return doConversion(holderSelector.getIssuer(), holderSelector.getSerialNumber(), holderSelector.getSubjectKeyIdentifier()); + } +} |