diff options
author | Sergio Giro <sgiro@google.com> | 2016-02-04 23:52:52 +0000 |
---|---|---|
committer | Sergio Giro <sgiro@google.com> | 2016-02-10 22:41:50 +0000 |
commit | 79d3bf2425a53baab7feb744dad710b6c15533c9 (patch) | |
tree | 2cba8cee6020669038b6603397dbc80dd73aa9ce | |
parent | 013d8784e65adfe3af81f7ff010eddc17c0c332e (diff) | |
download | bouncycastle-79d3bf2425a53baab7feb744dad710b6c15533c9.tar.gz |
bouncycastle: upgrade to version 1.54
Merge remote-tracking branch 'aosp/upstream-master'
(cherry picked from commit 4a2d5c40ffefaaa02c656a091f33fecdf8592607)
Change-Id: Icd734732677bc8ed04d8cd78bbb686efa152ed58
265 files changed, 11358 insertions, 2972 deletions
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java index c465c834..e6b0d7ec 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java @@ -279,7 +279,7 @@ public class X509AttributeCertificateHolder */ public byte[] getSignature() { - return attrCert.getSignatureValue().getBytes(); + return attrCert.getSignatureValue().getOctets(); } /** @@ -340,7 +340,7 @@ public class X509AttributeCertificateHolder throw new CertException("unable to process signature: " + e.getMessage(), e); } - return verifier.verify(attrCert.getSignatureValue().getBytes()); + return verifier.verify(this.getSignature()); } public boolean equals( diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java index 29c48fa6..4b773e2e 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java @@ -291,7 +291,7 @@ public class X509CRLHolder throw new CertException("unable to process signature: " + e.getMessage(), e); } - return verifier.verify(x509CRL.getSignature().getBytes()); + return verifier.verify(x509CRL.getSignature().getOctets()); } public boolean equals( diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java index dc61c78f..b5ad578d 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java @@ -240,7 +240,7 @@ public class X509CertificateHolder */ public byte[] getSignature() { - return x509Certificate.getSignature().getBytes(); + return x509Certificate.getSignature().getOctets(); } /** @@ -289,7 +289,7 @@ public class X509CertificateHolder throw new CertException("unable to process signature: " + e.getMessage(), e); } - return verifier.verify(x509Certificate.getSignature().getBytes()); + return verifier.verify(this.getSignature()); } public boolean equals( diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAttributeTableGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAttributeTableGenerator.java index 528c738b..a38752c1 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAttributeTableGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAttributeTableGenerator.java @@ -1,18 +1,20 @@ package org.bouncycastle.cms; -import org.bouncycastle.asn1.cms.AttributeTable; - import java.util.Map; +import org.bouncycastle.asn1.cms.AttributeTable; + /** * Note: The SIGNATURE parameter is only available when generating unsigned attributes. */ public interface CMSAttributeTableGenerator { - static final String CONTENT_TYPE = "contentType"; - static final String DIGEST = "digest"; - static final String SIGNATURE = "encryptedDigest"; - static final String DIGEST_ALGORITHM_IDENTIFIER = "digestAlgID"; + String CONTENT_TYPE = "contentType"; + String DIGEST = "digest"; + String SIGNATURE = "encryptedDigest"; + String DIGEST_ALGORITHM_IDENTIFIER = "digestAlgID"; + String MAC_ALGORITHM_IDENTIFIER = "macAlgID"; + String SIGNATURE_ALGORITHM_IDENTIFIER = "signatureAlgID"; AttributeTable getAttributes(Map parameters) throws CMSAttributeTableGenerationException; diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java index 5ef95ee3..7f6d4a2c 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java @@ -5,10 +5,15 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; +import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; @@ -20,9 +25,8 @@ import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.cms.SignedData; import org.bouncycastle.asn1.cms.SignerInfo; -import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.SignatureAlgorithmIdentifierFinder; import org.bouncycastle.util.Encodable; import org.bouncycastle.util.Store; @@ -184,11 +188,18 @@ public class CMSSignedData // this can happen if the signed message is sent simply to send a // certificate chain. // - if (signedData.getEncapContentInfo().getContent() != null) + ASN1Encodable content = signedData.getEncapContentInfo().getContent(); + if (content != null) { - this.signedContent = new CMSProcessableByteArray(signedData.getEncapContentInfo().getContentType(), - ((ASN1OctetString)(signedData.getEncapContentInfo() - .getContent())).getOctets()); + if (content instanceof ASN1OctetString) + { + this.signedContent = new CMSProcessableByteArray(signedData.getEncapContentInfo().getContentType(), + ((ASN1OctetString)content).getOctets()); + } + else + { + this.signedContent = new PKCS7ProcessableObject(signedData.getEncapContentInfo().getContentType(), content); + } } else { @@ -231,7 +242,6 @@ public class CMSSignedData { ASN1Set s = signedData.getSignerInfos(); List signerInfos = new ArrayList(); - SignatureAlgorithmIdentifierFinder sigAlgFinder = new DefaultSignatureAlgorithmIdentifierFinder(); for (int i = 0; i != s.size(); i++) { @@ -258,6 +268,26 @@ public class CMSSignedData } /** + * Return if this is object represents a detached signature. + * + * @return true if this message represents a detached signature, false otherwise. + */ + public boolean isDetachedSignature() + { + return signedData.getEncapContentInfo().getContent() == null && signedData.getSignerInfos().size() > 0; + } + + /** + * Return if this is object represents a certificate management message. + * + * @return true if the message has no signers or content, false otherwise. + */ + public boolean isCertificateManagementMessage() + { + return signedData.getEncapContentInfo().getContent() == null && signedData.getSignerInfos().size() == 0; + } + + /** * Return any X.509 certificate objects in this SignedData structure as a Store of X509CertificateHolder objects. * * @return a Store of X509CertificateHolder objects. @@ -303,6 +333,23 @@ public class CMSSignedData // END android-removed /** + * Return the digest algorithm identifiers for the SignedData object + * + * @return the set of digest algorithm identifiers + */ + public Set<AlgorithmIdentifier> getDigestAlgorithmIDs() + { + Set<AlgorithmIdentifier> digests = new HashSet<AlgorithmIdentifier>(signedData.getDigestAlgorithms().size()); + + for (Enumeration en = signedData.getDigestAlgorithms().getObjects(); en.hasMoreElements();) + { + digests.add(AlgorithmIdentifier.getInstance(en.nextElement())); + } + + return Collections.unmodifiableSet(digests); + } + + /** * Return the a string representation of the OID associated with the * encapsulated content info structure carried in the signed data. * diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java index e5f7e9b3..7dd16e03 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java @@ -5,8 +5,10 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; @@ -16,6 +18,7 @@ import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.BEROctetStringGenerator; import org.bouncycastle.asn1.BERSet; +import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; @@ -24,7 +27,10 @@ import org.bouncycastle.asn1.cms.ContentInfo; // import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat; // import org.bouncycastle.asn1.ocsp.OCSPResponse; // import org.bouncycastle.asn1.ocsp.OCSPResponseStatus; +// import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +// import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; // END android-removed +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.bouncycastle.cert.X509CRLHolder; import org.bouncycastle.cert.X509CertificateHolder; @@ -37,6 +43,49 @@ import org.bouncycastle.util.io.TeeOutputStream; class CMSUtils { + private static final Set<String> des = new HashSet<String>(); + + static + { + des.add("DES"); + des.add("DESEDE"); + // BEGIN android-removed + // des.add(OIWObjectIdentifiers.desCBC.getId()); + // des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId()); + // des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId()); + // des.add(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId()); + // END android-removed + } + + static boolean isDES(String algorithmID) + { + String name = Strings.toUpperCase(algorithmID); + + return des.contains(name); + } + + static boolean isEquivalent(AlgorithmIdentifier algId1, AlgorithmIdentifier algId2) + { + if (algId1 == null || algId2 == null) + { + return false; + } + + if (!algId1.getAlgorithm().equals(algId2.getAlgorithm())) + { + return false; + } + + ASN1Encodable params1 = algId1.getParameters(); + ASN1Encodable params2 = algId2.getParameters(); + if (params1 != null) + { + return params1.equals(params2) || (params1.equals(DERNull.INSTANCE) && params2 == null); + } + + return params2 == null || params2.equals(DERNull.INSTANCE); + } + static ContentInfo readContentInfo( byte[] input) throws CMSException @@ -229,63 +278,6 @@ class CMSUtils } } - static byte[] getPasswordBytes(int scheme, char[] password) - { - if (scheme == PasswordRecipient.PKCS5_SCHEME2) - { - return PKCS5PasswordToBytes(password); - } - - return PKCS5PasswordToUTF8Bytes(password); - } - - /** - * converts a password to a byte array according to the scheme in - * PKCS5 (ascii, no padding) - * - * @param password a character array representing the password. - * @return a byte array representing the password. - */ - private static byte[] PKCS5PasswordToBytes( - char[] password) - { - if (password != null) - { - byte[] bytes = new byte[password.length]; - - for (int i = 0; i != bytes.length; i++) - { - bytes[i] = (byte)password[i]; - } - - return bytes; - } - else - { - return new byte[0]; - } - } - - /** - * converts a password to a byte array according to the scheme in - * PKCS5 (UTF-8, no padding) - * - * @param password a character array representing the password. - * @return a byte array representing the password. - */ - private static byte[] PKCS5PasswordToUTF8Bytes( - char[] password) - { - if (password != null) - { - return Strings.toUTF8ByteArray(password); - } - else - { - return new byte[0]; - } - } - public static byte[] streamToByteArray( InputStream in) throws IOException diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java index d454fa6c..2230c780 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java @@ -173,6 +173,13 @@ public class DefaultCMSSignatureAlgorithmNameGenerator public String getSignatureName(AlgorithmIdentifier digestAlg, AlgorithmIdentifier encryptionAlg) { + String digestName = getDigestAlgName(encryptionAlg.getAlgorithm()); + + if (!digestName.equals(encryptionAlg.getAlgorithm().getId())) + { + return digestName + "with" + getEncryptionAlgName(encryptionAlg.getAlgorithm()); + } + return getDigestAlgName(digestAlg.getAlgorithm()) + "with" + getEncryptionAlgName(encryptionAlg.getAlgorithm()); } } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java index 837edd85..ddfd2ebd 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java @@ -10,8 +10,10 @@ import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.Attribute; import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.CMSAlgorithmProtection; import org.bouncycastle.asn1.cms.CMSAttributes; import org.bouncycastle.asn1.cms.Time; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; /** * Default signed attributes generator. @@ -93,6 +95,14 @@ public class DefaultSignedAttributeTableGenerator std.put(attr.getAttrType(), attr); } + if (!std.contains(CMSAttributes.cmsAlgorithmProtect)) + { + Attribute attr = new Attribute(CMSAttributes.cmsAlgorithmProtect, new DERSet(new CMSAlgorithmProtection( + (AlgorithmIdentifier)parameters.get(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER), + CMSAlgorithmProtection.SIGNATURE, (AlgorithmIdentifier)parameters.get(CMSAttributeTableGenerator.SIGNATURE_ALGORITHM_IDENTIFIER)))); + std.put(attr.getAttrType(), attr); + } + return std; } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PKCS7ProcessableObject.java b/bcpkix/src/main/java/org/bouncycastle/cms/PKCS7ProcessableObject.java new file mode 100644 index 00000000..077b2dc6 --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/cms/PKCS7ProcessableObject.java @@ -0,0 +1,65 @@ +package org.bouncycastle.cms; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Sequence; + +public class PKCS7ProcessableObject + implements CMSTypedData +{ + private final ASN1ObjectIdentifier type; + private final ASN1Encodable structure; + + public PKCS7ProcessableObject( + ASN1ObjectIdentifier type, + ASN1Encodable structure) + { + this.type = type; + this.structure = structure; + } + + public ASN1ObjectIdentifier getContentType() + { + return type; + } + + public void write(OutputStream cOut) + throws IOException, CMSException + { + if (structure instanceof ASN1Sequence) + { + ASN1Sequence s = ASN1Sequence.getInstance(structure); + + for (Iterator it = s.iterator(); it.hasNext();) + { + ASN1Encodable enc = (ASN1Encodable)it.next(); + + cOut.write(enc.toASN1Primitive().getEncoded(ASN1Encoding.DER)); + } + } + else + { + byte[] encoded = structure.toASN1Primitive().getEncoded(ASN1Encoding.DER); + int index = 1; + + while ((encoded[index] & 0xff) > 127) + { + index++; + } + + index++; + + cOut.write(encoded, index, encoded.length - index); + } + } + + public Object getContent() + { + return structure; + } +} diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java index c81c3028..7322fdcc 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java @@ -8,7 +8,7 @@ public interface PasswordRecipient public static final int PKCS5_SCHEME2 = 0; public static final int PKCS5_SCHEME2_UTF8 = 1; - byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + byte[] calculateDerivedKey(int schemeID, AlgorithmIdentifier derivationAlgorithm, int keySize) throws CMSException; RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, byte[] derivedKey, byte[] encryptedEncryptedContentKey) diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java index f264729c..e1b0ce1f 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java @@ -183,13 +183,15 @@ public class SignerInfoGenerator */ ASN1Set signedAttr = null; + AlgorithmIdentifier digestEncryptionAlgorithm = sigEncAlgFinder.findEncryptionAlgorithm(signer.getAlgorithmIdentifier()); + AlgorithmIdentifier digestAlg = null; if (sAttrGen != null) { digestAlg = digester.getAlgorithmIdentifier(); calculatedDigest = digester.getDigest(); - Map parameters = getBaseParameters(contentType, digester.getAlgorithmIdentifier(), calculatedDigest); + Map parameters = getBaseParameters(contentType, digester.getAlgorithmIdentifier(), digestEncryptionAlgorithm, calculatedDigest); AttributeTable signed = sAttrGen.getAttributes(Collections.unmodifiableMap(parameters)); signedAttr = getAttributeSet(signed); @@ -220,7 +222,7 @@ public class SignerInfoGenerator ASN1Set unsignedAttr = null; if (unsAttrGen != null) { - Map parameters = getBaseParameters(contentType, digestAlg, calculatedDigest); + Map parameters = getBaseParameters(contentType, digestAlg, digestEncryptionAlgorithm, calculatedDigest); parameters.put(CMSAttributeTableGenerator.SIGNATURE, Arrays.clone(sigBytes)); AttributeTable unsigned = unsAttrGen.getAttributes(Collections.unmodifiableMap(parameters)); @@ -228,8 +230,6 @@ public class SignerInfoGenerator unsignedAttr = getAttributeSet(unsigned); } - AlgorithmIdentifier digestEncryptionAlgorithm = sigEncAlgFinder.findEncryptionAlgorithm(signer.getAlgorithmIdentifier()); - return new SignerInfo(signerIdentifier, digestAlg, signedAttr, digestEncryptionAlgorithm, new DEROctetString(sigBytes), unsignedAttr); } @@ -255,7 +255,7 @@ public class SignerInfoGenerator return null; } - private Map getBaseParameters(ASN1ObjectIdentifier contentType, AlgorithmIdentifier digAlgId, byte[] hash) + private Map getBaseParameters(ASN1ObjectIdentifier contentType, AlgorithmIdentifier digAlgId, AlgorithmIdentifier sigAlgId, byte[] hash) { Map param = new HashMap(); @@ -265,7 +265,9 @@ public class SignerInfoGenerator } param.put(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER, digAlgId); + param.put(CMSAttributeTableGenerator.SIGNATURE_ALGORITHM_IDENTIFIER, sigAlgId); param.put(CMSAttributeTableGenerator.DIGEST, Arrays.clone(hash)); + return param; } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java index 081d1218..ac6dd0f9 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java @@ -18,6 +18,7 @@ import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.cms.Attribute; import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.CMSAlgorithmProtection; import org.bouncycastle.asn1.cms.CMSAttributes; import org.bouncycastle.asn1.cms.IssuerAndSerialNumber; import org.bouncycastle.asn1.cms.SignerIdentifier; @@ -38,21 +39,22 @@ import org.bouncycastle.util.io.TeeOutputStream; */ public class SignerInformation { - private SignerId sid; - private SignerInfo info; - private AlgorithmIdentifier digestAlgorithm; - private AlgorithmIdentifier encryptionAlgorithm; - private final ASN1Set signedAttributeSet; - private final ASN1Set unsignedAttributeSet; - private CMSProcessable content; - private byte[] signature; - private ASN1ObjectIdentifier contentType; - private byte[] resultDigest; + private final SignerId sid; + private final CMSProcessable content; + private final byte[] signature; + private final ASN1ObjectIdentifier contentType; + private final boolean isCounterSignature; // Derived - private AttributeTable signedAttributeValues; - private AttributeTable unsignedAttributeValues; - private boolean isCounterSignature; + private AttributeTable signedAttributeValues; + private AttributeTable unsignedAttributeValues; + private byte[] resultDigest; + + protected final SignerInfo info; + protected final AlgorithmIdentifier digestAlgorithm; + protected final AlgorithmIdentifier encryptionAlgorithm; + protected final ASN1Set signedAttributeSet; + protected final ASN1Set unsignedAttributeSet; SignerInformation( SignerInfo info, @@ -89,6 +91,28 @@ public class SignerInformation this.resultDigest = resultDigest; } + /** + * Protected constructor. In some cases clients have their own idea about how to encode + * the signed attributes and calculate the signature. This constructor is to allow developers + * to deal with that by extending off the class and overridng methods like getSignedAttributes(). + * + * @param baseInfo the SignerInformation to base this one on. + */ + protected SignerInformation(SignerInformation baseInfo) + { + this.info = baseInfo.info; + this.contentType = baseInfo.contentType; + this.isCounterSignature = baseInfo.isCounterSignature(); + this.sid = baseInfo.getSID(); + this.digestAlgorithm = info.getDigestAlgorithm(); + this.signedAttributeSet = info.getAuthenticatedAttributes(); + this.unsignedAttributeSet = info.getUnauthenticatedAttributes(); + this.encryptionAlgorithm = info.getDigestEncryptionAlgorithm(); + this.signature = info.getEncryptedDigest().getOctets(); + this.content = baseInfo.content; + this.resultDigest = baseInfo.resultDigest; + } + public boolean isCounterSignature() { return isCounterSignature; @@ -428,6 +452,46 @@ public class SignerInformation } } + AttributeTable signedAttrTable = this.getSignedAttributes(); + + // RFC 6211 Validate Algorithm Identifier protection attribute if present + { + AttributeTable unsignedAttrTable = this.getUnsignedAttributes(); + if (unsignedAttrTable != null && unsignedAttrTable.getAll(CMSAttributes.cmsAlgorithmProtect).size() > 0) + { + throw new CMSException("A cmsAlgorithmProtect attribute MUST be a signed attribute"); + } + if (signedAttrTable != null) + { + ASN1EncodableVector protectionAttributes = signedAttrTable.getAll(CMSAttributes.cmsAlgorithmProtect); + if (protectionAttributes.size() > 1) + { + throw new CMSException("Only one instance of a cmsAlgorithmProtect attribute can be present"); + } + + if (protectionAttributes.size() > 0) + { + Attribute attr = Attribute.getInstance(protectionAttributes.get(0)); + if (attr.getAttrValues().size() != 1) + { + throw new CMSException("A cmsAlgorithmProtect attribute MUST contain exactly one value"); + } + + CMSAlgorithmProtection algorithmProtection = CMSAlgorithmProtection.getInstance(attr.getAttributeValues()[0]); + + if (!CMSUtils.isEquivalent(algorithmProtection.getDigestAlgorithm(), info.getDigestAlgorithm())) + { + throw new CMSException("CMS Algorithm Identifier Protection check failed for digestAlgorithm"); + } + + if (!CMSUtils.isEquivalent(algorithmProtection.getSignatureAlgorithm(), info.getDigestEncryptionAlgorithm())) + { + throw new CMSException("CMS Algorithm Identifier Protection check failed for signatureAlgorithm"); + } + } + } + } + // RFC 3852 11.2 Check the message-digest attribute is correct { ASN1Primitive validMessageDigest = getSingleValuedSignedAttribute( @@ -457,7 +521,6 @@ public class SignerInformation // RFC 3852 11.4 Validate countersignature attribute(s) { - AttributeTable signedAttrTable = this.getSignedAttributes(); if (signedAttrTable != null && signedAttrTable.getAll(CMSAttributes.counterSignature).size() > 0) { @@ -470,7 +533,7 @@ public class SignerInformation ASN1EncodableVector csAttrs = unsignedAttrTable.getAll(CMSAttributes.counterSignature); for (int i = 0; i < csAttrs.size(); ++i) { - Attribute csAttr = (Attribute)csAttrs.get(i); + Attribute csAttr = Attribute.getInstance(csAttrs.get(i)); if (csAttr.getAttrValues().size() < 1) { throw new CMSException("A countersignature attribute MUST contain at least one AttributeValue"); diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/CertificateTrustBlock.java b/bcpkix/src/main/java/org/bouncycastle/openssl/CertificateTrustBlock.java new file mode 100644 index 00000000..9a76084b --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/openssl/CertificateTrustBlock.java @@ -0,0 +1,132 @@ +package org.bouncycastle.openssl; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.DERUTF8String; + +public class CertificateTrustBlock +{ + private ASN1Sequence uses; + private ASN1Sequence prohibitions; + private String alias; + + public CertificateTrustBlock(Set<ASN1ObjectIdentifier> uses) + { + this(null, uses, null); + } + + public CertificateTrustBlock(String alias, Set<ASN1ObjectIdentifier> uses) + { + this(alias, uses, null); + } + + public CertificateTrustBlock(String alias, Set<ASN1ObjectIdentifier> uses, Set<ASN1ObjectIdentifier> prohibitions) + { + this.alias = alias; + this.uses = toSequence(uses); + this.prohibitions = toSequence(prohibitions); + } + + CertificateTrustBlock(byte[] encoded) + { + ASN1Sequence seq = ASN1Sequence.getInstance(encoded); + + for (Enumeration en = seq.getObjects(); en.hasMoreElements();) + { + ASN1Encodable obj = (ASN1Encodable)en.nextElement(); + + if (obj instanceof ASN1Sequence) + { + this.uses = ASN1Sequence.getInstance(obj); + } + else if (obj instanceof ASN1TaggedObject) + { + this.prohibitions = ASN1Sequence.getInstance((ASN1TaggedObject)obj, false); + } + else if (obj instanceof DERUTF8String) + { + this.alias = DERUTF8String.getInstance(obj).getString(); + } + } + } + + public String getAlias() + { + return alias; + } + + public Set<ASN1ObjectIdentifier> getUses() + { + return toSet(uses); + } + + public Set<ASN1ObjectIdentifier> getProhibitions() + { + return toSet(prohibitions); + } + + private Set<ASN1ObjectIdentifier> toSet(ASN1Sequence seq) + { + if (seq != null) + { + Set<ASN1ObjectIdentifier> oids = new HashSet<ASN1ObjectIdentifier>(seq.size()); + + for (Enumeration en = seq.getObjects(); en.hasMoreElements(); ) + { + oids.add(ASN1ObjectIdentifier.getInstance(en.nextElement())); + } + + return oids; + } + + return Collections.EMPTY_SET; + } + + private ASN1Sequence toSequence(Set<ASN1ObjectIdentifier> oids) + { + if (oids == null || oids.isEmpty()) + { + return null; + } + + ASN1EncodableVector v = new ASN1EncodableVector(); + + for (Iterator it = oids.iterator(); it.hasNext();) + { + v.add((ASN1Encodable)it.next()); + } + + return new DERSequence(v); + } + + ASN1Sequence toASN1Sequence() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + if (uses != null) + { + v.add(uses); + } + if (prohibitions != null) + { + v.add(new DERTaggedObject(false, 0, prohibitions)); + } + if (alias != null) + { + v.add(new DERUTF8String(alias)); + } + + return new DERSequence(v); + } +} diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java index 293370f8..dc2c431b 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java @@ -72,6 +72,20 @@ public class DefaultDigestAlgorithmIdentifierFinder digestNameToOids.put("SHA-512", NISTObjectIdentifiers.id_sha512); // BEGIN android-removed + // digestNameToOids.put("SHA1", OIWObjectIdentifiers.idSHA1); + // digestNameToOids.put("SHA224", NISTObjectIdentifiers.id_sha224); + // digestNameToOids.put("SHA256", NISTObjectIdentifiers.id_sha256); + // digestNameToOids.put("SHA384", NISTObjectIdentifiers.id_sha384); + // digestNameToOids.put("SHA512", NISTObjectIdentifiers.id_sha512); + + // digestNameToOids.put("SHA3-224", NISTObjectIdentifiers.id_sha3_224); + // digestNameToOids.put("SHA3-256", NISTObjectIdentifiers.id_sha3_256); + // digestNameToOids.put("SHA3-384", NISTObjectIdentifiers.id_sha3_384); + // digestNameToOids.put("SHA3-512", NISTObjectIdentifiers.id_sha3_512); + // + // digestNameToOids.put("SHAKE-128", NISTObjectIdentifiers.id_shake128); + // digestNameToOids.put("SHAKE-256", NISTObjectIdentifiers.id_shake256); + // // digestNameToOids.put("GOST3411", CryptoProObjectIdentifiers.gostR3411); // // digestNameToOids.put("MD2", PKCSObjectIdentifiers.md2); @@ -106,4 +120,4 @@ public class DefaultDigestAlgorithmIdentifierFinder { return new AlgorithmIdentifier((ASN1ObjectIdentifier)digestNameToOids.get(digAlgName), DERNull.INSTANCE); } -}
\ No newline at end of file +} diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java index a0847fb1..19d46ec9 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java @@ -40,9 +40,11 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.jcajce.util.AlgorithmParametersUtils; import org.bouncycastle.jcajce.util.JcaJceHelper; -import org.bouncycastle.jcajce.util.JcaJceUtils; +import org.bouncycastle.jcajce.util.MessageDigestUtils; import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.util.Integers; class OperatorHelper { @@ -50,6 +52,7 @@ class OperatorHelper private static final Map asymmetricWrapperAlgNames = new HashMap(); private static final Map symmetricWrapperAlgNames = new HashMap(); private static final Map symmetricKeyAlgNames = new HashMap(); + private static final Map symmetricWrapperKeySizes = new HashMap(); static { @@ -114,6 +117,16 @@ class OperatorHelper symmetricWrapperAlgNames.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap, "SEEDWrap"); symmetricWrapperAlgNames.put(PKCSObjectIdentifiers.des_EDE3_CBC, "DESede"); + symmetricWrapperKeySizes.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap, Integers.valueOf(192)); + symmetricWrapperKeySizes.put(NISTObjectIdentifiers.id_aes128_wrap, Integers.valueOf(128)); + symmetricWrapperKeySizes.put(NISTObjectIdentifiers.id_aes192_wrap, Integers.valueOf(192)); + symmetricWrapperKeySizes.put(NISTObjectIdentifiers.id_aes256_wrap, Integers.valueOf(256)); + symmetricWrapperKeySizes.put(NTTObjectIdentifiers.id_camellia128_wrap, Integers.valueOf(128)); + symmetricWrapperKeySizes.put(NTTObjectIdentifiers.id_camellia192_wrap, Integers.valueOf(192)); + symmetricWrapperKeySizes.put(NTTObjectIdentifiers.id_camellia256_wrap, Integers.valueOf(256)); + symmetricWrapperKeySizes.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap, Integers.valueOf(128)); + symmetricWrapperKeySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC, Integers.valueOf(192)); + symmetricKeyAlgNames.put(NISTObjectIdentifiers.aes, "AES"); symmetricKeyAlgNames.put(NISTObjectIdentifiers.id_aes128_CBC, "AES"); symmetricKeyAlgNames.put(NISTObjectIdentifiers.id_aes192_CBC, "AES"); @@ -129,6 +142,16 @@ class OperatorHelper this.helper = helper; } + String getWrappingAlgorithmName(ASN1ObjectIdentifier algOid) + { + return (String)symmetricWrapperAlgNames.get(algOid); + } + + int getKeySizeInBits(ASN1ObjectIdentifier algOid) + { + return ((Integer)symmetricWrapperKeySizes.get(algOid)).intValue(); + } + Cipher createAsymmetricWrapper(ASN1ObjectIdentifier algorithm, Map extraAlgNames) throws OperatorCreationException { @@ -248,7 +271,7 @@ class OperatorHelper try { - dig = helper.createDigest(JcaJceUtils.getDigestAlgName(digAlgId.getAlgorithm())); + dig = helper.createDigest(MessageDigestUtils.getDigestName(digAlgId.getAlgorithm())); } catch (NoSuchAlgorithmException e) { @@ -318,7 +341,7 @@ class OperatorHelper { AlgorithmParameters params = helper.createAlgorithmParameters(algName); - JcaJceUtils.loadParameters(params, algorithm.getParameters()); + AlgorithmParametersUtils.loadParameters(params, algorithm.getParameters()); PSSParameterSpec spec = (PSSParameterSpec)params.getParameterSpec(PSSParameterSpec.class); sig.setParameter(spec); @@ -342,7 +365,7 @@ class OperatorHelper if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) { RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params); - return JcaJceUtils.getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "WITHRSAANDMGF1"; + return getDigestName(rsaParams.getHashAlgorithm().getAlgorithm()) + "WITHRSAANDMGF1"; } } @@ -354,6 +377,20 @@ class OperatorHelper return sigAlgId.getAlgorithm().getId(); } + // we need to remove the - to create a correct signature name + private static String getDigestName(ASN1ObjectIdentifier oid) + { + String name = MessageDigestUtils.getDigestName(oid); + + int dIndex = name.indexOf('-'); + if (dIndex > 0) + { + return name.substring(0, dIndex) + name.substring(dIndex + 1); + } + + return MessageDigestUtils.getDigestName(oid); + } + public X509Certificate convertCertificate(X509CertificateHolder certHolder) throws CertificateException { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java new file mode 100644 index 00000000..fca4e01a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java @@ -0,0 +1,226 @@ +package org.bouncycastle.asn1; + +import java.io.IOException; + +import org.bouncycastle.util.Arrays; + +/** + * Base class for an application specific object + */ +public abstract class ASN1ApplicationSpecific + extends ASN1Primitive +{ + protected final boolean isConstructed; + protected final int tag; + protected final byte[] octets; + + ASN1ApplicationSpecific( + boolean isConstructed, + int tag, + byte[] octets) + { + this.isConstructed = isConstructed; + this.tag = tag; + this.octets = octets; + } + + /** + * Return an ASN1ApplicationSpecific from the passed in object, which may be a byte array, or null. + * + * @param obj the object to be converted. + * @return obj's representation as an ASN1ApplicationSpecific object. + */ + public static ASN1ApplicationSpecific getInstance(Object obj) + { + if (obj == null || obj instanceof ASN1ApplicationSpecific) + { + return (ASN1ApplicationSpecific)obj; + } + else if (obj instanceof byte[]) + { + try + { + return ASN1ApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj)); + } + catch (IOException e) + { + throw new IllegalArgumentException("Failed to construct object from byte[]: " + e.getMessage()); + } + } + + throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName()); + } + + protected static int getLengthOfHeader(byte[] data) + { + int length = data[1] & 0xff; // TODO: assumes 1 byte tag + + if (length == 0x80) + { + return 2; // indefinite-length encoding + } + + if (length > 127) + { + int size = length & 0x7f; + + // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here + if (size > 4) + { + throw new IllegalStateException("DER length more than 4 bytes: " + size); + } + + return size + 2; + } + + return 2; + } + + /** + * Return true if the object is marked as constructed, false otherwise. + * + * @return true if constructed, otherwise false. + */ + public boolean isConstructed() + { + return isConstructed; + } + + /** + * Return the contents of this object as a byte[] + * + * @return the encoded contents of the object. + */ + public byte[] getContents() + { + return octets; + } + + /** + * Return the tag number associated with this object, + * + * @return the application tag number. + */ + public int getApplicationTag() + { + return tag; + } + + /** + * Return the enclosed object assuming explicit tagging. + * + * @return the resulting object + * @throws IOException if reconstruction fails. + */ + public ASN1Primitive 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 ASN1Primitive 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] & BERTags.CONSTRUCTED) != 0) + { + tmp[0] |= BERTags.CONSTRUCTED; + } + + return new ASN1InputStream(tmp).readObject(); + } + + int encodedLength() + throws IOException + { + return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length; + } + + /* (non-Javadoc) + * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream) + */ + void encode(ASN1OutputStream out) throws IOException + { + int classBits = BERTags.APPLICATION; + if (isConstructed) + { + classBits |= BERTags.CONSTRUCTED; + } + + out.writeEncoded(classBits, tag, octets); + } + + boolean asn1Equals( + ASN1Primitive o) + { + if (!(o instanceof ASN1ApplicationSpecific)) + { + return false; + } + + ASN1ApplicationSpecific other = (ASN1ApplicationSpecific)o; + + return isConstructed == other.isConstructed + && tag == other.tag + && Arrays.areEqual(octets, other.octets); + } + + 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; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1BitString.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1BitString.java new file mode 100644 index 00000000..513d4e5b --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1BitString.java @@ -0,0 +1,291 @@ +package org.bouncycastle.asn1; + +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; + +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.io.Streams; + +/** + * Base class for BIT STRING objects + */ +public abstract class ASN1BitString + extends ASN1Primitive + implements ASN1String +{ + private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + protected final byte[] data; + protected final int padBits; + + /** + * @param bitString an int containing the BIT STRING + * @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 0; + } + + int bits = 1; + + while (((val <<= 1) & 0xFF) != 0) + { + bits++; + } + + return 8 - bits; + } + + /** + * @param bitString an int containing the BIT STRING + * @return the correct number of bytes for a bit string defined in + * a 32 bit constant + */ + static protected byte[] getBytes(int bitString) + { + if (bitString == 0) + { + return new byte[0]; + } + + 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; + } + + /** + * Base constructor. + * + * @param data the octets making up the bit string. + * @param padBits the number of extra bits at the end of the string. + */ + public ASN1BitString( + byte[] data, + int padBits) + { + if (data == null) + { + throw new NullPointerException("data cannot be null"); + } + if (data.length == 0 && padBits != 0) + { + throw new IllegalArgumentException("zero length data with non-zero pad bits"); + } + if (padBits > 7 || padBits < 0) + { + throw new IllegalArgumentException("pad bits cannot be greater than 7 or less than 0"); + } + + this.data = Arrays.clone(data); + this.padBits = padBits; + } + + /** + * Return a String representation of this BIT STRING + * + * @return a String representation. + */ + 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 ASN1ParsingException("Internal error encoding BitString: " + e.getMessage(), e); + } + + 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(); + } + + /** + * @return the value of the bit string as an int (truncating if necessary) + */ + public int intValue() + { + int value = 0; + byte[] string = data; + + if (padBits > 0 && data.length <= 4) + { + string = derForm(data, padBits); + } + + for (int i = 0; i != string.length && i != 4; i++) + { + value |= (string[i] & 0xff) << (8 * i); + } + + return value; + } + + /** + * Return the octets contained in this BIT STRING, checking that this BIT STRING really + * does represent an octet aligned string. Only use this method when the standard you are + * following dictates that the BIT STRING will be octet aligned. + * + * @return a copy of the octet aligned data. + */ + public byte[] getOctets() + { + if (padBits != 0) + { + throw new IllegalStateException("attempt to get non-octet aligned data from BIT STRING"); + } + + return Arrays.clone(data); + } + + public byte[] getBytes() + { + return derForm(data, padBits); + } + + public int getPadBits() + { + return padBits; + } + + public String toString() + { + return getString(); + } + + public int hashCode() + { + return padBits ^ Arrays.hashCode(this.getBytes()); + } + + protected boolean asn1Equals( + ASN1Primitive o) + { + if (!(o instanceof ASN1BitString)) + { + return false; + } + + ASN1BitString other = (ASN1BitString)o; + + return this.padBits == other.padBits + && Arrays.areEqual(this.getBytes(), other.getBytes()); + } + + protected static byte[] derForm(byte[] data, int padBits) + { + byte[] rv = Arrays.clone(data); + // DER requires pad bits be zero + if (padBits > 0) + { + rv[data.length - 1] &= 0xff << padBits; + } + + return rv; + } + + static ASN1BitString fromInputStream(int length, InputStream stream) + throws IOException + { + if (length < 1) + { + throw new IllegalArgumentException("truncated BIT STRING detected"); + } + + int padBits = stream.read(); + byte[] data = new byte[length - 1]; + + if (data.length != 0) + { + if (Streams.readFully(stream, data) != data.length) + { + throw new EOFException("EOF encountered in middle of BIT STRING"); + } + + if (padBits > 0 && padBits < 8) + { + if (data[data.length - 1] != (byte)(data[data.length - 1] & (0xff << padBits))) + { + return new DLBitString(data, padBits); + } + } + } + + return new DERBitString(data, padBits); + } + + public ASN1Primitive getLoadedObject() + { + return this.toASN1Primitive(); + } + + ASN1Primitive toDERObject() + { + return new DERBitString(data, padBits); + } + + ASN1Primitive toDLObject() + { + return new DLBitString(data, padBits); + } + + abstract void encode(ASN1OutputStream out) + throws IOException; +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java index 30d7d452..d883a732 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java @@ -8,7 +8,6 @@ import org.bouncycastle.util.Arrays; * Public facade of ASN.1 Boolean data. * <p> * Use following to place a new instance of ASN.1 Boolean in your dataset: - * </p> * <ul> * <li> ASN1Boolean.TRUE literal</li> * <li> ASN1Boolean.FALSE literal</li> @@ -23,9 +22,7 @@ public class ASN1Boolean private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff }; private static final byte[] FALSE_VALUE = new byte[] { 0 }; - // BEGIN android-changed - final private byte[] value; - // END android-changed + private final byte[] value; public static final ASN1Boolean FALSE = new ASN1Boolean(false); public static final ASN1Boolean TRUE = new ASN1Boolean(true); @@ -63,6 +60,7 @@ public class ASN1Boolean /** * return an ASN1Boolean from the passed in boolean. + * @param value true or false depending on the ASN1Boolean wanted. * @return an ASN1Boolean instance. */ public static ASN1Boolean getInstance( @@ -73,6 +71,7 @@ public class ASN1Boolean /** * return an ASN1Boolean from the passed in value. + * @param value non-zero (true) or zero (false) depending on the ASN1Boolean wanted. * @return an ASN1Boolean instance. */ public static ASN1Boolean getInstance( diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java index 8a6714f2..3ca88905 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java @@ -7,7 +7,7 @@ package org.bouncycastle.asn1; * <p> * If you use this interface your class should also implement the getInstance() * pattern which takes a tag object and the tagging mode used. - * <p> + * </p> * <hr> * <p><b>X.690</b></p> * <p><b>8: Basic encoding rules</b></p> @@ -16,7 +16,7 @@ package org.bouncycastle.asn1; * The encoding of a choice value shall be the same as the encoding of a value of the chosen type. * <blockquote> * NOTE 1 — The encoding may be primitive or constructed depending on the chosen type. - * <p> + * <br /> * NOTE 2 — The tag used in the identifier octets is the tag of the chosen type, * as specified in the ASN.1 definition of the choice type. * </blockquote> diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java index 530da524..2828541e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java @@ -8,7 +8,7 @@ import java.util.Vector; */ public class ASN1EncodableVector { - Vector v = new Vector(); + private final Vector v = new Vector(); /** * Base constructor. diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java index d6fd2e29..195b924f 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java @@ -11,7 +11,7 @@ import org.bouncycastle.util.Arrays; public class ASN1Enumerated extends ASN1Primitive { - byte[] bytes; + private final byte[] bytes; /** * return an enumerated from the passed in object diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java index bbe5ae17..089526e1 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java @@ -162,6 +162,7 @@ public class ASN1GeneralizedTime * To read in the time and get a date which is compatible with our local * time zone. * </p> + * @return a String representation of the time. */ public String getTime() { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java index 1971af92..0c63a1a6 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java @@ -236,11 +236,11 @@ public class ASN1InputStream // int length = readLength(); - if (length < 0) // indefinite length method + if (length < 0) // indefinite-length method { if (!isConstructed) { - throw new IOException("indefinite length primitive encoding encountered"); + throw new IOException("indefinite-length primitive encoding encountered"); } IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this, limit); @@ -430,7 +430,7 @@ public class ASN1InputStream switch (tagNo) { case BIT_STRING: - return DERBitString.fromInputStream(defIn.getRemaining(), defIn); + return ASN1BitString.fromInputStream(defIn.getRemaining(), defIn); case BMP_STRING: return new DERBMPString(getBMPCharBuffer(defIn)); case BOOLEAN: @@ -465,6 +465,10 @@ public class ASN1InputStream return new DERUTF8String(defIn.toByteArray()); case VISIBLE_STRING: return new DERVisibleString(defIn.toByteArray()); + case GRAPHIC_STRING: + return new DERGraphicString(defIn.toByteArray()); + case VIDEOTEX_STRING: + return new DERVideotexString(defIn.toByteArray()); default: throw new IOException("unknown tag " + tagNo + " encountered"); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java index 10326cf6..c3c3f9cf 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java @@ -11,7 +11,7 @@ import org.bouncycastle.util.Arrays; public class ASN1Integer extends ASN1Primitive { - byte[] bytes; + private final byte[] bytes; /** * return an integer from the passed in object diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java index 9d54058d..ac65d96f 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java @@ -3,6 +3,8 @@ package org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; import org.bouncycastle.util.Arrays; @@ -12,7 +14,7 @@ import org.bouncycastle.util.Arrays; public class ASN1ObjectIdentifier extends ASN1Primitive { - String identifier; + private final String identifier; private byte[] body; @@ -304,7 +306,7 @@ public class ASN1ObjectIdentifier } } - protected synchronized byte[] getBody() + private synchronized byte[] getBody() { if (body == null) { @@ -350,6 +352,11 @@ public class ASN1ObjectIdentifier boolean asn1Equals( ASN1Primitive o) { + if (o == this) + { + return true; + } + if (!(o instanceof ASN1ObjectIdentifier)) { return false; @@ -414,69 +421,74 @@ public class ASN1ObjectIdentifier return isValidBranchID(identifier, 2); } - private static ASN1ObjectIdentifier[][] cache = new ASN1ObjectIdentifier[256][]; - - static ASN1ObjectIdentifier fromOctetString(byte[] enc) + /** + * Intern will return a reference to a pooled version of this object, unless it + * is not present in which case intern will add it. + * <p> + * The pool is also used by the ASN.1 parsers to limit the number of duplicated OID + * objects in circulation. + * </p> + * @return a reference to the identifier in the pool. + */ + public ASN1ObjectIdentifier intern() { - if (enc.length < 3) + synchronized (pool) { - return new ASN1ObjectIdentifier(enc); - } - - int idx1 = enc[enc.length - 2] & 0xff; - // in this case top bit is always zero - int idx2 = enc[enc.length - 1] & 0x7f; - - ASN1ObjectIdentifier possibleMatch; + OidHandle hdl = new OidHandle(getBody()); + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)pool.get(hdl); - synchronized (cache) - { - ASN1ObjectIdentifier[] first = cache[idx1]; - if (first == null) + if (oid != null) { - first = cache[idx1] = new ASN1ObjectIdentifier[128]; + return oid; } - - possibleMatch = first[idx2]; - if (possibleMatch == null) + else { - return first[idx2] = new ASN1ObjectIdentifier(enc); + pool.put(hdl, this); + return this; } + } + } - if (Arrays.areEqual(enc, possibleMatch.getBody())) - { - return possibleMatch; - } + private static final Map pool = new HashMap(); - idx1 = (idx1 + 1) & 0xff; - first = cache[idx1]; - if (first == null) - { - first = cache[idx1] = new ASN1ObjectIdentifier[128]; - } + private static class OidHandle + { + private int key; + private final byte[] enc; - possibleMatch = first[idx2]; - if (possibleMatch == null) - { - return first[idx2] = new ASN1ObjectIdentifier(enc); - } + OidHandle(byte[] enc) + { + this.key = Arrays.hashCode(enc); + this.enc = enc; + } - if (Arrays.areEqual(enc, possibleMatch.getBody())) - { - return possibleMatch; - } + public int hashCode() + { + return key; + } - idx2 = (idx2 + 1) & 0x7f; - possibleMatch = first[idx2]; - if (possibleMatch == null) + public boolean equals(Object o) + { + if (o instanceof OidHandle) { - return first[idx2] = new ASN1ObjectIdentifier(enc); + return Arrays.areEqual(enc, ((OidHandle)o).enc); } + + return false; } + } - if (Arrays.areEqual(enc, possibleMatch.getBody())) + static ASN1ObjectIdentifier fromOctetString(byte[] enc) + { + OidHandle hdl = new OidHandle(enc); + + synchronized (pool) { - return possibleMatch; + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)pool.get(hdl); + if (oid != null) + { + return oid; + } } return new ASN1ObjectIdentifier(enc); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java index 200b66a3..a3fa4a41 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java @@ -63,14 +63,14 @@ import org.bouncycastle.util.encoders.Hex; * each encoding in the contents octets may itself * be primitive or constructed. * However, such encodings will usually be primitive. - * </p><p> + * <br /> * NOTE 2 — In particular, the tags in the contents octets are always universal class, number 4. * </blockquote> * </p> * <p><b>9: Canonical encoding rules</b></p> * <p><b>9.1 Length forms</b></p> * <p> - * If the encoding is constructed, it shall employ the indefinite length form. + * If the encoding is constructed, it shall employ the indefinite-length form. * If the encoding is primitive, it shall include the fewest length octets necessary. * [Contrast with 8.1.3.2 b).] * </p> @@ -83,7 +83,7 @@ import org.bouncycastle.util.encoders.Hex; * the constructed encoding shall be encoded with a primitive encoding. * The encoding of each fragment, except possibly * the last, shall have 1000 contents octets. (Contrast with 8.21.6.) - * </p> + * </p><p> * <b>10: Distinguished encoding rules</b> * </p><p> * <b>10.1 Length forms</b> @@ -166,6 +166,8 @@ public abstract class ASN1OctetString } /** + * Base constructor. + * * @param string the octets making up the octet string. */ public ASN1OctetString( diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java index 3c887e55..db72d6ad 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java @@ -18,7 +18,7 @@ public abstract class ASN1Primitive * * @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. + * @exception IOException if there is a problem parsing the data, or parsing the stream did not exhaust the available data. */ public static ASN1Primitive fromByteArray(byte[] data) throws IOException @@ -27,7 +27,14 @@ public abstract class ASN1Primitive try { - return aIn.readObject(); + ASN1Primitive o = aIn.readObject(); + + if (aIn.available() != 0) + { + throw new IOException("Extra data detected in stream"); + } + + return o; } catch (ClassCastException e) { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java index aa543f28..0ca4d8f5 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java @@ -2,8 +2,11 @@ package org.bouncycastle.asn1; import java.io.IOException; import java.util.Enumeration; +import java.util.Iterator; import java.util.Vector; +import org.bouncycastle.util.Arrays; + /** * ASN.1 <code>SEQUENCE</code> and <code>SEQUENCE OF</code> constructs. * <p> @@ -41,7 +44,7 @@ import java.util.Vector; * </p> * <p><b>9: Canonical encoding rules</b></p> * <p><b>9.1 Length forms</b></p> - * If the encoding is constructed, it shall employ the indefinite length form. + * If the encoding is constructed, it shall employ the indefinite-length form. * If the encoding is primitive, it shall include the fewest length octets necessary. * [Contrast with 8.1.3.2 b).] * @@ -53,6 +56,7 @@ import java.util.Vector; */ public abstract class ASN1Sequence extends ASN1Primitive + implements org.bouncycastle.util.Iterable<ASN1Encodable> { protected Vector seq = new Vector(); @@ -188,7 +192,7 @@ public abstract class ASN1Sequence } } - /** + /* * Create a sequence containing a vector of objects. */ protected ASN1Sequence( @@ -379,4 +383,9 @@ public abstract class ASN1Sequence { return seq.toString(); } + + public Iterator<ASN1Encodable> iterator() + { + return new Arrays.Iterator<ASN1Encodable>(toArray()); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java index b4d263a3..1f6234f5 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java @@ -1,10 +1,12 @@ package org.bouncycastle.asn1; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Enumeration; +import java.util.Iterator; import java.util.Vector; +import org.bouncycastle.util.Arrays; + /** * ASN.1 <code>SET</code> and <code>SET OF</code> constructs. * <p> @@ -48,7 +50,7 @@ import java.util.Vector; * * <h3>9: Canonical encoding rules</h3> * <h4>9.1 Length forms</h4> - * If the encoding is constructed, it shall employ the indefinite length form. + * If the encoding is constructed, it shall employ the indefinite-length form. * If the encoding is primitive, it shall include the fewest length octets necessary. * [Contrast with 8.1.3.2 b).] * <h4>9.3 Set components</h4> @@ -94,6 +96,7 @@ import java.util.Vector; */ public abstract class ASN1Set extends ASN1Primitive + implements org.bouncycastle.util.Iterable<ASN1Encodable> { private Vector set = new Vector(); private boolean isSorted = false; @@ -252,7 +255,7 @@ public abstract class ASN1Set } } - /** + /* * create a sequence containing a vector of objects. */ protected ASN1Set( @@ -552,4 +555,9 @@ public abstract class ASN1Set { return set.toString(); } + + public Iterator<ASN1Encodable> iterator() + { + return new Arrays.Iterator<ASN1Encodable>(toArray()); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java index 418c1016..a4bb370e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java @@ -61,7 +61,7 @@ public class ASN1StreamParser { if (!constructed) { - throw new IOException("indefinite length primitive encoding encountered"); + throw new IOException("indefinite-length primitive encoding encountered"); } return readIndef(tag); @@ -92,8 +92,7 @@ public class ASN1StreamParser } } - // TODO ASN1Exception - throw new RuntimeException("implicit tagging not implemented"); + throw new ASN1Exception("implicit tagging not implemented"); } ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException @@ -145,11 +144,11 @@ public class ASN1StreamParser // int length = ASN1InputStream.readLength(_in, _limit); - if (length < 0) // indefinite length method + if (length < 0) // indefinite-length method { if (!isConstructed) { - throw new IOException("indefinite length primitive encoding encountered"); + throw new IOException("indefinite-length primitive encoding encountered"); } IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1String.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1String.java index fde4e239..37544406 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1String.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1String.java @@ -1,6 +1,13 @@ package org.bouncycastle.asn1; +/** + * General interface implemented by ASN.1 STRING objects. + */ public interface ASN1String { + /** + * Return a Java String representation of this STRING type's content. + * @return a Java String representation of this STRING. + */ public String getString(); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java index fb1e2442..778bea74 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java @@ -192,6 +192,7 @@ public abstract class ASN1TaggedObject public ASN1Encodable getObjectParser( int tag, boolean isExplicit) + throws IOException { switch (tag) { @@ -208,7 +209,7 @@ public abstract class ASN1TaggedObject return getObject(); } - throw new RuntimeException("implicit tagging not implemented for tag: " + tag); + throw new ASN1Exception("implicit tagging not implemented for tag: " + tag); } public ASN1Primitive getLoadedObject() diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java index 8bc8a4eb..f8d6aa22 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java @@ -1,10 +1,114 @@ package org.bouncycastle.asn1; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * An indefinite-length encoding version of an application specific object. + */ public class BERApplicationSpecific - extends DERApplicationSpecific + extends ASN1ApplicationSpecific { + BERApplicationSpecific( + boolean isConstructed, + int tag, + byte[] octets) + { + super(isConstructed, tag, octets); + } + + /** + * Create an application specific object with a tagging of explicit/constructed. + * + * @param tag the tag number for this object. + * @param object the object to be contained. + */ + public BERApplicationSpecific( + int tag, + ASN1Encodable object) + throws IOException + { + this(true, tag, object); + } + + /** + * Create an application specific object with the tagging style given by the value of constructed. + * + * @param constructed true if the object is constructed. + * @param tag the tag number for this object. + * @param object the object to be contained. + */ + public BERApplicationSpecific( + boolean constructed, + int tag, + ASN1Encodable object) + throws IOException + { + super(constructed || object.toASN1Primitive().isConstructed(), tag, getEncoding(constructed, object)); + } + + private static byte[] getEncoding(boolean explicit, ASN1Encodable object) + throws IOException + { + byte[] data = object.toASN1Primitive().getEncoded(ASN1Encoding.BER); + + if (explicit) + { + return data; + } + else + { + int lenBytes = getLengthOfHeader(data); + byte[] tmp = new byte[data.length - lenBytes]; + System.arraycopy(data, lenBytes, tmp, 0, tmp.length); + return tmp; + } + } + + /** + * Create an application specific object which is marked as constructed + * + * @param tagNo the tag number for this object. + * @param vec the objects making up the application specific object. + */ public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec) { - super(tagNo, vec); + super(true, tagNo, getEncodedVector(vec)); + } + + private static byte[] getEncodedVector(ASN1EncodableVector vec) + { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + for (int i = 0; i != vec.size(); i++) + { + try + { + bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.BER)); + } + catch (IOException e) + { + throw new ASN1ParsingException("malformed object: " + e, e); + } + } + return bOut.toByteArray(); + } + + /* (non-Javadoc) + * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream) + */ + void encode(ASN1OutputStream out) throws IOException + { + int classBits = BERTags.APPLICATION; + if (isConstructed) + { + classBits |= BERTags.CONSTRUCTED; + } + + out.writeTag(classBits, tag); + out.write(0x80); + out.write(octets); + out.write(0x00); + out.write(0x00); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java index 63bd9f3d..e4904e05 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java @@ -2,6 +2,9 @@ package org.bouncycastle.asn1; import java.io.IOException; +/** + * A parser for indefinite-length application specific objects. + */ public class BERApplicationSpecificParser implements ASN1ApplicationSpecificParser { @@ -14,18 +17,34 @@ public class BERApplicationSpecificParser this.parser = parser; } + /** + * Return the object contained in this application specific object, + * @return the contained object. + * @throws IOException if the underlying stream cannot be read, or does not contain an ASN.1 encoding. + */ public ASN1Encodable readObject() throws IOException { return parser.readObject(); } + /** + * Return an in-memory, encodable, representation of the application specific object. + * + * @return a BERApplicationSpecific. + * @throws IOException if there is an issue loading the data. + */ public ASN1Primitive getLoadedObject() throws IOException { return new BERApplicationSpecific(tag, parser.readVector()); } + /** + * Return a BERApplicationSpecific representing this parser and its contents. + * + * @return a BERApplicationSpecific + */ public ASN1Primitive toASN1Primitive() { try @@ -37,5 +56,4 @@ public class BERApplicationSpecificParser throw new ASN1ParsingException(e.getMessage(), e); } } - } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERGenerator.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERGenerator.java index ef7f9a38..c855110f 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BERGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERGenerator.java @@ -1,23 +1,25 @@ package org.bouncycastle.asn1; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; +/** + * Base class for generators for indefinite-length structures. + */ public class BERGenerator extends ASN1Generator { private boolean _tagged = false; private boolean _isExplicit; private int _tagNo; - + protected BERGenerator( OutputStream out) { super(out); } - public BERGenerator( + protected BERGenerator( OutputStream out, int tagNo, boolean isExplicit) @@ -72,18 +74,6 @@ public class BERGenerator writeHdr(tag); } } - - protected void writeBERBody( - InputStream contentStream) - throws IOException - { - int ch; - - while ((ch = contentStream.read()) >= 0) - { - _out.write(ch); - } - } protected void writeBEREnd() throws IOException diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERSequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERSequence.java index aa44950f..d4bfa061 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BERSequence.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERSequence.java @@ -3,18 +3,21 @@ package org.bouncycastle.asn1; import java.io.IOException; import java.util.Enumeration; +/** + * Carrier class for an indefinite-length SEQUENCE. + */ public class BERSequence extends ASN1Sequence { /** - * create an empty sequence + * Create an empty sequence */ public BERSequence() { } /** - * create a sequence containing one object + * Create a sequence containing one object */ public BERSequence( ASN1Encodable obj) @@ -23,7 +26,7 @@ public class BERSequence } /** - * create a sequence containing a vector of objects. + * Create a sequence containing a vector of objects. */ public BERSequence( ASN1EncodableVector v) @@ -32,7 +35,7 @@ public class BERSequence } /** - * create a sequence containing an array of objects. + * Create a sequence containing an array of objects. */ public BERSequence( ASN1Encodable[] array) @@ -52,8 +55,6 @@ public class BERSequence return 2 + length + 2; } - /* - */ void encode( ASN1OutputStream out) throws IOException diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERSequenceParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERSequenceParser.java index d5d43959..543a182e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BERSequenceParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERSequenceParser.java @@ -2,6 +2,9 @@ package org.bouncycastle.asn1; import java.io.IOException; +/** + * Parser for indefinite-length SEQUENCEs. + */ public class BERSequenceParser implements ASN1SequenceParser { @@ -12,18 +15,35 @@ public class BERSequenceParser this._parser = parser; } + /** + * Read the next object in the SEQUENCE. + * + * @return the next object in the SEQUENCE, null if there are no more. + * @throws IOException if there is an issue reading the underlying stream. + */ public ASN1Encodable readObject() throws IOException { return _parser.readObject(); } + /** + * Return an in-memory, encodable, representation of the SEQUENCE. + * + * @return a BERSequence. + * @throws IOException if there is an issue loading the data. + */ public ASN1Primitive getLoadedObject() throws IOException { return new BERSequence(_parser.readVector()); } - + + /** + * Return an BERSequence representing this parser and its contents. + * + * @return an BERSequence + */ public ASN1Primitive toASN1Primitive() { try diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERSet.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERSet.java index 064d7786..63a276bb 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BERSet.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERSet.java @@ -3,17 +3,22 @@ package org.bouncycastle.asn1; import java.io.IOException; import java.util.Enumeration; +/** + * Carrier class for an indefinite-length SET. + */ public class BERSet extends ASN1Set { /** - * create an empty sequence + * Create an empty SET. */ public BERSet() { } /** + * Create a SET containing one object. + * * @param obj - a single object that makes up the set. */ public BERSet( @@ -23,7 +28,8 @@ public class BERSet } /** - * @param v - a vector of objects making up the set. + * Create a SET containing multiple objects. + * @param v a vector of objects making up the set. */ public BERSet( ASN1EncodableVector v) @@ -32,7 +38,8 @@ public class BERSet } /** - * create a set from an array of objects. + * Create a SET from an array of objects. + * @param a an array of ASN.1 objects. */ public BERSet( ASN1Encodable[] a) @@ -52,8 +59,6 @@ public class BERSet return 2 + length + 2; } - /* - */ void encode( ASN1OutputStream out) throws IOException @@ -70,4 +75,4 @@ public class BERSet out.write(0x00); out.write(0x00); } -} +}
\ No newline at end of file diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERSetParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERSetParser.java index 5a30f3cf..c6e18095 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BERSetParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERSetParser.java @@ -2,6 +2,9 @@ package org.bouncycastle.asn1; import java.io.IOException; +/** + * Parser for indefinite-length SETs. + */ public class BERSetParser implements ASN1SetParser { @@ -12,18 +15,35 @@ public class BERSetParser this._parser = parser; } + /** + * Read the next object in the SET. + * + * @return the next object in the SET, null if there are no more. + * @throws IOException if there is an issue reading the underlying stream. + */ public ASN1Encodable readObject() throws IOException { return _parser.readObject(); } + /** + * Return an in-memory, encodable, representation of the SET. + * + * @return a BERSet. + * @throws IOException if there is an issue loading the data. + */ public ASN1Primitive getLoadedObject() throws IOException { return new BERSet(_parser.readVector()); } + /** + * Return an BERSet representing this parser and its contents. + * + * @return an BERSet + */ public ASN1Primitive toASN1Primitive() { try @@ -35,4 +55,4 @@ public class BERSetParser throw new ASN1ParsingException(e.getMessage(), e); } } -} +}
\ No newline at end of file diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERTaggedObjectParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERTaggedObjectParser.java index 7cd334a4..02f3f265 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BERTaggedObjectParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERTaggedObjectParser.java @@ -2,6 +2,9 @@ package org.bouncycastle.asn1; import java.io.IOException; +/** + * Parser for indefinite-length tagged objects. + */ public class BERTaggedObjectParser implements ASN1TaggedObjectParser { @@ -19,16 +22,34 @@ public class BERTaggedObjectParser _parser = parser; } + /** + * Return true if this tagged object is marked as constructed. + * + * @return true if constructed, false otherwise. + */ public boolean isConstructed() { return _constructed; } + /** + * Return the tag number associated with this object. + * + * @return the tag number. + */ public int getTagNo() { return _tagNumber; } + /** + * Return an object parser for the contents of this tagged object. + * + * @param tag the actual tag number of the object (needed if implicit). + * @param isExplicit true if the contained object was explicitly tagged, false if implicit. + * @return an ASN.1 encodable object parser. + * @throws IOException if there is an issue building the object parser from the stream. + */ public ASN1Encodable getObjectParser( int tag, boolean isExplicit) @@ -46,12 +67,23 @@ public class BERTaggedObjectParser return _parser.readImplicit(_constructed, tag); } + /** + * Return an in-memory, encodable, representation of the tagged object. + * + * @return an ASN1TaggedObject. + * @throws IOException if there is an issue loading the data. + */ public ASN1Primitive getLoadedObject() throws IOException { return _parser.readTaggedObject(_constructed, _tagNumber); } + /** + * Return an ASN1TaggedObject representing this parser and its contents. + * + * @return an ASN1TaggedObject + */ public ASN1Primitive toASN1Primitive() { try @@ -63,4 +95,4 @@ public class BERTaggedObjectParser throw new ASN1ParsingException(e.getMessage()); } } -} +}
\ No newline at end of file diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java index 85d9843b..a5999c09 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java @@ -3,28 +3,27 @@ package org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; -import org.bouncycastle.util.Arrays; - /** - * Base class for an application specific object + * A DER encoding version of an application specific object. */ public class DERApplicationSpecific - extends ASN1Primitive + extends ASN1ApplicationSpecific { - 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; + super(isConstructed, tag, octets); } + /** + * Create an application specific object from the passed in data. This will assume + * the data does not represent a constructed object. + * + * @param tag the tag number for this object. + * @param octets the encoding of the object's body. + */ public DERApplicationSpecific( int tag, byte[] octets) @@ -32,44 +31,67 @@ public class DERApplicationSpecific this(false, tag, octets); } + /** + * Create an application specific object with a tagging of explicit/constructed. + * + * @param tag the tag number for this object. + * @param object the object to be contained. + */ public DERApplicationSpecific( - int tag, + int tag, ASN1Encodable object) throws IOException { this(true, tag, object); } + /** + * Create an application specific object with the tagging style given by the value of constructed. + * + * @param constructed true if the object is constructed. + * @param tag the tag number for this object. + * @param object the object to be contained. + */ public DERApplicationSpecific( - boolean explicit, + boolean constructed, int tag, ASN1Encodable object) throws IOException { - ASN1Primitive primitive = object.toASN1Primitive(); - - byte[] data = primitive.getEncoded(ASN1Encoding.DER); + super(constructed || object.toASN1Primitive().isConstructed(), tag, getEncoding(constructed, object)); + } - this.isConstructed = explicit || (primitive instanceof ASN1Set || primitive instanceof ASN1Sequence); - this.tag = tag; + private static byte[] getEncoding(boolean explicit, ASN1Encodable object) + throws IOException + { + byte[] data = object.toASN1Primitive().getEncoded(ASN1Encoding.DER); if (explicit) { - this.octets = data; + return data; } else { int lenBytes = getLengthOfHeader(data); byte[] tmp = new byte[data.length - lenBytes]; System.arraycopy(data, lenBytes, tmp, 0, tmp.length); - this.octets = tmp; + return tmp; } } + /** + * Create an application specific object which is marked as constructed + * + * @param tagNo the tag number for this object. + * @param vec the objects making up the application specific object. + */ public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec) { - this.tag = tagNo; - this.isConstructed = true; + super(true, tagNo, getEncodedVector(vec)); + } + + private static byte[] getEncodedVector(ASN1EncodableVector vec) + { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); for (int i = 0; i != vec.size(); i++) @@ -83,112 +105,7 @@ public class DERApplicationSpecific throw new ASN1ParsingException("malformed object: " + e, e); } } - this.octets = bOut.toByteArray(); - } - - public static DERApplicationSpecific getInstance(Object obj) - { - if (obj == null || obj instanceof DERApplicationSpecific) - { - return (DERApplicationSpecific)obj; - } - else if (obj instanceof byte[]) - { - try - { - return DERApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj)); - } - catch (IOException e) - { - throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage()); - } - } - - throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName()); - } - - private int getLengthOfHeader(byte[] data) - { - int length = data[1] & 0xff; // TODO: assumes 1 byte tag - - if (length == 0x80) - { - return 2; // indefinite-length encoding - } - - if (length > 127) - { - int size = length & 0x7f; - - // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here - if (size > 4) - { - throw new IllegalStateException("DER length more than 4 bytes: " + size); - } - - return size + 2; - } - - return 2; - } - - 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 ASN1Primitive 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 ASN1Primitive 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] & BERTags.CONSTRUCTED) != 0) - { - tmp[0] |= BERTags.CONSTRUCTED; - } - - return new ASN1InputStream(tmp).readObject(); - } - - int encodedLength() - throws IOException - { - return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length; + return bOut.toByteArray(); } /* (non-Javadoc) @@ -204,64 +121,4 @@ public class DERApplicationSpecific out.writeEncoded(classBits, tag, octets); } - - boolean asn1Equals( - ASN1Primitive o) - { - if (!(o instanceof DERApplicationSpecific)) - { - return false; - } - - DERApplicationSpecific other = (DERApplicationSpecific)o; - - return isConstructed == other.isConstructed - && tag == other.tag - && Arrays.areEqual(octets, other.octets); - } - - 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; - } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java index 635300b4..e689985c 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java @@ -5,13 +5,13 @@ import java.io.IOException; import org.bouncycastle.util.Arrays; /** - * DER BMPString object. + * Carrier class for DER encoding BMPString object. */ public class DERBMPString extends ASN1Primitive implements ASN1String { - private char[] string; + private final char[] string; /** * return a BMP String from the given object. diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java index 4852a796..d74bc00e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java @@ -1,97 +1,13 @@ package org.bouncycastle.asn1; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; import java.io.IOException; -import java.io.InputStream; - -import org.bouncycastle.util.Arrays; -import org.bouncycastle.util.io.Streams; +/** + * A BIT STRING with DER encoding. + */ public class DERBitString - extends ASN1Primitive - implements ASN1String + extends ASN1BitString { - 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; - - /** - * @param bitString an int containing the BIT STRING - * @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; - } - - /** - * @param bitString an int containing the BIT STRING - * @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 * @@ -106,6 +22,10 @@ public class DERBitString { return (DERBitString)obj; } + if (obj instanceof DLBitString) + { + return new DERBitString(((DLBitString)obj).data, ((DLBitString)obj).padBits); + } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } @@ -140,9 +60,16 @@ public class DERBitString byte data, int padBits) { - this.data = new byte[1]; - this.data[0] = data; - this.padBits = padBits; + this(toByteArray(data), padBits); + } + + private static byte[] toByteArray(byte data) + { + byte[] rv = new byte[1]; + + rv[0] = data; + + return rv; } /** @@ -153,8 +80,7 @@ public class DERBitString byte[] data, int padBits) { - this.data = data; - this.padBits = padBits; + super(data, padBits); } public DERBitString( @@ -166,42 +92,14 @@ public class DERBitString public DERBitString( int value) { - this.data = getBytes(value); - this.padBits = getPadBits(value); + super(getBytes(value), getPadBits(value)); } public DERBitString( ASN1Encodable obj) throws IOException { - this.data = obj.toASN1Primitive().getEncoded(ASN1Encoding.DER); - this.padBits = 0; - } - - 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; + super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER), 0); } boolean isConstructed() @@ -218,64 +116,15 @@ public class DERBitString ASN1OutputStream out) throws IOException { - byte[] bytes = new byte[getBytes().length + 1]; + byte[] string = derForm(data, padBits); + byte[] bytes = new byte[string.length + 1]; bytes[0] = (byte)getPadBits(); - System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1); + System.arraycopy(string, 0, bytes, 1, bytes.length - 1); out.writeEncoded(BERTags.BIT_STRING, bytes); } - public int hashCode() - { - return padBits ^ Arrays.hashCode(data); - } - - protected boolean asn1Equals( - ASN1Primitive 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(); - } - - public String toString() - { - return getString(); - } - static DERBitString fromOctetString(byte[] bytes) { if (bytes.length < 1) @@ -293,26 +142,4 @@ public class DERBitString return new DERBitString(data, padBits); } - - static DERBitString fromInputStream(int length, InputStream stream) - throws IOException - { - if (length < 1) - { - throw new IllegalArgumentException("truncated BIT STRING detected"); - } - - int padBits = stream.read(); - byte[] data = new byte[length - 1]; - - if (data.length != 0) - { - if (Streams.readFully(stream, data) != data.length) - { - throw new EOFException("EOF encountered in middle of BIT STRING"); - } - } - - return new DERBitString(data, padBits); - } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DEREncodableVector.java b/bcprov/src/main/java/org/bouncycastle/asn1/DEREncodableVector.java index 919ff72d..ff1059ac 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DEREncodableVector.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DEREncodableVector.java @@ -2,7 +2,7 @@ package org.bouncycastle.asn1; /** * a general class for building up a vector of DER encodable objects - - * this will eventually be superceded by ASN1EncodableVector so you should + * this will eventually be superseded by ASN1EncodableVector so you should * use that class in preference. */ public class DEREncodableVector diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERExternal.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERExternal.java index aed1d27f..f6c45d31 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERExternal.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERExternal.java @@ -32,7 +32,7 @@ public class DERExternal offset++; enc = getObjFromVector(vector, offset); } - if (!(enc instanceof DERTaggedObject)) + if (!(enc instanceof ASN1TaggedObject)) { dataValueDescriptor = (ASN1Primitive) enc; offset++; @@ -44,11 +44,11 @@ public class DERExternal throw new IllegalArgumentException("input vector too large"); } - if (!(enc instanceof DERTaggedObject)) + if (!(enc instanceof ASN1TaggedObject)) { throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External"); } - DERTaggedObject obj = (DERTaggedObject)enc; + ASN1TaggedObject obj = (ASN1TaggedObject)enc; setEncoding(obj.getTagNo()); externalContent = obj.getObject(); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERExternalParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERExternalParser.java index b19c84d5..98d02e73 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERExternalParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERExternalParser.java @@ -2,13 +2,18 @@ package org.bouncycastle.asn1; import java.io.IOException; +/** + * Parser DER EXTERNAL tagged objects. + */ public class DERExternalParser implements ASN1Encodable, InMemoryRepresentable { private ASN1StreamParser _parser; /** - * + * Base constructor. + * + * @param parser the underlying parser to read the DER EXTERNAL from. */ public DERExternalParser(ASN1StreamParser parser) { @@ -21,6 +26,12 @@ public class DERExternalParser return _parser.readObject(); } + /** + * Return an in-memory, encodable, representation of the EXTERNAL object. + * + * @return a DERExternal. + * @throws IOException if there is an issue loading the data. + */ public ASN1Primitive getLoadedObject() throws IOException { @@ -33,20 +44,25 @@ public class DERExternalParser throw new ASN1Exception(e.getMessage(), e); } } - + + /** + * Return an DERExternal representing this parser and its contents. + * + * @return an DERExternal + */ public ASN1Primitive toASN1Primitive() { - try + try { return getLoadedObject(); } - catch (IOException ioe) + catch (IOException ioe) { throw new ASN1ParsingException("unable to get DER object", ioe); } - catch (IllegalArgumentException ioe) + catch (IllegalArgumentException ioe) { throw new ASN1ParsingException("unable to get DER object", ioe); } } -} +}
\ No newline at end of file diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralString.java index c6354f46..9addf700 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralString.java @@ -5,12 +5,22 @@ import java.io.IOException; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Strings; +/** + * Carrier class for a DER encoding GeneralString + */ public class DERGeneralString extends ASN1Primitive implements ASN1String { - private byte[] string; - + private final byte[] string; + + /** + * return a GeneralString from the given object. + * + * @param obj the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERBMPString instance, or null. + */ public static DERGeneralString getInstance( Object obj) { @@ -35,6 +45,16 @@ public class DERGeneralString + obj.getClass().getName()); } + /** + * return a GeneralString 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. + * @return a DERGeneralString instance. + */ public static DERGeneralString getInstance( ASN1TaggedObject obj, boolean explicit) @@ -56,11 +76,21 @@ public class DERGeneralString this.string = string; } + /** + * Construct a GeneralString from the passed in String. + * + * @param string the string to be contained in this object. + */ public DERGeneralString(String string) { this.string = Strings.toByteArray(string); } - + + /** + * Return a Java String representation of our contained String. + * + * @return a Java String representing our contents. + */ public String getString() { return Strings.fromByteArray(string); @@ -71,6 +101,11 @@ public class DERGeneralString return getString(); } + /** + * Return a byte array representation of our contained String. + * + * @return a byte array representing our contents. + */ public byte[] getOctets() { return Arrays.clone(string); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERGraphicString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERGraphicString.java new file mode 100644 index 00000000..01baf0f9 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERGraphicString.java @@ -0,0 +1,124 @@ +package org.bouncycastle.asn1; + +import java.io.IOException; + +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Strings; + +public class DERGraphicString + extends ASN1Primitive + implements ASN1String +{ + private final byte[] string; + + /** + * return a Graphic String from the passed in object + * + * @param obj a DERGraphicString or an object that can be converted into one. + * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERGraphicString instance, or null. + */ + public static DERGraphicString getInstance( + Object obj) + { + if (obj == null || obj instanceof DERGraphicString) + { + return (DERGraphicString)obj; + } + + if (obj instanceof byte[]) + { + try + { + return (DERGraphicString)fromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); + } + } + + throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); + } + + /** + * return a Graphic 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. + * @return a DERGraphicString instance, or null. + */ + public static DERGraphicString getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + ASN1Primitive o = obj.getObject(); + + if (explicit || o instanceof DERGraphicString) + { + return getInstance(o); + } + else + { + return new DERGraphicString(((ASN1OctetString)o).getOctets()); + } + } + + /** + * basic constructor - with bytes. + * @param string the byte encoding of the characters making up the string. + */ + public DERGraphicString( + byte[] string) + { + this.string = Arrays.clone(string); + } + + public byte[] getOctets() + { + return Arrays.clone(string); + } + + boolean isConstructed() + { + return false; + } + + int encodedLength() + { + return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; + } + + void encode( + ASN1OutputStream out) + throws IOException + { + out.writeEncoded(BERTags.GRAPHIC_STRING, string); + } + + public int hashCode() + { + return Arrays.hashCode(string); + } + + boolean asn1Equals( + ASN1Primitive o) + { + if (!(o instanceof DERGraphicString)) + { + return false; + } + + DERGraphicString s = (DERGraphicString)o; + + return Arrays.areEqual(string, s.string); + } + + public String getString() + { + return Strings.fromByteArray(string); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java index 1c533b10..0336e6b7 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java @@ -12,7 +12,7 @@ public class DERIA5String extends ASN1Primitive implements ASN1String { - private byte[] string; + private final byte[] string; /** * return a IA5 string from the passed in object diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java index e1b1276d..ed287e56 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java @@ -12,7 +12,7 @@ public class DERNumericString extends ASN1Primitive implements ASN1String { - private byte[] string; + private final byte[] string; /** * return a Numeric string from the passed in object diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetString.java index 988186fb..1201c74e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetString.java @@ -2,10 +2,15 @@ package org.bouncycastle.asn1; import java.io.IOException; +/** + * Carrier class for a DER encoding OCTET STRING + */ public class DEROctetString extends ASN1OctetString { /** + * Base constructor. + * * @param string the octets making up the octet string. */ public DEROctetString( @@ -14,6 +19,11 @@ public class DEROctetString super(string); } + /** + * Constructor from the encoding of an ASN.1 object. + * + * @param obj the object to be encoded. + */ public DEROctetString( ASN1Encodable obj) throws IOException diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java index e6e20686..58be862d 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java @@ -3,6 +3,9 @@ package org.bouncycastle.asn1; import java.io.IOException; import java.io.InputStream; +/** + * Parse for DER encoded OCTET STRINGS + */ public class DEROctetStringParser implements ASN1OctetStringParser { @@ -14,17 +17,33 @@ public class DEROctetStringParser this.stream = stream; } + /** + * Return an InputStream representing the contents of the OCTET STRING. + * + * @return an InputStream with its source as the OCTET STRING content. + */ public InputStream getOctetStream() { return stream; } + /** + * Return an in-memory, encodable, representation of the OCTET STRING. + * + * @return a DEROctetString. + * @throws IOException if there is an issue loading the data. + */ public ASN1Primitive getLoadedObject() throws IOException { return new DEROctetString(stream.toByteArray()); } - + + /** + * Return an DEROctetString representing this parser and its contents. + * + * @return an DEROctetString + */ public ASN1Primitive toASN1Primitive() { try diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java index 7d56b492..805ad30e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java @@ -12,9 +12,7 @@ public class DERPrintableString extends ASN1Primitive implements ASN1String { - // BEGIN android-changed private final byte[] string; - // END android-changed /** * return a printable string from the passed in object. diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERSequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERSequence.java index ad48a833..b631064d 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERSequence.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERSequence.java @@ -17,6 +17,7 @@ public class DERSequence /** * create a sequence containing one object + * @param obj the object to go in the sequence. */ public DERSequence( ASN1Encodable obj) @@ -26,6 +27,7 @@ public class DERSequence /** * create a sequence containing a vector of objects. + * @param v the vector of objects to make up the sequence. */ public DERSequence( ASN1EncodableVector v) @@ -35,6 +37,7 @@ public class DERSequence /** * create a sequence containing an array of objects. + * @param array the array of objects to make up the sequence. */ public DERSequence( ASN1Encodable[] array) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java index c1faf849..ac58eacf 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java @@ -19,7 +19,8 @@ public class DERSet } /** - * @param obj - a single object that makes up the set. + * create a set containing one object + * @param obj the object to go in the set */ public DERSet( ASN1Encodable obj) @@ -28,7 +29,8 @@ public class DERSet } /** - * @param v - a vector of objects making up the set. + * create a set containing a vector of objects. + * @param v the vector of objects to make up the set. */ public DERSet( ASN1EncodableVector v) @@ -37,7 +39,8 @@ public class DERSet } /** - * create a set from an array of objects. + * create a set containing an array of objects. + * @param a the array of objects to make up the set. */ public DERSet( ASN1Encodable[] a) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java index 783cd336..30744c69 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java @@ -13,7 +13,7 @@ public class DERT61String extends ASN1Primitive implements ASN1String { - private byte[] string; + private final byte[] string; /** * return a T61 string from the passed in object. diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERUTF8String.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERUTF8String.java index f54d1dbb..d1fffa67 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERUTF8String.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERUTF8String.java @@ -12,7 +12,7 @@ public class DERUTF8String extends ASN1Primitive implements ASN1String { - private byte[] string; + private final byte[] string; /** * Return an UTF8 string from the passed in object. @@ -73,7 +73,7 @@ public class DERUTF8String } } - /** + /* * Basic constructor - byte encoded string. */ DERUTF8String(byte[] string) @@ -83,6 +83,8 @@ public class DERUTF8String /** * Basic constructor + * + * @param string the string to be carried in the UTF8String object, */ public DERUTF8String(String string) { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java index 0d447df7..85390990 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java @@ -13,7 +13,7 @@ public class DERUniversalString implements ASN1String { private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - private byte[] string; + private final byte[] string; /** * return a Universal String from the passed in object. @@ -73,6 +73,8 @@ public class DERUniversalString /** * basic constructor - byte encoded string. + * + * @param string the byte encoding of the string to be carried in the UniversalString object, */ public DERUniversalString( byte[] string) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERVideotexString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERVideotexString.java new file mode 100644 index 00000000..da231e15 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERVideotexString.java @@ -0,0 +1,124 @@ +package org.bouncycastle.asn1; + +import java.io.IOException; + +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Strings; + +public class DERVideotexString + extends ASN1Primitive + implements ASN1String +{ + private final byte[] string; + + /** + * return a Videotex String from the passed in object + * + * @param obj a DERVideotexString or an object that can be converted into one. + * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERVideotexString instance, or null. + */ + public static DERVideotexString getInstance( + Object obj) + { + if (obj == null || obj instanceof DERVideotexString) + { + return (DERVideotexString)obj; + } + + if (obj instanceof byte[]) + { + try + { + return (DERVideotexString)fromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); + } + } + + throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); + } + + /** + * return a Videotex 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. + * @return a DERVideotexString instance, or null. + */ + public static DERVideotexString getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + ASN1Primitive o = obj.getObject(); + + if (explicit || o instanceof DERVideotexString) + { + return getInstance(o); + } + else + { + return new DERVideotexString(((ASN1OctetString)o).getOctets()); + } + } + + /** + * basic constructor - with bytes. + * @param string the byte encoding of the characters making up the string. + */ + public DERVideotexString( + byte[] string) + { + this.string = Arrays.clone(string); + } + + public byte[] getOctets() + { + return Arrays.clone(string); + } + + boolean isConstructed() + { + return false; + } + + int encodedLength() + { + return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; + } + + void encode( + ASN1OutputStream out) + throws IOException + { + out.writeEncoded(BERTags.VIDEOTEX_STRING, string); + } + + public int hashCode() + { + return Arrays.hashCode(string); + } + + boolean asn1Equals( + ASN1Primitive o) + { + if (!(o instanceof DERVideotexString)) + { + return false; + } + + DERVideotexString s = (DERVideotexString)o; + + return Arrays.areEqual(string, s.string); + } + + public String getString() + { + return Strings.fromByteArray(string); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERVisibleString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERVisibleString.java index 6eb282cc..5932c977 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERVisibleString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERVisibleString.java @@ -15,7 +15,7 @@ public class DERVisibleString extends ASN1Primitive implements ASN1String { - private byte[] string; + private final byte[] string; /** * Return a Visible String from the passed in object. @@ -73,7 +73,7 @@ public class DERVisibleString } } - /** + /* * Basic constructor - byte encoded string. */ DERVisibleString( @@ -84,6 +84,8 @@ public class DERVisibleString /** * Basic constructor + * + * @param string the string to be carried in the VisibleString object, */ public DERVisibleString( String string) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java new file mode 100644 index 00000000..c81f0ab9 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java @@ -0,0 +1,145 @@ +package org.bouncycastle.asn1; + +import java.io.IOException; + +/** + * A Definite length BIT STRING + */ +public class DLBitString + extends ASN1BitString +{ + /** + * return a Bit String that can be definite-length encoded from the passed in object. + * + * @param obj a DL or DER BitString or an object that can be converted into one. + * @exception IllegalArgumentException if the object cannot be converted. + * @return an ASN1BitString instance, or null. + */ + public static ASN1BitString getInstance( + Object obj) + { + if (obj == null || obj instanceof DLBitString) + { + return (DLBitString)obj; + } + if (obj instanceof DERBitString) + { + return (DERBitString)obj; + } + + 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. + * @return an ASN1BitString instance, or null. + */ + public static ASN1BitString getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + ASN1Primitive o = obj.getObject(); + + if (explicit || o instanceof DLBitString) + { + return getInstance(o); + } + else + { + return fromOctetString(((ASN1OctetString)o).getOctets()); + } + } + + protected DLBitString( + byte data, + int padBits) + { + this(toByteArray(data), padBits); + } + + private static byte[] toByteArray(byte data) + { + byte[] rv = new byte[1]; + + rv[0] = data; + + return rv; + } + + /** + * @param data the octets making up the bit string. + * @param padBits the number of extra bits at the end of the string. + */ + public DLBitString( + byte[] data, + int padBits) + { + super(data, padBits); + } + + public DLBitString( + byte[] data) + { + this(data, 0); + } + + public DLBitString( + int value) + { + super(getBytes(value), getPadBits(value)); + } + + public DLBitString( + ASN1Encodable obj) + throws IOException + { + super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER), 0); + } + + boolean isConstructed() + { + return false; + } + + int encodedLength() + { + return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1; + } + + void encode( + ASN1OutputStream out) + throws IOException + { + byte[] string = data; + byte[] bytes = new byte[string.length + 1]; + + bytes[0] = (byte)getPadBits(); + System.arraycopy(string, 0, bytes, 1, bytes.length - 1); + + out.writeEncoded(BERTags.BIT_STRING, bytes); + } + + static DLBitString fromOctetString(byte[] bytes) + { + if (bytes.length < 1) + { + throw new IllegalArgumentException("truncated BIT STRING detected"); + } + + int padBits = bytes[0]; + byte[] data = new byte[bytes.length - 1]; + + if (data.length != 0) + { + System.arraycopy(bytes, 1, data, 0, bytes.length - 1); + } + + return new DLBitString(data, padBits); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java index b5cc59a2..65acd274 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java @@ -19,7 +19,8 @@ public class DLSequence } /** - * Create a sequence containing one object + * create a sequence containing one object + * @param obj the object to go in the sequence. */ public DLSequence( ASN1Encodable obj) @@ -28,7 +29,8 @@ public class DLSequence } /** - * Create a sequence containing a vector of objects. + * create a sequence containing a vector of objects. + * @param v the vector of objects to make up the sequence. */ public DLSequence( ASN1EncodableVector v) @@ -37,7 +39,8 @@ public class DLSequence } /** - * Create a sequence containing an array of objects. + * create a sequence containing an array of objects. + * @param array the array of objects to make up the sequence. */ public DLSequence( ASN1Encodable[] array) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java b/bcprov/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java index 9374ab76..734298b9 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java @@ -9,6 +9,7 @@ public interface InMemoryRepresentable { /** * Get the in-memory representation of the ASN.1 object. + * @return an ASN1Primitive representing the loaded object. * @throws IOException for bad input data. */ ASN1Primitive getLoadedObject() diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/OIDTokenizer.java b/bcprov/src/main/java/org/bouncycastle/asn1/OIDTokenizer.java index 54679447..4c896ad2 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/OIDTokenizer.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/OIDTokenizer.java @@ -1,7 +1,7 @@ package org.bouncycastle.asn1; /** - * class for breaking up an OID into it's component tokens, ala + * 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. @@ -11,6 +11,11 @@ public class OIDTokenizer private String oid; private int index; + /** + * Base constructor. + * + * @param oid the string representation of the OID. + */ public OIDTokenizer( String oid) { @@ -18,11 +23,21 @@ public class OIDTokenizer this.index = 0; } + /** + * Return whether or not there are more tokens in this tokenizer. + * + * @return true if there are more tokens, false otherwise. + */ public boolean hasMoreTokens() { return (index != -1); } + /** + * Return the next token in the underlying String. + * + * @return the next token. + */ public String nextToken() { if (index == -1) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java index 16a67682..5b95b79e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java @@ -3,9 +3,7 @@ package org.bouncycastle.asn1.bc; import org.bouncycastle.asn1.ASN1ObjectIdentifier; /** - * iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle - * <p> - * 1.3.6.1.4.1.22554 + * Object Identifiers belonging to iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle (1.3.6.1.4.1.22554) */ public interface BCObjectIdentifiers { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java index 3b8e0bed..7550282a 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java @@ -216,9 +216,9 @@ public class AttributeTable /** * Return a new table with the passed in attribute added. * - * @param attrType - * @param attrValue - * @return + * @param attrType the type of the attribute to add. + * @param attrValue the value corresponding to the attribute (will be wrapped in a SET). + * @return a new table with the extra attribute in it. */ public AttributeTable add(ASN1ObjectIdentifier attrType, ASN1Encodable attrValue) { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAlgorithmProtection.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAlgorithmProtection.java new file mode 100644 index 00000000..d18fe4bc --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAlgorithmProtection.java @@ -0,0 +1,136 @@ +package org.bouncycastle.asn1.cms; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** + * From RFC 6211 + * <pre> + * CMSAlgorithmProtection ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * signatureAlgorithm [1] SignatureAlgorithmIdentifier OPTIONAL, + * macAlgorithm [2] MessageAuthenticationCodeAlgorithm + * OPTIONAL + * } + * (WITH COMPONENTS { signatureAlgorithm PRESENT, + * macAlgorithm ABSENT } | + * WITH COMPONENTS { signatureAlgorithm ABSENT, + * macAlgorithm PRESENT }) + * </pre> + */ +public class CMSAlgorithmProtection + extends ASN1Object +{ + public static final int SIGNATURE = 1; + public static final int MAC = 2; + + private final AlgorithmIdentifier digestAlgorithm; + private final AlgorithmIdentifier signatureAlgorithm; + private final AlgorithmIdentifier macAlgorithm; + + public CMSAlgorithmProtection(AlgorithmIdentifier digestAlgorithm, int type, AlgorithmIdentifier algorithmIdentifier) + { + if (digestAlgorithm == null || algorithmIdentifier == null) + { + throw new NullPointerException("AlgorithmIdentifiers cannot be null"); + } + + this.digestAlgorithm = digestAlgorithm; + + if (type == 1) + { + this.signatureAlgorithm = algorithmIdentifier; + this.macAlgorithm = null; + } + else if (type == 2) + { + this.signatureAlgorithm = null; + this.macAlgorithm = algorithmIdentifier; + } + else + { + throw new IllegalArgumentException("Unknown type: " + type); + } + } + + private CMSAlgorithmProtection(ASN1Sequence sequence) + { + if (sequence.size() != 2) + { + throw new IllegalArgumentException("Sequence wrong size: One of signatureAlgorithm or macAlgorithm must be present"); + } + + this.digestAlgorithm = AlgorithmIdentifier.getInstance(sequence.getObjectAt(0)); + + ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(sequence.getObjectAt(1)); + if (tagged.getTagNo() == 1) + { + this.signatureAlgorithm = AlgorithmIdentifier.getInstance(tagged, false); + this.macAlgorithm = null; + } + else if (tagged.getTagNo() == 2) + { + this.signatureAlgorithm = null; + + this.macAlgorithm = AlgorithmIdentifier.getInstance(tagged, false); + } + else + { + throw new IllegalArgumentException("Unknown tag found: " + tagged.getTagNo()); + } + } + + public static CMSAlgorithmProtection getInstance( + Object obj) + { + if (obj instanceof CMSAlgorithmProtection) + { + return (CMSAlgorithmProtection)obj; + } + else if (obj != null) + { + return new CMSAlgorithmProtection(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + + public AlgorithmIdentifier getDigestAlgorithm() + { + return digestAlgorithm; + } + + public AlgorithmIdentifier getMacAlgorithm() + { + return macAlgorithm; + } + + public AlgorithmIdentifier getSignatureAlgorithm() + { + return signatureAlgorithm; + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(digestAlgorithm); + if (signatureAlgorithm != null) + { + v.add(new DERTaggedObject(false, 1, signatureAlgorithm)); + } + if (macAlgorithm != null) + { + v.add(new DERTaggedObject(false, 2, macAlgorithm)); + } + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java index d2fc7d1a..71c85fbe 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java @@ -5,13 +5,15 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; /** * <a href="http://tools.ietf.org/html/rfc5652">RFC 5652</a> CMS attribute OID constants. + * and <a href="http://tools.ietf.org/html/rfc6211">RFC 6211</a> Algorithm Identifier Protection Attribute. * <pre> * contentType ::= 1.2.840.113549.1.9.3 * messageDigest ::= 1.2.840.113549.1.9.4 * signingTime ::= 1.2.840.113549.1.9.5 * counterSignature ::= 1.2.840.113549.1.9.6 * - * contentHint ::= 1.2.840.113549.1.9.16.2.4 + * contentHint ::= 1.2.840.113549.1.9.16.2.4 + * cmsAlgorithmProtect := 1.2.840.113549.1.9.52 * </pre> */ @@ -27,4 +29,7 @@ public interface CMSAttributes public static final ASN1ObjectIdentifier counterSignature = PKCSObjectIdentifiers.pkcs_9_at_counterSignature; /** PKCS#9: 1.2.840.113549.1.9.16.6.2.4 - See <a href="http://tools.ietf.org/html/rfc2634">RFC 2634</a> */ public static final ASN1ObjectIdentifier contentHint = PKCSObjectIdentifiers.id_aa_contentHint; + + public static final ASN1ObjectIdentifier cmsAlgorithmProtect = PKCSObjectIdentifiers.id_aa_cmsAlgorithmProtect; + } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java index 8c7fcc2d..70278970 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java @@ -34,7 +34,7 @@ import org.bouncycastle.asn1.DERTaggedObject; * SignerInfos ::= SET OF SignerInfo * </pre> * <p> - * The version calculation uses following ruleset from RFC 3852 section 5.1: + * The version calculation uses following ruleset from RFC 5652 section 5.1: * <pre> * IF ((certificates is present) AND * (any certificates with a type of other are present)) OR @@ -54,7 +54,6 @@ import org.bouncycastle.asn1.DERTaggedObject; * ELSE version MUST be 1 * </pre> * <p> - * @todo Check possible update for this to RFC 5652 level */ public class SignedData extends ASN1Object @@ -84,7 +83,8 @@ public class SignedData * </ul> * * @param o the object we want converted. - * @exception IllegalArgumentException if the object cannot be converted. + * @return a reference that can be assigned to SignedData (may be null) + * @throws IllegalArgumentException if the object cannot be converted. */ public static SignedData getInstance( Object o) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java index 42090458..486eae2d 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java @@ -39,7 +39,7 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; * * ----------------------------------------- * - * RFC 5256: + * RFC 5652: * * SignerInfo ::= SEQUENCE { * version CMSVersion, diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java index 098656c0..284751eb 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java @@ -63,4 +63,33 @@ public interface MiscObjectIdentifiers static final ASN1ObjectIdentifier entrust = new ASN1ObjectIdentifier("1.2.840.113533.7"); /** NortelNetworks Entrust VersionExtension OID: 1.2.840.113533.7.65.0 */ static final ASN1ObjectIdentifier entrustVersionExtension = entrust.branch("65.0"); + + /** cast5CBC OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) nt(113533) nsn(7) algorithms(66) 10} SEE RFC 2984 */ + ASN1ObjectIdentifier cast5CBC = entrust.branch("66.10"); + + // + // Ascom + // + ASN1ObjectIdentifier as_sys_sec_alg_ideaCBC = new ASN1ObjectIdentifier("1.3.6.1.4.1.188.7.1.1.2"); + + // + // Peter Gutmann's Cryptlib + // + ASN1ObjectIdentifier cryptlib = new ASN1ObjectIdentifier("1.3.6.1.4.1.3029"); + + ASN1ObjectIdentifier cryptlib_algorithm = cryptlib.branch("1"); + ASN1ObjectIdentifier cryptlib_algorithm_blowfish_ECB = cryptlib_algorithm.branch("1.1"); + ASN1ObjectIdentifier cryptlib_algorithm_blowfish_CBC = cryptlib_algorithm.branch("1.2"); + ASN1ObjectIdentifier cryptlib_algorithm_blowfish_CFB = cryptlib_algorithm.branch("1.3"); + ASN1ObjectIdentifier cryptlib_algorithm_blowfish_OFB = cryptlib_algorithm.branch("1.4"); + + // + // Blake2b + // + ASN1ObjectIdentifier blake2 = new ASN1ObjectIdentifier("1.3.6.1.4.1.1722.12.2"); + + ASN1ObjectIdentifier id_blake2b160 = blake2.branch("1.5"); + ASN1ObjectIdentifier id_blake2b256 = blake2.branch("1.8"); + ASN1ObjectIdentifier id_blake2b384 = blake2.branch("1.12"); + ASN1ObjectIdentifier id_blake2b512 = blake2.branch("1.16"); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java index ba7e5187..19077e4c 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java @@ -17,42 +17,38 @@ public class NISTNamedCurves static final Hashtable objIds = new Hashtable(); static final Hashtable names = new Hashtable(); - static void defineCurve(String name, ASN1ObjectIdentifier oid) + static void defineCurveAlias(String name, ASN1ObjectIdentifier oid) { - objIds.put(name, oid); + objIds.put(name.toUpperCase(), oid); names.put(oid, name); } static { - defineCurve("B-571", SECObjectIdentifiers.sect571r1); - defineCurve("B-409", SECObjectIdentifiers.sect409r1); - defineCurve("B-283", SECObjectIdentifiers.sect283r1); - defineCurve("B-233", SECObjectIdentifiers.sect233r1); - defineCurve("B-163", SECObjectIdentifiers.sect163r2); - defineCurve("K-571", SECObjectIdentifiers.sect571k1); - defineCurve("K-409", SECObjectIdentifiers.sect409k1); - defineCurve("K-283", SECObjectIdentifiers.sect283k1); - defineCurve("K-233", SECObjectIdentifiers.sect233k1); - defineCurve("K-163", SECObjectIdentifiers.sect163k1); - defineCurve("P-521", SECObjectIdentifiers.secp521r1); - defineCurve("P-384", SECObjectIdentifiers.secp384r1); - defineCurve("P-256", SECObjectIdentifiers.secp256r1); - defineCurve("P-224", SECObjectIdentifiers.secp224r1); - defineCurve("P-192", SECObjectIdentifiers.secp192r1); + defineCurveAlias("B-163", SECObjectIdentifiers.sect163r2); + defineCurveAlias("B-233", SECObjectIdentifiers.sect233r1); + defineCurveAlias("B-283", SECObjectIdentifiers.sect283r1); + defineCurveAlias("B-409", SECObjectIdentifiers.sect409r1); + defineCurveAlias("B-571", SECObjectIdentifiers.sect571r1); + + defineCurveAlias("K-163", SECObjectIdentifiers.sect163k1); + defineCurveAlias("K-233", SECObjectIdentifiers.sect233k1); + defineCurveAlias("K-283", SECObjectIdentifiers.sect283k1); + defineCurveAlias("K-409", SECObjectIdentifiers.sect409k1); + defineCurveAlias("K-571", SECObjectIdentifiers.sect571k1); + + defineCurveAlias("P-192", SECObjectIdentifiers.secp192r1); + defineCurveAlias("P-224", SECObjectIdentifiers.secp224r1); + defineCurveAlias("P-256", SECObjectIdentifiers.secp256r1); + defineCurveAlias("P-384", SECObjectIdentifiers.secp384r1); + defineCurveAlias("P-521", SECObjectIdentifiers.secp521r1); } public static X9ECParameters getByName( String name) { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toUpperCase(name)); - - if (oid != null) - { - return getByOID(oid); - } - - return null; + ASN1ObjectIdentifier oid = getOID(name); + return oid == null ? null : getByOID(oid); } /** @@ -94,6 +90,6 @@ public class NISTNamedCurves */ public static Enumeration getNames() { - return objIds.keys(); + return names.elements(); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java index e3613c68..0de40f20 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java @@ -31,6 +31,19 @@ public interface NISTObjectIdentifiers /** 2.16.840.1.101.3.4.2.6 */ static final ASN1ObjectIdentifier id_sha512_256 = hashAlgs.branch("6"); + /** 2.16.840.1.101.3.4.2.7 */ + static final ASN1ObjectIdentifier id_sha3_224 = hashAlgs.branch("7"); + /** 2.16.840.1.101.3.4.2.8 */ + static final ASN1ObjectIdentifier id_sha3_256 = hashAlgs.branch("8"); + /** 2.16.840.1.101.3.4.2.9 */ + static final ASN1ObjectIdentifier id_sha3_384 = hashAlgs.branch("9"); + /** 2.16.840.1.101.3.4.2.10 */ + static final ASN1ObjectIdentifier id_sha3_512 = hashAlgs.branch("10"); + /** 2.16.840.1.101.3.4.2.11 */ + static final ASN1ObjectIdentifier id_shake128 = hashAlgs.branch("11"); + /** 2.16.840.1.101.3.4.2.12 */ + static final ASN1ObjectIdentifier id_shake256 = hashAlgs.branch("12"); + /** 2.16.840.1.101.3.4.1 */ static final ASN1ObjectIdentifier aes = nistAlgorithm.branch("1"); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java index 06208731..747277c3 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java @@ -9,6 +9,9 @@ import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; +/** + * CRL Bag for PKCS#12 + */ public class CRLBag extends ASN1Object { @@ -44,12 +47,12 @@ public class CRLBag this.crlValue = crlValue; } - public ASN1ObjectIdentifier getcrlId() + public ASN1ObjectIdentifier getCrlId() { return crlId; } - public ASN1Encodable getCRLValue() + public ASN1Encodable getCrlValue() { return crlValue; } @@ -58,7 +61,7 @@ public class CRLBag * <pre> * CRLBag ::= SEQUENCE { * crlId BAG-TYPE.&id ({CRLTypes}), - * crlValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId}) + * crlValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId}) * } * * x509CRL BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java deleted file mode 100644 index db44a82a..00000000 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.bouncycastle.asn1.pkcs; - -import java.util.Enumeration; - -import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1Primitive; -import org.bouncycastle.asn1.ASN1Sequence; -import org.bouncycastle.asn1.DERSequence; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; - -/** - * @deprecated - use AlgorithmIdentifier and PBES2Parameters - */ -public class PBES2Algorithms - extends AlgorithmIdentifier implements PKCSObjectIdentifiers -{ - private ASN1ObjectIdentifier objectId; - private KeyDerivationFunc func; - private EncryptionScheme scheme; - - public PBES2Algorithms( - ASN1Sequence obj) - { - super(obj); - - Enumeration e = obj.getObjects(); - - objectId = (ASN1ObjectIdentifier)e.nextElement(); - - ASN1Sequence seq = (ASN1Sequence)e.nextElement(); - - e = seq.getObjects(); - - ASN1Sequence funcSeq = (ASN1Sequence)e.nextElement(); - - if (funcSeq.getObjectAt(0).equals(id_PBKDF2)) - { - func = new KeyDerivationFunc(id_PBKDF2, PBKDF2Params.getInstance(funcSeq.getObjectAt(1))); - } - else - { - func = KeyDerivationFunc.getInstance(funcSeq); - } - - scheme = EncryptionScheme.getInstance(e.nextElement()); - } - - public ASN1ObjectIdentifier getObjectId() - { - return objectId; - } - - public KeyDerivationFunc getKeyDerivationFunc() - { - return func; - } - - public EncryptionScheme getEncryptionScheme() - { - return scheme; - } - - public ASN1Primitive getASN1Primitive() - { - ASN1EncodableVector v = new ASN1EncodableVector(); - ASN1EncodableVector subV = new ASN1EncodableVector(); - - v.add(objectId); - - subV.add(func); - subV.add(scheme); - v.add(new DERSequence(subV)); - - return new DERSequence(v); - } -} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java index 92c4e8f1..6a6ad559 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java @@ -13,6 +13,7 @@ import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.util.Arrays; /** * <pre> @@ -31,19 +32,19 @@ public class PBKDF2Params { private static final AlgorithmIdentifier algid_hmacWithSHA1 = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA1, DERNull.INSTANCE); - private ASN1OctetString octStr; - private ASN1Integer iterationCount; - private ASN1Integer keyLength; - private AlgorithmIdentifier prf; + private final ASN1OctetString octStr; + private final ASN1Integer iterationCount; + private final ASN1Integer keyLength; + private final AlgorithmIdentifier prf; /** * Create PBKDF2Params from the passed in object, * - * @param obj either PBKDF2Params or an ASN2Sequence. + * @param obj either PBKDF2Params or an ASN1Sequence. * @return a PBKDF2Params instance. */ public static PBKDF2Params getInstance( - Object obj) + Object obj) { if (obj instanceof PBKDF2Params) { @@ -61,72 +62,77 @@ public class PBKDF2Params /** * Create a PBKDF2Params with the specified salt, iteration count, and algid-hmacWithSHA1 for the prf. * - * @param salt input salt. + * @param salt input salt. * @param iterationCount input iteration count. */ public PBKDF2Params( - byte[] salt, - int iterationCount) + byte[] salt, + int iterationCount) { - this.octStr = new DEROctetString(salt); - this.iterationCount = new ASN1Integer(iterationCount); + this(salt, iterationCount, 0); } /** * Create a PBKDF2Params with the specified salt, iteration count, keyLength, and algid-hmacWithSHA1 for the prf. * - * @param salt input salt. + * @param salt input salt. * @param iterationCount input iteration count. - * @param keyLength intended key length to be produced. + * @param keyLength intended key length to be produced. */ public PBKDF2Params( - byte[] salt, - int iterationCount, - int keyLength) + byte[] salt, + int iterationCount, + int keyLength) { - this(salt, iterationCount); - - this.keyLength = new ASN1Integer(keyLength); + this(salt, iterationCount, keyLength, null); } /** * Create a PBKDF2Params with the specified salt, iteration count, keyLength, and a defined prf. * - * @param salt input salt. + * @param salt input salt. * @param iterationCount input iteration count. - * @param keyLength intended key length to be produced. - * @param prf the pseudo-random function to use. + * @param keyLength intended key length to be produced. + * @param prf the pseudo-random function to use. */ public PBKDF2Params( - byte[] salt, - int iterationCount, - int keyLength, + byte[] salt, + int iterationCount, + int keyLength, AlgorithmIdentifier prf) { - this(salt, iterationCount); + this.octStr = new DEROctetString(Arrays.clone(salt)); + this.iterationCount = new ASN1Integer(iterationCount); + + if (keyLength > 0) + { + this.keyLength = new ASN1Integer(keyLength); + } + else + { + this.keyLength = null; + } - this.keyLength = new ASN1Integer(keyLength); this.prf = prf; } /** * Create a PBKDF2Params with the specified salt, iteration count, and a defined prf. * - * @param salt input salt. + * @param salt input salt. * @param iterationCount input iteration count. - * @param prf the pseudo-random function to use. + * @param prf the pseudo-random function to use. */ public PBKDF2Params( - byte[] salt, - int iterationCount, + byte[] salt, + int iterationCount, AlgorithmIdentifier prf) { - this(salt, iterationCount); - this.prf = prf; + this(salt, iterationCount, 0, prf); } private PBKDF2Params( - ASN1Sequence seq) + ASN1Sequence seq) { Enumeration e = seq.getObjects(); @@ -158,6 +164,15 @@ public class PBKDF2Params { prf = AlgorithmIdentifier.getInstance(o); } + else + { + prf = null; + } + } + else + { + keyLength = null; + prf = null; } } @@ -228,7 +243,7 @@ public class PBKDF2Params */ public ASN1Primitive toASN1Primitive() { - ASN1EncodableVector v = new ASN1EncodableVector(); + ASN1EncodableVector v = new ASN1EncodableVector(); v.add(octStr); v.add(iterationCount); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java index 82f1f94d..5dbddc3c 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java @@ -120,34 +120,34 @@ public interface PKCSObjectIdentifiers static final ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5"); /** 1.2.840.113549.2.7 */ - static final ASN1ObjectIdentifier id_hmacWithSHA1 = digestAlgorithm.branch("7"); + static final ASN1ObjectIdentifier id_hmacWithSHA1 = digestAlgorithm.branch("7").intern(); /** 1.2.840.113549.2.8 */ - static final ASN1ObjectIdentifier id_hmacWithSHA224 = digestAlgorithm.branch("8"); + static final ASN1ObjectIdentifier id_hmacWithSHA224 = digestAlgorithm.branch("8").intern(); /** 1.2.840.113549.2.9 */ - static final ASN1ObjectIdentifier id_hmacWithSHA256 = digestAlgorithm.branch("9"); + static final ASN1ObjectIdentifier id_hmacWithSHA256 = digestAlgorithm.branch("9").intern(); /** 1.2.840.113549.2.10 */ - static final ASN1ObjectIdentifier id_hmacWithSHA384 = digestAlgorithm.branch("10"); + static final ASN1ObjectIdentifier id_hmacWithSHA384 = digestAlgorithm.branch("10").intern(); /** 1.2.840.113549.2.11 */ - static final ASN1ObjectIdentifier id_hmacWithSHA512 = digestAlgorithm.branch("11"); + static final ASN1ObjectIdentifier id_hmacWithSHA512 = digestAlgorithm.branch("11").intern(); // // pkcs-7 OBJECT IDENTIFIER ::= { // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } // /** pkcs#7: 1.2.840.113549.1.7 */ - static final ASN1ObjectIdentifier pkcs_7 = new ASN1ObjectIdentifier("1.2.840.113549.1.7"); + static final ASN1ObjectIdentifier pkcs_7 = new ASN1ObjectIdentifier("1.2.840.113549.1.7").intern(); /** PKCS#7: 1.2.840.113549.1.7.1 */ - static final ASN1ObjectIdentifier data = new ASN1ObjectIdentifier("1.2.840.113549.1.7.1"); + static final ASN1ObjectIdentifier data = new ASN1ObjectIdentifier("1.2.840.113549.1.7.1").intern(); /** PKCS#7: 1.2.840.113549.1.7.2 */ - static final ASN1ObjectIdentifier signedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.2"); + static final ASN1ObjectIdentifier signedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.2").intern(); /** PKCS#7: 1.2.840.113549.1.7.3 */ - static final ASN1ObjectIdentifier envelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.3"); + static final ASN1ObjectIdentifier envelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.3").intern(); /** PKCS#7: 1.2.840.113549.1.7.4 */ - static final ASN1ObjectIdentifier signedAndEnvelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.4"); + static final ASN1ObjectIdentifier signedAndEnvelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.4").intern(); /** PKCS#7: 1.2.840.113549.1.7.5 */ - static final ASN1ObjectIdentifier digestedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.5"); + static final ASN1ObjectIdentifier digestedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.5").intern(); /** PKCS#7: 1.2.840.113549.1.7.76 */ - static final ASN1ObjectIdentifier encryptedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.6"); + static final ASN1ObjectIdentifier encryptedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.6").intern(); // // pkcs-9 OBJECT IDENTIFIER ::= { @@ -157,37 +157,37 @@ public interface PKCSObjectIdentifiers static final ASN1ObjectIdentifier pkcs_9 = new ASN1ObjectIdentifier("1.2.840.113549.1.9"); /** PKCS#9: 1.2.840.113549.1.9.1 */ - static final ASN1ObjectIdentifier pkcs_9_at_emailAddress = pkcs_9.branch("1"); + static final ASN1ObjectIdentifier pkcs_9_at_emailAddress = pkcs_9.branch("1").intern(); /** PKCS#9: 1.2.840.113549.1.9.2 */ - static final ASN1ObjectIdentifier pkcs_9_at_unstructuredName = pkcs_9.branch("2"); + static final ASN1ObjectIdentifier pkcs_9_at_unstructuredName = pkcs_9.branch("2").intern(); /** PKCS#9: 1.2.840.113549.1.9.3 */ - static final ASN1ObjectIdentifier pkcs_9_at_contentType = pkcs_9.branch("3"); + static final ASN1ObjectIdentifier pkcs_9_at_contentType = pkcs_9.branch("3").intern(); /** PKCS#9: 1.2.840.113549.1.9.4 */ - static final ASN1ObjectIdentifier pkcs_9_at_messageDigest = pkcs_9.branch("4"); + static final ASN1ObjectIdentifier pkcs_9_at_messageDigest = pkcs_9.branch("4").intern(); /** PKCS#9: 1.2.840.113549.1.9.5 */ - static final ASN1ObjectIdentifier pkcs_9_at_signingTime = pkcs_9.branch("5"); + static final ASN1ObjectIdentifier pkcs_9_at_signingTime = pkcs_9.branch("5").intern(); /** PKCS#9: 1.2.840.113549.1.9.6 */ - static final ASN1ObjectIdentifier pkcs_9_at_counterSignature = pkcs_9.branch("6"); + static final ASN1ObjectIdentifier pkcs_9_at_counterSignature = pkcs_9.branch("6").intern(); /** PKCS#9: 1.2.840.113549.1.9.7 */ - static final ASN1ObjectIdentifier pkcs_9_at_challengePassword = pkcs_9.branch("7"); + static final ASN1ObjectIdentifier pkcs_9_at_challengePassword = pkcs_9.branch("7").intern(); /** PKCS#9: 1.2.840.113549.1.9.8 */ - static final ASN1ObjectIdentifier pkcs_9_at_unstructuredAddress = pkcs_9.branch("8"); + static final ASN1ObjectIdentifier pkcs_9_at_unstructuredAddress = pkcs_9.branch("8").intern(); /** PKCS#9: 1.2.840.113549.1.9.9 */ - static final ASN1ObjectIdentifier pkcs_9_at_extendedCertificateAttributes = pkcs_9.branch("9"); + static final ASN1ObjectIdentifier pkcs_9_at_extendedCertificateAttributes = pkcs_9.branch("9").intern(); /** PKCS#9: 1.2.840.113549.1.9.13 */ - static final ASN1ObjectIdentifier pkcs_9_at_signingDescription = pkcs_9.branch("13"); + static final ASN1ObjectIdentifier pkcs_9_at_signingDescription = pkcs_9.branch("13").intern(); /** PKCS#9: 1.2.840.113549.1.9.14 */ - static final ASN1ObjectIdentifier pkcs_9_at_extensionRequest = pkcs_9.branch("14"); + static final ASN1ObjectIdentifier pkcs_9_at_extensionRequest = pkcs_9.branch("14").intern(); /** PKCS#9: 1.2.840.113549.1.9.15 */ - static final ASN1ObjectIdentifier pkcs_9_at_smimeCapabilities = pkcs_9.branch("15"); + static final ASN1ObjectIdentifier pkcs_9_at_smimeCapabilities = pkcs_9.branch("15").intern(); /** PKCS#9: 1.2.840.113549.1.9.16 */ - static final ASN1ObjectIdentifier id_smime = pkcs_9.branch("16"); + static final ASN1ObjectIdentifier id_smime = pkcs_9.branch("16").intern(); /** PKCS#9: 1.2.840.113549.1.9.20 */ - static final ASN1ObjectIdentifier pkcs_9_at_friendlyName = pkcs_9.branch("20"); + static final ASN1ObjectIdentifier pkcs_9_at_friendlyName = pkcs_9.branch("20").intern(); /** PKCS#9: 1.2.840.113549.1.9.21 */ - static final ASN1ObjectIdentifier pkcs_9_at_localKeyId = pkcs_9.branch("21"); + static final ASN1ObjectIdentifier pkcs_9_at_localKeyId = pkcs_9.branch("21").intern(); /** PKCS#9: 1.2.840.113549.1.9.22.1 * @deprecated use x509Certificate instead */ @@ -196,14 +196,19 @@ public interface PKCSObjectIdentifiers /** PKCS#9: 1.2.840.113549.1.9.22 */ static final ASN1ObjectIdentifier certTypes = pkcs_9.branch("22"); /** PKCS#9: 1.2.840.113549.1.9.22.1 */ - static final ASN1ObjectIdentifier x509Certificate = certTypes.branch("1"); + static final ASN1ObjectIdentifier x509Certificate = certTypes.branch("1").intern(); /** PKCS#9: 1.2.840.113549.1.9.22.2 */ - static final ASN1ObjectIdentifier sdsiCertificate = certTypes.branch("2"); + static final ASN1ObjectIdentifier sdsiCertificate = certTypes.branch("2").intern(); /** PKCS#9: 1.2.840.113549.1.9.23 */ static final ASN1ObjectIdentifier crlTypes = pkcs_9.branch("23"); /** PKCS#9: 1.2.840.113549.1.9.23.1 */ - static final ASN1ObjectIdentifier x509Crl = crlTypes.branch("1"); + static final ASN1ObjectIdentifier x509Crl = crlTypes.branch("1").intern(); + + /** RFC 6211 - id-aa-cmsAlgorithmProtect OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) + pkcs9(9) 52 } */ + ASN1ObjectIdentifier id_aa_cmsAlgorithmProtect = pkcs_9.branch("52").intern(); // // SMIME capability sub oids. @@ -238,6 +243,17 @@ public interface PKCSObjectIdentifiers static final ASN1ObjectIdentifier id_alg = id_smime.branch("3"); /** PKCS#9: 1.2.840.113549.1.9.16.3.9 */ static final ASN1ObjectIdentifier id_alg_PWRI_KEK = id_alg.branch("9"); + /** + * <pre> + * -- RSA-KEM Key Transport Algorithm + * + * id-rsa-kem OID ::= { + * iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) + * pkcs-9(9) smime(16) alg(3) 14 + * } + * </pre> + */ + static final ASN1ObjectIdentifier id_rsa_KEM = id_alg.branch("14"); // // id-cti OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840) @@ -392,5 +408,9 @@ public interface PKCSObjectIdentifiers static final ASN1ObjectIdentifier id_alg_CMS3DESwrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.6"); /** PKCS#9: 1.2.840.113549.1.9.16.3.7 */ static final ASN1ObjectIdentifier id_alg_CMSRC2wrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7"); + /** PKCS#9: 1.2.840.113549.1.9.16.3.5 */ + static final ASN1ObjectIdentifier id_alg_ESDH = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.5"); + /** PKCS#9: 1.2.840.113549.1.9.16.3.10 */ + static final ASN1ObjectIdentifier id_alg_SSDH = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.10"); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java index ed7a8d82..1cdaf129 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java @@ -7,9 +7,9 @@ import java.util.Hashtable; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ECParametersHolder; +import org.bouncycastle.asn1.x9.X9ECPoint; import org.bouncycastle.math.ec.ECConstants; import org.bouncycastle.math.ec.ECCurve; -import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism; import org.bouncycastle.math.ec.endo.GLVTypeBParameters; import org.bouncycastle.util.Strings; @@ -51,7 +51,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "09487239995A5EE76B55F9C2F098")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "09487239995A5EE76B55F9C2F098" + "A89CE5AF8724C0A23E0E0FF77500")); @@ -77,7 +77,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "4BA30AB5E892B4E1649DD0928643")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "4BA30AB5E892B4E1649DD0928643" + "ADCD46F5882E3747DEF36E956E97")); @@ -103,7 +103,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "161FF7528B899B2D0C28607CA52C5B86")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "161FF7528B899B2D0C28607CA52C5B86" + "CF5AC8395BAFEB13C02DA292DDED7A83")); @@ -129,7 +129,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "7B6AA5D85E572983E6FB32A7CDEBC140")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "7B6AA5D85E572983E6FB32A7CDEBC140" + "27B6916A894D3AEE7106FE805FC34B44")); @@ -168,7 +168,7 @@ public class SECNamedCurves ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv); // ECPoint G = curve.decodePoint(Hex.decode("02" // + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB" + "938CF935318FDCED6BC28286531733C3F03C4FEE")); @@ -194,7 +194,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "4A96B5688EF573284664698968C38BB913CBFC82")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "4A96B5688EF573284664698968C38BB913CBFC82" + "23A628553168947D59DCC912042351377AC5FB32")); @@ -220,7 +220,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "52DCB034293A117E1F4FF11B30F7199D3144CE6D" + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E")); @@ -259,7 +259,7 @@ public class SECNamedCurves ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D" + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D")); @@ -285,7 +285,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")); @@ -324,7 +324,7 @@ public class SECNamedCurves ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C" + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5")); @@ -350,7 +350,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")); @@ -389,7 +389,7 @@ public class SECNamedCurves ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")); @@ -415,7 +415,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")); @@ -441,7 +441,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7" + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")); @@ -468,7 +468,7 @@ public class SECNamedCurves //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650")); @@ -495,7 +495,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "009D73616F35F4AB1407D73562C10F")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "009D73616F35F4AB1407D73562C10F" + "00A52830277958EE84D1315ED31886")); @@ -522,7 +522,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "01A57A6A7B26CA5EF52FCDB8164797")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "01A57A6A7B26CA5EF52FCDB8164797" + "00B3ADC94ED1FE674C06E695BABA1D")); @@ -551,7 +551,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "0081BAF91FDF9833C40F9C181343638399")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "0081BAF91FDF9833C40F9C181343638399" + "078C6E7EA38C001F73C8134B1B4EF9E150")); @@ -580,7 +580,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "0356DCD8F2F95031AD652D23951BB366A8")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "0356DCD8F2F95031AD652D23951BB366A8" + "0648F06D867940A5366D9E265DE9EB240F")); @@ -609,7 +609,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8" + "0289070FB05D38FF58321F2E800536D538CCDAA3D9")); @@ -638,7 +638,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "0369979697AB43897789566789567F787A7876A654")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "0369979697AB43897789566789567F787A7876A654" + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883")); @@ -667,7 +667,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "03F0EBA16286A2D57EA0991168D4994637E8343E36")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "03F0EBA16286A2D57EA0991168D4994637E8343E36" + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1")); @@ -694,7 +694,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1" + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05")); @@ -721,7 +721,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F" + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C")); @@ -748,7 +748,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126" + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3")); @@ -775,7 +775,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B" + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052")); @@ -802,7 +802,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC" + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA")); @@ -831,7 +831,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836" + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259")); @@ -860,7 +860,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053" + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4")); @@ -887,7 +887,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746" + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B")); @@ -914,7 +914,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7" + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706")); @@ -943,7 +943,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972" + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3")); @@ -972,7 +972,7 @@ public class SECNamedCurves ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19")); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19" + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B")); @@ -987,7 +987,7 @@ public class SECNamedCurves static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder) { - objIds.put(name, oid); + objIds.put(name.toLowerCase(), oid); names.put(oid, name); curves.put(oid, holder); } @@ -1033,14 +1033,8 @@ public class SECNamedCurves public static X9ECParameters getByName( String name) { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name)); - - if (oid != null) - { - return getByOID(oid); - } - - return null; + ASN1ObjectIdentifier oid = getOID(name); + return oid == null ? null : getByOID(oid); } /** @@ -1053,13 +1047,7 @@ public class SECNamedCurves ASN1ObjectIdentifier oid) { X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid); - - if (holder != null) - { - return holder.getParameters(); - } - - return null; + return holder == null ? null : holder.getParameters(); } /** @@ -1089,6 +1077,6 @@ public class SECNamedCurves */ public static Enumeration getNames() { - return objIds.keys(); + return names.elements(); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java index fb60aca6..1ddc17d0 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java @@ -84,4 +84,25 @@ public interface SECObjectIdentifiers /** secp256r1 OID: 1.3.132.0.prime256v1 */ static final ASN1ObjectIdentifier secp256r1 = X9ObjectIdentifiers.prime256v1; + static final ASN1ObjectIdentifier secg_scheme = new ASN1ObjectIdentifier("1.3.132.1"); + + static final ASN1ObjectIdentifier dhSinglePass_stdDH_sha224kdf_scheme = secg_scheme.branch("11.0"); + static final ASN1ObjectIdentifier dhSinglePass_stdDH_sha256kdf_scheme = secg_scheme.branch("11.1"); + static final ASN1ObjectIdentifier dhSinglePass_stdDH_sha384kdf_scheme = secg_scheme.branch("11.2"); + static final ASN1ObjectIdentifier dhSinglePass_stdDH_sha512kdf_scheme = secg_scheme.branch("11.3"); + + static final ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha224kdf_scheme = secg_scheme.branch("14.0"); + static final ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha256kdf_scheme = secg_scheme.branch("14.1"); + static final ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha384kdf_scheme = secg_scheme.branch("14.2"); + static final ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha512kdf_scheme = secg_scheme.branch("14.3"); + + static final ASN1ObjectIdentifier mqvSinglePass_sha224kdf_scheme = secg_scheme.branch("15.0"); + static final ASN1ObjectIdentifier mqvSinglePass_sha256kdf_scheme = secg_scheme.branch("15.1"); + static final ASN1ObjectIdentifier mqvSinglePass_sha384kdf_scheme = secg_scheme.branch("15.2"); + static final ASN1ObjectIdentifier mqvSinglePass_sha512kdf_scheme = secg_scheme.branch("15.3"); + + static final ASN1ObjectIdentifier mqvFull_sha224kdf_scheme = secg_scheme.branch("16.0"); + static final ASN1ObjectIdentifier mqvFull_sha256kdf_scheme = secg_scheme.branch("16.1"); + static final ASN1ObjectIdentifier mqvFull_sha384kdf_scheme = secg_scheme.branch("16.2"); + static final ASN1ObjectIdentifier mqvFull_sha512kdf_scheme = secg_scheme.branch("16.3"); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java b/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java index 8a454f27..1330d256 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java @@ -3,6 +3,7 @@ package org.bouncycastle.asn1.util; import java.io.IOException; import java.util.Enumeration; +import org.bouncycastle.asn1.ASN1ApplicationSpecific; import org.bouncycastle.asn1.ASN1Boolean; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Enumerated; @@ -25,13 +26,16 @@ import org.bouncycastle.asn1.DERApplicationSpecific; import org.bouncycastle.asn1.DERBMPString; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERExternal; +import org.bouncycastle.asn1.DERGraphicString; import org.bouncycastle.asn1.DERIA5String; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERPrintableString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERT61String; import org.bouncycastle.asn1.DERUTF8String; +import org.bouncycastle.asn1.DERVideotexString; import org.bouncycastle.asn1.DERVisibleString; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; public class ASN1Dump @@ -50,7 +54,7 @@ public class ASN1Dump ASN1Primitive obj, StringBuffer buf) { - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); if (obj instanceof ASN1Sequence) { Enumeration e = ((ASN1Sequence)obj).getObjects(); @@ -237,6 +241,14 @@ public class ASN1Dump { buf.append(indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl); } + else if (obj instanceof DERGraphicString) + { + buf.append(indent + "GraphicString(" + ((DERGraphicString)obj).getString() + ") " + nl); + } + else if (obj instanceof DERVideotexString) + { + buf.append(indent + "VideotexString(" + ((DERVideotexString)obj).getString() + ") " + nl); + } else if (obj instanceof ASN1UTCTime) { buf.append(indent + "UTCTime(" + ((ASN1UTCTime)obj).getTime() + ") " + nl); @@ -286,7 +298,7 @@ public class ASN1Dump private static String outputApplicationSpecific(String type, String indent, boolean verbose, ASN1Primitive obj, String nl) { - DERApplicationSpecific app = (DERApplicationSpecific)obj; + ASN1ApplicationSpecific app = ASN1ApplicationSpecific.getInstance(obj); StringBuffer buf = new StringBuffer(); if (app.isConstructed()) @@ -353,7 +365,7 @@ public class ASN1Dump private static String dumpBinaryDataAsString(String indent, byte[] bytes) { - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); StringBuffer buf = new StringBuffer(); indent += TAB; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java index 7f283f97..b4b2bd43 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java @@ -8,6 +8,9 @@ import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERSequence; +/** + * Holding class for the AttributeTypeAndValue structures that make up an RDN. + */ public class AttributeTypeAndValue extends ASN1Object { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/DirectoryString.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/DirectoryString.java index cf7563e2..39312dec 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/DirectoryString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/DirectoryString.java @@ -12,6 +12,9 @@ import org.bouncycastle.asn1.DERT61String; import org.bouncycastle.asn1.DERUTF8String; import org.bouncycastle.asn1.DERUniversalString; +/** + * The DirectoryString CHOICE object. + */ public class DirectoryString extends ASN1Object implements ASN1Choice, ASN1String diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/RDN.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/RDN.java index f51c2619..6a1b318f 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/RDN.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/RDN.java @@ -9,6 +9,9 @@ import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERSet; +/** + * Holding class for a single Relative Distinguished Name (RDN). + */ public class RDN extends ASN1Object { @@ -105,12 +108,12 @@ public class RDN * <pre> * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue - + * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * </pre> - * @return this object as an ASN1Primitive type + * @return this object as its ASN1Primitive type */ public ASN1Primitive toASN1Primitive() { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500Name.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500Name.java index 50e57c51..67c5cd1c 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500Name.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500Name.java @@ -13,6 +13,7 @@ import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x500.style.BCStyle; /** + * The X.500 Name object. * <pre> * Name ::= CHOICE { * RDNSequence } @@ -38,6 +39,9 @@ public class X500Name private X500NameStyle style; private RDN[] rdns; + /** + * @deprecated use the getInstance() method that takes a style. + */ public X500Name(X500NameStyle style, X500Name name) { this.rdns = name.rdns; @@ -80,7 +84,7 @@ public class X500Name { if (obj instanceof X500Name) { - return getInstance(style, ((X500Name)obj).toASN1Primitive()); + return new X500Name(style, (X500Name)obj); } else if (obj != null) { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500NameBuilder.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500NameBuilder.java index 7c9506a9..d019aaac 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500NameBuilder.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500NameBuilder.java @@ -6,21 +6,39 @@ import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x500.style.BCStyle; +/** + * A builder class for making X.500 Name objects. + */ public class X500NameBuilder { private X500NameStyle template; private Vector rdns = new Vector(); + /** + * Constructor using the default style (BCStyle). + */ public X500NameBuilder() { this(BCStyle.INSTANCE); } + /** + * Constructor using a specified style. + * + * @param template the style template for string to DN conversion. + */ public X500NameBuilder(X500NameStyle template) { this.template = template; } + /** + * Add an RDN based on a single OID and a string representation of its value. + * + * @param oid the OID for this RDN. + * @param value the string representation of the value the OID refers to. + * @return the current builder instance. + */ public X500NameBuilder addRDN(ASN1ObjectIdentifier oid, String value) { this.addRDN(oid, template.stringToValue(oid, value)); @@ -28,6 +46,13 @@ public class X500NameBuilder return this; } + /** + * Add an RDN based on a single OID and an ASN.1 value. + * + * @param oid the OID for this RDN. + * @param value the ASN.1 value the OID refers to. + * @return the current builder instance. + */ public X500NameBuilder addRDN(ASN1ObjectIdentifier oid, ASN1Encodable value) { rdns.addElement(new RDN(oid, value)); @@ -35,6 +60,12 @@ public class X500NameBuilder return this; } + /** + * Add an RDN based on the passed in AttributeTypeAndValue. + * + * @param attrTAndV the AttributeTypeAndValue to build the RDN from. + * @return the current builder instance. + */ public X500NameBuilder addRDN(AttributeTypeAndValue attrTAndV) { rdns.addElement(new RDN(attrTAndV)); @@ -42,6 +73,13 @@ public class X500NameBuilder return this; } + /** + * Add a multi-valued RDN made up of the passed in OIDs and associated string values. + * + * @param oids the OIDs making up the RDN. + * @param values the string representation of the values the OIDs refer to. + * @return the current builder instance. + */ public X500NameBuilder addMultiValuedRDN(ASN1ObjectIdentifier[] oids, String[] values) { ASN1Encodable[] vals = new ASN1Encodable[values.length]; @@ -54,6 +92,13 @@ public class X500NameBuilder return addMultiValuedRDN(oids, vals); } + /** + * Add a multi-valued RDN made up of the passed in OIDs and associated ASN.1 values. + * + * @param oids the OIDs making up the RDN. + * @param values the ASN.1 values the OIDs refer to. + * @return the current builder instance. + */ public X500NameBuilder addMultiValuedRDN(ASN1ObjectIdentifier[] oids, ASN1Encodable[] values) { AttributeTypeAndValue[] avs = new AttributeTypeAndValue[oids.length]; @@ -66,6 +111,12 @@ public class X500NameBuilder return addMultiValuedRDN(avs); } + /** + * Add an RDN based on the passed in AttributeTypeAndValues. + * + * @param attrTAndVs the AttributeTypeAndValues to build the RDN from. + * @return the current builder instance. + */ public X500NameBuilder addMultiValuedRDN(AttributeTypeAndValue[] attrTAndVs) { rdns.addElement(new RDN(attrTAndVs)); @@ -73,6 +124,11 @@ public class X500NameBuilder return this; } + /** + * Build an X.500 name for the current builder state. + * + * @return a new X.500 name. + */ public X500Name build() { RDN[] vals = new RDN[rdns.size()]; @@ -84,4 +140,4 @@ public class X500NameBuilder return new X500Name(template, vals); } -} +}
\ No newline at end of file diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500NameStyle.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500NameStyle.java index 704ea72e..8a87fb43 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500NameStyle.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500NameStyle.java @@ -4,11 +4,11 @@ import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1ObjectIdentifier; /** - * It turns out that the number of standard ways the fields in a DN should be - * encoded into their ASN.1 counterparts is rapidly approaching the - * number of machines on the internet. By default the X500Name class - * will produce UTF8Strings in line with the current recommendations (RFC 3280). - * <p> + * This interface provides a profile to conform to when + * DNs are being converted into strings and back. The idea being that we'll be able to deal with + * the number of standard ways the fields in a DN should be + * encoded into their ASN.1 counterparts - a number that is rapidly approaching the + * number of machines on the internet. */ public interface X500NameStyle { @@ -76,4 +76,4 @@ public interface X500NameStyle * @return an array of String aliases for the OID, zero length if there are none. */ String[] oidToAttrNames(ASN1ObjectIdentifier oid); -} +}
\ No newline at end of file diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java index 9792d40e..a97b17d2 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java @@ -6,6 +6,7 @@ import java.util.Hashtable; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1ParsingException; import org.bouncycastle.asn1.DERUTF8String; import org.bouncycastle.asn1.x500.AttributeTypeAndValue; import org.bouncycastle.asn1.x500.RDN; @@ -101,7 +102,7 @@ public abstract class AbstractX500NameStyle } catch (IOException e) { - throw new RuntimeException("can't recode value for oid " + oid.getId()); + throw new ASN1ParsingException("can't recode value for oid " + oid.getId()); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java index 1c2a9269..34b43856 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java @@ -19,37 +19,37 @@ public class BCStyle /** * country code - StringType(SIZE(2)) */ - public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6"); + public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6").intern(); /** * organization - StringType(SIZE(1..64)) */ - public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10"); + public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10").intern(); /** * organizational unit name - StringType(SIZE(1..64)) */ - public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11"); + public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11").intern(); /** * Title */ - public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12"); + public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12").intern(); /** * common name - StringType(SIZE(1..64)) */ - public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3"); + public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3").intern(); /** * device serial number name - StringType(SIZE(1..64)) */ - public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5"); + public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5").intern(); /** * street - StringType(SIZE(1..64)) */ - public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9"); + public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9").intern(); /** * device serial number name - StringType(SIZE(1..64)) @@ -59,95 +59,95 @@ public class BCStyle /** * locality name - StringType(SIZE(1..64)) */ - public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7"); + public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7").intern(); /** * state, or province name - StringType(SIZE(1..64)) */ - public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8"); + public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8").intern(); /** * Naming attributes of type X520name */ - public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4"); - public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42"); - public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43"); - public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44"); - public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45"); + public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4").intern(); + public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42").intern(); + public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43").intern(); + public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44").intern(); + public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45").intern(); /** * businessCategory - DirectoryString(SIZE(1..128) */ public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier( - "2.5.4.15"); + "2.5.4.15").intern(); /** * postalCode - DirectoryString(SIZE(1..40) */ public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier( - "2.5.4.17"); + "2.5.4.17").intern(); /** * dnQualifier - DirectoryString(SIZE(1..64) */ public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier( - "2.5.4.46"); + "2.5.4.46").intern(); /** * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64) */ public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier( - "2.5.4.65"); + "2.5.4.65").intern(); /** * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z */ public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.1"); + "1.3.6.1.5.5.7.9.1").intern(); /** * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128) */ public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.2"); + "1.3.6.1.5.5.7.9.2").intern(); /** * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f" */ public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.3"); + "1.3.6.1.5.5.7.9.3").intern(); /** * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166 * codes only */ public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.4"); + "1.3.6.1.5.5.7.9.4").intern(); /** * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166 * codes only */ public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.5"); + "1.3.6.1.5.5.7.9.5").intern(); /** * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64) */ - public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14"); + public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14").intern(); /** * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF * DirectoryString(SIZE(1..30)) */ - public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16"); + public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16").intern(); /** * RFC 2256 dmdName */ - public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54"); + public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54").intern(); /** * id-at-telephoneNumber diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java index 13f6ef1e..2a40fb03 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java @@ -13,49 +13,49 @@ import org.bouncycastle.asn1.x500.X500NameStyle; public class RFC4519Style extends AbstractX500NameStyle { - public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15"); - public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6"); - public static final ASN1ObjectIdentifier cn = new ASN1ObjectIdentifier("2.5.4.3"); - public static final ASN1ObjectIdentifier dc = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25"); - public static final ASN1ObjectIdentifier description = new ASN1ObjectIdentifier("2.5.4.13"); - public static final ASN1ObjectIdentifier destinationIndicator = new ASN1ObjectIdentifier("2.5.4.27"); - public static final ASN1ObjectIdentifier distinguishedName = new ASN1ObjectIdentifier("2.5.4.49"); - public static final ASN1ObjectIdentifier dnQualifier = new ASN1ObjectIdentifier("2.5.4.46"); - public static final ASN1ObjectIdentifier enhancedSearchGuide = new ASN1ObjectIdentifier("2.5.4.47"); - public static final ASN1ObjectIdentifier facsimileTelephoneNumber = new ASN1ObjectIdentifier("2.5.4.23"); - public static final ASN1ObjectIdentifier generationQualifier = new ASN1ObjectIdentifier("2.5.4.44"); - public static final ASN1ObjectIdentifier givenName = new ASN1ObjectIdentifier("2.5.4.42"); - public static final ASN1ObjectIdentifier houseIdentifier = new ASN1ObjectIdentifier("2.5.4.51"); - public static final ASN1ObjectIdentifier initials = new ASN1ObjectIdentifier("2.5.4.43"); - public static final ASN1ObjectIdentifier internationalISDNNumber = new ASN1ObjectIdentifier("2.5.4.25"); - public static final ASN1ObjectIdentifier l = new ASN1ObjectIdentifier("2.5.4.7"); - public static final ASN1ObjectIdentifier member = new ASN1ObjectIdentifier("2.5.4.31"); - public static final ASN1ObjectIdentifier name = new ASN1ObjectIdentifier("2.5.4.41"); - public static final ASN1ObjectIdentifier o = new ASN1ObjectIdentifier("2.5.4.10"); - public static final ASN1ObjectIdentifier ou = new ASN1ObjectIdentifier("2.5.4.11"); - public static final ASN1ObjectIdentifier owner = new ASN1ObjectIdentifier("2.5.4.32"); - public static final ASN1ObjectIdentifier physicalDeliveryOfficeName = new ASN1ObjectIdentifier("2.5.4.19"); - public static final ASN1ObjectIdentifier postalAddress = new ASN1ObjectIdentifier("2.5.4.16"); - public static final ASN1ObjectIdentifier postalCode = new ASN1ObjectIdentifier("2.5.4.17"); - public static final ASN1ObjectIdentifier postOfficeBox = new ASN1ObjectIdentifier("2.5.4.18"); - public static final ASN1ObjectIdentifier preferredDeliveryMethod = new ASN1ObjectIdentifier("2.5.4.28"); - public static final ASN1ObjectIdentifier registeredAddress = new ASN1ObjectIdentifier("2.5.4.26"); - public static final ASN1ObjectIdentifier roleOccupant = new ASN1ObjectIdentifier("2.5.4.33"); - public static final ASN1ObjectIdentifier searchGuide = new ASN1ObjectIdentifier("2.5.4.14"); - public static final ASN1ObjectIdentifier seeAlso = new ASN1ObjectIdentifier("2.5.4.34"); - public static final ASN1ObjectIdentifier serialNumber = new ASN1ObjectIdentifier("2.5.4.5"); - public static final ASN1ObjectIdentifier sn = new ASN1ObjectIdentifier("2.5.4.4"); - public static final ASN1ObjectIdentifier st = new ASN1ObjectIdentifier("2.5.4.8"); - public static final ASN1ObjectIdentifier street = new ASN1ObjectIdentifier("2.5.4.9"); - public static final ASN1ObjectIdentifier telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20"); - public static final ASN1ObjectIdentifier teletexTerminalIdentifier = new ASN1ObjectIdentifier("2.5.4.22"); - public static final ASN1ObjectIdentifier telexNumber = new ASN1ObjectIdentifier("2.5.4.21"); - public static final ASN1ObjectIdentifier title = new ASN1ObjectIdentifier("2.5.4.12"); - public static final ASN1ObjectIdentifier uid = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1"); - public static final ASN1ObjectIdentifier uniqueMember = new ASN1ObjectIdentifier("2.5.4.50"); - public static final ASN1ObjectIdentifier userPassword = new ASN1ObjectIdentifier("2.5.4.35"); - public static final ASN1ObjectIdentifier x121Address = new ASN1ObjectIdentifier("2.5.4.24"); - public static final ASN1ObjectIdentifier x500UniqueIdentifier = new ASN1ObjectIdentifier("2.5.4.45"); + public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15").intern(); + public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6").intern(); + public static final ASN1ObjectIdentifier cn = new ASN1ObjectIdentifier("2.5.4.3").intern(); + public static final ASN1ObjectIdentifier dc = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25").intern(); + public static final ASN1ObjectIdentifier description = new ASN1ObjectIdentifier("2.5.4.13").intern(); + public static final ASN1ObjectIdentifier destinationIndicator = new ASN1ObjectIdentifier("2.5.4.27").intern(); + public static final ASN1ObjectIdentifier distinguishedName = new ASN1ObjectIdentifier("2.5.4.49").intern(); + public static final ASN1ObjectIdentifier dnQualifier = new ASN1ObjectIdentifier("2.5.4.46").intern(); + public static final ASN1ObjectIdentifier enhancedSearchGuide = new ASN1ObjectIdentifier("2.5.4.47").intern(); + public static final ASN1ObjectIdentifier facsimileTelephoneNumber = new ASN1ObjectIdentifier("2.5.4.23").intern(); + public static final ASN1ObjectIdentifier generationQualifier = new ASN1ObjectIdentifier("2.5.4.44").intern(); + public static final ASN1ObjectIdentifier givenName = new ASN1ObjectIdentifier("2.5.4.42").intern(); + public static final ASN1ObjectIdentifier houseIdentifier = new ASN1ObjectIdentifier("2.5.4.51").intern(); + public static final ASN1ObjectIdentifier initials = new ASN1ObjectIdentifier("2.5.4.43").intern(); + public static final ASN1ObjectIdentifier internationalISDNNumber = new ASN1ObjectIdentifier("2.5.4.25").intern(); + public static final ASN1ObjectIdentifier l = new ASN1ObjectIdentifier("2.5.4.7").intern(); + public static final ASN1ObjectIdentifier member = new ASN1ObjectIdentifier("2.5.4.31").intern(); + public static final ASN1ObjectIdentifier name = new ASN1ObjectIdentifier("2.5.4.41").intern(); + public static final ASN1ObjectIdentifier o = new ASN1ObjectIdentifier("2.5.4.10").intern(); + public static final ASN1ObjectIdentifier ou = new ASN1ObjectIdentifier("2.5.4.11").intern(); + public static final ASN1ObjectIdentifier owner = new ASN1ObjectIdentifier("2.5.4.32").intern(); + public static final ASN1ObjectIdentifier physicalDeliveryOfficeName = new ASN1ObjectIdentifier("2.5.4.19").intern(); + public static final ASN1ObjectIdentifier postalAddress = new ASN1ObjectIdentifier("2.5.4.16").intern(); + public static final ASN1ObjectIdentifier postalCode = new ASN1ObjectIdentifier("2.5.4.17").intern(); + public static final ASN1ObjectIdentifier postOfficeBox = new ASN1ObjectIdentifier("2.5.4.18").intern(); + public static final ASN1ObjectIdentifier preferredDeliveryMethod = new ASN1ObjectIdentifier("2.5.4.28").intern(); + public static final ASN1ObjectIdentifier registeredAddress = new ASN1ObjectIdentifier("2.5.4.26").intern(); + public static final ASN1ObjectIdentifier roleOccupant = new ASN1ObjectIdentifier("2.5.4.33").intern(); + public static final ASN1ObjectIdentifier searchGuide = new ASN1ObjectIdentifier("2.5.4.14").intern(); + public static final ASN1ObjectIdentifier seeAlso = new ASN1ObjectIdentifier("2.5.4.34").intern(); + public static final ASN1ObjectIdentifier serialNumber = new ASN1ObjectIdentifier("2.5.4.5").intern(); + public static final ASN1ObjectIdentifier sn = new ASN1ObjectIdentifier("2.5.4.4").intern(); + public static final ASN1ObjectIdentifier st = new ASN1ObjectIdentifier("2.5.4.8").intern(); + public static final ASN1ObjectIdentifier street = new ASN1ObjectIdentifier("2.5.4.9").intern(); + public static final ASN1ObjectIdentifier telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20").intern(); + public static final ASN1ObjectIdentifier teletexTerminalIdentifier = new ASN1ObjectIdentifier("2.5.4.22").intern(); + public static final ASN1ObjectIdentifier telexNumber = new ASN1ObjectIdentifier("2.5.4.21").intern(); + public static final ASN1ObjectIdentifier title = new ASN1ObjectIdentifier("2.5.4.12").intern(); + public static final ASN1ObjectIdentifier uid = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1").intern(); + public static final ASN1ObjectIdentifier uniqueMember = new ASN1ObjectIdentifier("2.5.4.50").intern(); + public static final ASN1ObjectIdentifier userPassword = new ASN1ObjectIdentifier("2.5.4.35").intern(); + public static final ASN1ObjectIdentifier x121Address = new ASN1ObjectIdentifier("2.5.4.24").intern(); + public static final ASN1ObjectIdentifier x500UniqueIdentifier = new ASN1ObjectIdentifier("2.5.4.45").intern(); /** * default look up table translating OID values into their common symbols following diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java index bb90030c..54eaa329 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java @@ -7,15 +7,13 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; -import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERSequence; public class AlgorithmIdentifier extends ASN1Object { - private ASN1ObjectIdentifier objectId; + private ASN1ObjectIdentifier algorithm; private ASN1Encodable parameters; - private boolean parametersDefined = false; public static AlgorithmIdentifier getInstance( ASN1TaggedObject obj, @@ -23,60 +21,37 @@ public class AlgorithmIdentifier { return getInstance(ASN1Sequence.getInstance(obj, explicit)); } - + public static AlgorithmIdentifier getInstance( Object obj) { - if (obj== null || obj instanceof AlgorithmIdentifier) + if (obj instanceof AlgorithmIdentifier) { return (AlgorithmIdentifier)obj; } - - // TODO: delete - if (obj instanceof ASN1ObjectIdentifier) - { - return new AlgorithmIdentifier((ASN1ObjectIdentifier)obj); - } - - // TODO: delete - if (obj instanceof String) + else if (obj != null) { - return new AlgorithmIdentifier((String)obj); + return new AlgorithmIdentifier(ASN1Sequence.getInstance(obj)); } - return new AlgorithmIdentifier(ASN1Sequence.getInstance(obj)); + return null; } public AlgorithmIdentifier( - ASN1ObjectIdentifier objectId) - { - this.objectId = objectId; - } - - /** - * @deprecated use ASN1ObjectIdentifier - * @param objectId - */ - public AlgorithmIdentifier( - String objectId) + ASN1ObjectIdentifier algorithm) { - this.objectId = new ASN1ObjectIdentifier(objectId); + this.algorithm = algorithm; } public AlgorithmIdentifier( - ASN1ObjectIdentifier objectId, + ASN1ObjectIdentifier algorithm, ASN1Encodable parameters) { - parametersDefined = true; - this.objectId = objectId; + this.algorithm = algorithm; this.parameters = parameters; } - /** - * @deprecated use AlgorithmIdentifier.getInstance() - * @param seq - */ - public AlgorithmIdentifier( + private AlgorithmIdentifier( ASN1Sequence seq) { if (seq.size() < 1 || seq.size() > 2) @@ -84,12 +59,11 @@ public class AlgorithmIdentifier throw new IllegalArgumentException("Bad sequence size: " + seq.size()); } - - objectId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)); + + algorithm = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)); if (seq.size() == 2) { - parametersDefined = true; parameters = seq.getObjectAt(1); } else @@ -100,16 +74,7 @@ public class AlgorithmIdentifier public ASN1ObjectIdentifier getAlgorithm() { - return new ASN1ObjectIdentifier(objectId.getId()); - } - - /** - * @deprecated use getAlgorithm - * @return - */ - public ASN1ObjectIdentifier getObjectId() - { - return objectId; + return algorithm; } public ASN1Encodable getParameters() @@ -129,18 +94,11 @@ public class AlgorithmIdentifier { ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(objectId); + v.add(algorithm); - if (parametersDefined) + if (parameters != null) { - if (parameters != null) - { - v.add(parameters); - } - else - { - v.add(DERNull.INSTANCE); - } + v.add(parameters); } return new DERSequence(v); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java index 1ee6aa5a..dd3422f6 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java @@ -6,6 +6,7 @@ import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.util.Strings; public class CRLDistPoint extends ASN1Object @@ -84,7 +85,7 @@ public class CRLDistPoint public String toString() { StringBuffer buf = new StringBuffer(); - String sep = System.getProperty("line.separator"); + String sep = Strings.lineSeparator(); buf.append("CRLDistPoint:"); buf.append(sep); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java index ab73dfbb..48e5640d 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java @@ -8,6 +8,7 @@ import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.util.Strings; /** * The DistributionPoint object. @@ -121,7 +122,7 @@ public class DistributionPoint public String toString() { - String sep = System.getProperty("line.separator"); + String sep = Strings.lineSeparator(); StringBuffer buf = new StringBuffer(); buf.append("DistributionPoint: ["); buf.append(sep); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPointName.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPointName.java index ee06efdc..f69ccb3a 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPointName.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPointName.java @@ -7,6 +7,7 @@ import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.util.Strings; /** * The DistributionPointName object. @@ -105,7 +106,7 @@ public class DistributionPointName public String toString() { - String sep = System.getProperty("line.separator"); + String sep = Strings.lineSeparator(); StringBuffer buf = new StringBuffer(); buf.append("DistributionPointName: ["); buf.append(sep); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extension.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extension.java index 4d566b18..456e3d32 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extension.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extension.java @@ -22,157 +22,157 @@ public class Extension /** * Subject Directory Attributes */ - public static final ASN1ObjectIdentifier subjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9"); + public static final ASN1ObjectIdentifier subjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9").intern(); /** * Subject Key Identifier */ - public static final ASN1ObjectIdentifier subjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14"); + public static final ASN1ObjectIdentifier subjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14").intern(); /** * Key Usage */ - public static final ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier("2.5.29.15"); + public static final ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier("2.5.29.15").intern(); /** * Private Key Usage Period */ - public static final ASN1ObjectIdentifier privateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16"); + public static final ASN1ObjectIdentifier privateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16").intern(); /** * Subject Alternative Name */ - public static final ASN1ObjectIdentifier subjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17"); + public static final ASN1ObjectIdentifier subjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17").intern(); /** * Issuer Alternative Name */ - public static final ASN1ObjectIdentifier issuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18"); + public static final ASN1ObjectIdentifier issuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18").intern(); /** * Basic Constraints */ - public static final ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19"); + public static final ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19").intern(); /** * CRL Number */ - public static final ASN1ObjectIdentifier cRLNumber = new ASN1ObjectIdentifier("2.5.29.20"); + public static final ASN1ObjectIdentifier cRLNumber = new ASN1ObjectIdentifier("2.5.29.20").intern(); /** * Reason code */ - public static final ASN1ObjectIdentifier reasonCode = new ASN1ObjectIdentifier("2.5.29.21"); + public static final ASN1ObjectIdentifier reasonCode = new ASN1ObjectIdentifier("2.5.29.21").intern(); /** * Hold Instruction Code */ - public static final ASN1ObjectIdentifier instructionCode = new ASN1ObjectIdentifier("2.5.29.23"); + public static final ASN1ObjectIdentifier instructionCode = new ASN1ObjectIdentifier("2.5.29.23").intern(); /** * Invalidity Date */ - public static final ASN1ObjectIdentifier invalidityDate = new ASN1ObjectIdentifier("2.5.29.24"); + public static final ASN1ObjectIdentifier invalidityDate = new ASN1ObjectIdentifier("2.5.29.24").intern(); /** * Delta CRL indicator */ - public static final ASN1ObjectIdentifier deltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27"); + public static final ASN1ObjectIdentifier deltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27").intern(); /** * Issuing Distribution Point */ - public static final ASN1ObjectIdentifier issuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28"); + public static final ASN1ObjectIdentifier issuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28").intern(); /** * Certificate Issuer */ - public static final ASN1ObjectIdentifier certificateIssuer = new ASN1ObjectIdentifier("2.5.29.29"); + public static final ASN1ObjectIdentifier certificateIssuer = new ASN1ObjectIdentifier("2.5.29.29").intern(); /** * Name Constraints */ - public static final ASN1ObjectIdentifier nameConstraints = new ASN1ObjectIdentifier("2.5.29.30"); + public static final ASN1ObjectIdentifier nameConstraints = new ASN1ObjectIdentifier("2.5.29.30").intern(); /** * CRL Distribution Points */ - public static final ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31"); + public static final ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31").intern(); /** * Certificate Policies */ - public static final ASN1ObjectIdentifier certificatePolicies = new ASN1ObjectIdentifier("2.5.29.32"); + public static final ASN1ObjectIdentifier certificatePolicies = new ASN1ObjectIdentifier("2.5.29.32").intern(); /** * Policy Mappings */ - public static final ASN1ObjectIdentifier policyMappings = new ASN1ObjectIdentifier("2.5.29.33"); + public static final ASN1ObjectIdentifier policyMappings = new ASN1ObjectIdentifier("2.5.29.33").intern(); /** * Authority Key Identifier */ - public static final ASN1ObjectIdentifier authorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35"); + public static final ASN1ObjectIdentifier authorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35").intern(); /** * Policy Constraints */ - public static final ASN1ObjectIdentifier policyConstraints = new ASN1ObjectIdentifier("2.5.29.36"); + public static final ASN1ObjectIdentifier policyConstraints = new ASN1ObjectIdentifier("2.5.29.36").intern(); /** * Extended Key Usage */ - public static final ASN1ObjectIdentifier extendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37"); + public static final ASN1ObjectIdentifier extendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37").intern(); /** * Freshest CRL */ - public static final ASN1ObjectIdentifier freshestCRL = new ASN1ObjectIdentifier("2.5.29.46"); + public static final ASN1ObjectIdentifier freshestCRL = new ASN1ObjectIdentifier("2.5.29.46").intern(); /** * Inhibit Any Policy */ - public static final ASN1ObjectIdentifier inhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54"); + public static final ASN1ObjectIdentifier inhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54").intern(); /** * Authority Info Access */ - public static final ASN1ObjectIdentifier authorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1"); + public static final ASN1ObjectIdentifier authorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1").intern(); /** * Subject Info Access */ - public static final ASN1ObjectIdentifier subjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11"); + public static final ASN1ObjectIdentifier subjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11").intern(); /** * Logo Type */ - public static final ASN1ObjectIdentifier logoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12"); + public static final ASN1ObjectIdentifier logoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12").intern(); /** * BiometricInfo */ - public static final ASN1ObjectIdentifier biometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2"); + public static final ASN1ObjectIdentifier biometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2").intern(); /** * QCStatements */ - public static final ASN1ObjectIdentifier qCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3"); + public static final ASN1ObjectIdentifier qCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3").intern(); /** * Audit identity extension in attribute certificates. */ - public static final ASN1ObjectIdentifier auditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4"); + public static final ASN1ObjectIdentifier auditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4").intern(); /** * NoRevAvail extension in attribute certificates. */ - public static final ASN1ObjectIdentifier noRevAvail = new ASN1ObjectIdentifier("2.5.29.56"); + public static final ASN1ObjectIdentifier noRevAvail = new ASN1ObjectIdentifier("2.5.29.56").intern(); /** * TargetInformation extension in attribute certificates. */ - public static final ASN1ObjectIdentifier targetInformation = new ASN1ObjectIdentifier("2.5.29.55"); + public static final ASN1ObjectIdentifier targetInformation = new ASN1ObjectIdentifier("2.5.29.55").intern(); private ASN1ObjectIdentifier extnId; private boolean critical; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtensionsGenerator.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtensionsGenerator.java index 270ef1c4..d20e62f5 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtensionsGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtensionsGenerator.java @@ -66,6 +66,23 @@ public class ExtensionsGenerator } /** + * Add a given extension. + * + * @param extension the full extension value. + */ + public void addExtension( + Extension extension) + { + if (extensions.containsKey(extension.getExtnId())) + { + throw new IllegalArgumentException("extension " + extension.getExtnId() + " already added"); + } + + extOrdering.addElement(extension.getExtnId()); + extensions.put(extension.getExtnId(), extension); + } + + /** * Return true if there are no extension present in this generator. * * @return true if empty, false otherwise diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java index 7118d107..405f6e4e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java @@ -6,6 +6,7 @@ import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.util.Strings; public class GeneralNames extends ASN1Object @@ -92,7 +93,7 @@ public class GeneralNames public String toString() { StringBuffer buf = new StringBuffer(); - String sep = System.getProperty("line.separator"); + String sep = Strings.lineSeparator(); buf.append("GeneralNames:"); buf.append(sep); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java index 1f29162b..c24b788e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java @@ -8,6 +8,7 @@ import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.util.Strings; /** * <pre> @@ -219,7 +220,7 @@ public class IssuingDistributionPoint public String toString() { - String sep = System.getProperty("line.separator"); + String sep = Strings.lineSeparator(); StringBuffer buf = new StringBuffer(); buf.append("IssuingDistributionPoint: ["); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java index 01980bec..01c9aa2a 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java @@ -145,6 +145,11 @@ public class KeyPurposeId return null; } + public ASN1ObjectIdentifier toOID() + { + return id; + } + public ASN1Primitive toASN1Primitive() { return id; @@ -154,4 +159,9 @@ public class KeyPurposeId { return id.getId(); } + + public String toString() + { + return id.toString(); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraintValidator.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraintValidator.java new file mode 100644 index 00000000..4596fe0c --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraintValidator.java @@ -0,0 +1,18 @@ +package org.bouncycastle.asn1.x509; + +public interface NameConstraintValidator +{ + void checkPermitted(GeneralName name) + throws NameConstraintValidatorException; + + void checkExcluded(GeneralName name) + throws NameConstraintValidatorException; + + void intersectPermittedSubtree(GeneralSubtree permitted); + + void intersectPermittedSubtree(GeneralSubtree[] permitted); + + void intersectEmptyPermittedSubtree(int nameType); + + void addExcludedSubtree(GeneralSubtree subtree); +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraintValidatorException.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraintValidatorException.java new file mode 100644 index 00000000..517fddb0 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraintValidatorException.java @@ -0,0 +1,10 @@ +package org.bouncycastle.asn1.x509; + +public class NameConstraintValidatorException + extends Exception +{ + public NameConstraintValidatorException(String msg) + { + super(msg); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PKIXNameConstraintValidator.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PKIXNameConstraintValidator.java new file mode 100644 index 00000000..0f15dae1 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PKIXNameConstraintValidator.java @@ -0,0 +1,1920 @@ +package org.bouncycastle.asn1.x509; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERIA5String; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Integers; +import org.bouncycastle.util.Strings; + +public class PKIXNameConstraintValidator + implements NameConstraintValidator +{ + private Set excludedSubtreesDN = new HashSet(); + + private Set excludedSubtreesDNS = new HashSet(); + + private Set excludedSubtreesEmail = new HashSet(); + + private Set excludedSubtreesURI = new HashSet(); + + private Set excludedSubtreesIP = new HashSet(); + + private Set permittedSubtreesDN; + + private Set permittedSubtreesDNS; + + private Set permittedSubtreesEmail; + + private Set permittedSubtreesURI; + + private Set permittedSubtreesIP; + + public PKIXNameConstraintValidator() + { + } + + /** + * Checks if the given GeneralName is in the permitted set. + * + * @param name The GeneralName + * @throws NameConstraintValidatorException If the <code>name</code> + */ + public void checkPermitted(GeneralName name) + throws NameConstraintValidatorException + { + switch (name.getTagNo()) + { + case GeneralName.rfc822Name: + checkPermittedEmail(permittedSubtreesEmail, + extractNameAsString(name)); + break; + case GeneralName.dNSName: + checkPermittedDNS(permittedSubtreesDNS, DERIA5String.getInstance( + name.getName()).getString()); + break; + case GeneralName.directoryName: + checkPermittedDN(X500Name.getInstance(name.getName())); + break; + case GeneralName.uniformResourceIdentifier: + checkPermittedURI(permittedSubtreesURI, DERIA5String.getInstance( + name.getName()).getString()); + break; + case GeneralName.iPAddress: + byte[] ip = ASN1OctetString.getInstance(name.getName()).getOctets(); + + checkPermittedIP(permittedSubtreesIP, ip); + } + } + + /** + * Check if the given GeneralName is contained in the excluded set. + * + * @param name The GeneralName. + * @throws NameConstraintValidatorException If the <code>name</code> is + * excluded. + */ + public void checkExcluded(GeneralName name) + throws NameConstraintValidatorException + { + switch (name.getTagNo()) + { + case GeneralName.rfc822Name: + checkExcludedEmail(excludedSubtreesEmail, extractNameAsString(name)); + break; + case GeneralName.dNSName: + checkExcludedDNS(excludedSubtreesDNS, DERIA5String.getInstance( + name.getName()).getString()); + break; + case GeneralName.directoryName: + checkExcludedDN(X500Name.getInstance(name.getName())); + break; + case GeneralName.uniformResourceIdentifier: + checkExcludedURI(excludedSubtreesURI, DERIA5String.getInstance( + name.getName()).getString()); + break; + case GeneralName.iPAddress: + byte[] ip = ASN1OctetString.getInstance(name.getName()).getOctets(); + + checkExcludedIP(excludedSubtreesIP, ip); + } + } + + public void intersectPermittedSubtree(GeneralSubtree permitted) + { + intersectPermittedSubtree(new GeneralSubtree[]{permitted}); + } + + /** + * Updates the permitted set of these name constraints with the intersection + * with the given subtree. + * + * @param permitted The permitted subtrees + */ + public void intersectPermittedSubtree(GeneralSubtree[] permitted) + { + Map subtreesMap = new HashMap(); + + // group in sets in a map ordered by tag no. + for (int i = 0; i != permitted.length; i++) + { + GeneralSubtree subtree = permitted[i]; + Integer tagNo = Integers.valueOf(subtree.getBase().getTagNo()); + if (subtreesMap.get(tagNo) == null) + { + subtreesMap.put(tagNo, new HashSet()); + } + ((Set)subtreesMap.get(tagNo)).add(subtree); + } + + for (Iterator it = subtreesMap.entrySet().iterator(); it.hasNext(); ) + { + Map.Entry entry = (Map.Entry)it.next(); + + // go through all subtree groups + switch (((Integer)entry.getKey()).intValue()) + { + case GeneralName.rfc822Name: + permittedSubtreesEmail = intersectEmail(permittedSubtreesEmail, + (Set)entry.getValue()); + break; + case GeneralName.dNSName: + permittedSubtreesDNS = intersectDNS(permittedSubtreesDNS, + (Set)entry.getValue()); + break; + case GeneralName.directoryName: + permittedSubtreesDN = intersectDN(permittedSubtreesDN, + (Set)entry.getValue()); + break; + case GeneralName.uniformResourceIdentifier: + permittedSubtreesURI = intersectURI(permittedSubtreesURI, + (Set)entry.getValue()); + break; + case GeneralName.iPAddress: + permittedSubtreesIP = intersectIP(permittedSubtreesIP, + (Set)entry.getValue()); + } + } + } + + public void intersectEmptyPermittedSubtree(int nameType) + { + switch (nameType) + { + case GeneralName.rfc822Name: + permittedSubtreesEmail = new HashSet(); + break; + case GeneralName.dNSName: + permittedSubtreesDNS = new HashSet(); + break; + case GeneralName.directoryName: + permittedSubtreesDN = new HashSet(); + break; + case GeneralName.uniformResourceIdentifier: + permittedSubtreesURI = new HashSet(); + break; + case GeneralName.iPAddress: + permittedSubtreesIP = new HashSet(); + } + } + + /** + * Adds a subtree to the excluded set of these name constraints. + * + * @param subtree A subtree with an excluded GeneralName. + */ + public void addExcludedSubtree(GeneralSubtree subtree) + { + GeneralName base = subtree.getBase(); + + switch (base.getTagNo()) + { + case GeneralName.rfc822Name: + excludedSubtreesEmail = unionEmail(excludedSubtreesEmail, + extractNameAsString(base)); + break; + case GeneralName.dNSName: + excludedSubtreesDNS = unionDNS(excludedSubtreesDNS, + extractNameAsString(base)); + break; + case GeneralName.directoryName: + excludedSubtreesDN = unionDN(excludedSubtreesDN, + (ASN1Sequence)base.getName().toASN1Primitive()); + break; + case GeneralName.uniformResourceIdentifier: + excludedSubtreesURI = unionURI(excludedSubtreesURI, + extractNameAsString(base)); + break; + case GeneralName.iPAddress: + excludedSubtreesIP = unionIP(excludedSubtreesIP, ASN1OctetString + .getInstance(base.getName()).getOctets()); + break; + } + } + + public int hashCode() + { + return hashCollection(excludedSubtreesDN) + + hashCollection(excludedSubtreesDNS) + + hashCollection(excludedSubtreesEmail) + + hashCollection(excludedSubtreesIP) + + hashCollection(excludedSubtreesURI) + + hashCollection(permittedSubtreesDN) + + hashCollection(permittedSubtreesDNS) + + hashCollection(permittedSubtreesEmail) + + hashCollection(permittedSubtreesIP) + + hashCollection(permittedSubtreesURI); + } + + public boolean equals(Object o) + { + if (!(o instanceof PKIXNameConstraintValidator)) + { + return false; + } + PKIXNameConstraintValidator constraintValidator = (PKIXNameConstraintValidator)o; + return collectionsAreEqual(constraintValidator.excludedSubtreesDN, excludedSubtreesDN) + && collectionsAreEqual(constraintValidator.excludedSubtreesDNS, excludedSubtreesDNS) + && collectionsAreEqual(constraintValidator.excludedSubtreesEmail, excludedSubtreesEmail) + && collectionsAreEqual(constraintValidator.excludedSubtreesIP, excludedSubtreesIP) + && collectionsAreEqual(constraintValidator.excludedSubtreesURI, excludedSubtreesURI) + && collectionsAreEqual(constraintValidator.permittedSubtreesDN, permittedSubtreesDN) + && collectionsAreEqual(constraintValidator.permittedSubtreesDNS, permittedSubtreesDNS) + && collectionsAreEqual(constraintValidator.permittedSubtreesEmail, permittedSubtreesEmail) + && collectionsAreEqual(constraintValidator.permittedSubtreesIP, permittedSubtreesIP) + && collectionsAreEqual(constraintValidator.permittedSubtreesURI, permittedSubtreesURI); + } + + public String toString() + { + String temp = ""; + temp += "permitted:\n"; + if (permittedSubtreesDN != null) + { + temp += "DN:\n"; + temp += permittedSubtreesDN.toString() + "\n"; + } + if (permittedSubtreesDNS != null) + { + temp += "DNS:\n"; + temp += permittedSubtreesDNS.toString() + "\n"; + } + if (permittedSubtreesEmail != null) + { + temp += "Email:\n"; + temp += permittedSubtreesEmail.toString() + "\n"; + } + if (permittedSubtreesURI != null) + { + temp += "URI:\n"; + temp += permittedSubtreesURI.toString() + "\n"; + } + if (permittedSubtreesIP != null) + { + temp += "IP:\n"; + temp += stringifyIPCollection(permittedSubtreesIP) + "\n"; + } + temp += "excluded:\n"; + if (!excludedSubtreesDN.isEmpty()) + { + temp += "DN:\n"; + temp += excludedSubtreesDN.toString() + "\n"; + } + if (!excludedSubtreesDNS.isEmpty()) + { + temp += "DNS:\n"; + temp += excludedSubtreesDNS.toString() + "\n"; + } + if (!excludedSubtreesEmail.isEmpty()) + { + temp += "Email:\n"; + temp += excludedSubtreesEmail.toString() + "\n"; + } + if (!excludedSubtreesURI.isEmpty()) + { + temp += "URI:\n"; + temp += excludedSubtreesURI.toString() + "\n"; + } + if (!excludedSubtreesIP.isEmpty()) + { + temp += "IP:\n"; + temp += stringifyIPCollection(excludedSubtreesIP) + "\n"; + } + return temp; + } + + private void checkPermittedDN(X500Name dns) + throws NameConstraintValidatorException + { + checkPermittedDN(permittedSubtreesDN, ASN1Sequence.getInstance(dns.toASN1Primitive())); + } + + private void checkExcludedDN(X500Name dns) + throws NameConstraintValidatorException + { + checkExcludedDN(excludedSubtreesDN, ASN1Sequence.getInstance(dns)); + } + + private static boolean withinDNSubtree( + ASN1Sequence dns, + ASN1Sequence subtree) + { + if (subtree.size() < 1) + { + return false; + } + + if (subtree.size() > dns.size()) + { + return false; + } + + for (int j = subtree.size() - 1; j >= 0; j--) + { + if (!subtree.getObjectAt(j).equals(dns.getObjectAt(j))) + { + return false; + } + } + + return true; + } + + private void checkPermittedDN(Set permitted, ASN1Sequence dns) + throws NameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + if (permitted.isEmpty() && dns.size() == 0) + { + return; + } + Iterator it = permitted.iterator(); + + while (it.hasNext()) + { + ASN1Sequence subtree = (ASN1Sequence)it.next(); + + if (withinDNSubtree(dns, subtree)) + { + return; + } + } + + throw new NameConstraintValidatorException( + "Subject distinguished name is not from a permitted subtree"); + } + + private void checkExcludedDN(Set excluded, ASN1Sequence dns) + throws NameConstraintValidatorException + { + if (excluded.isEmpty()) + { + return; + } + + Iterator it = excluded.iterator(); + + while (it.hasNext()) + { + ASN1Sequence subtree = (ASN1Sequence)it.next(); + + if (withinDNSubtree(dns, subtree)) + { + throw new NameConstraintValidatorException( + "Subject distinguished name is from an excluded subtree"); + } + } + } + + private Set intersectDN(Set permitted, Set dns) + { + Set intersect = new HashSet(); + for (Iterator it = dns.iterator(); it.hasNext(); ) + { + ASN1Sequence dn = ASN1Sequence.getInstance(((GeneralSubtree)it + .next()).getBase().getName().toASN1Primitive()); + if (permitted == null) + { + if (dn != null) + { + intersect.add(dn); + } + } + else + { + Iterator _iter = permitted.iterator(); + while (_iter.hasNext()) + { + ASN1Sequence subtree = (ASN1Sequence)_iter.next(); + + if (withinDNSubtree(dn, subtree)) + { + intersect.add(dn); + } + else if (withinDNSubtree(subtree, dn)) + { + intersect.add(subtree); + } + } + } + } + return intersect; + } + + private Set unionDN(Set excluded, ASN1Sequence dn) + { + if (excluded.isEmpty()) + { + if (dn == null) + { + return excluded; + } + excluded.add(dn); + + return excluded; + } + else + { + Set intersect = new HashSet(); + + Iterator it = excluded.iterator(); + while (it.hasNext()) + { + ASN1Sequence subtree = (ASN1Sequence)it.next(); + + if (withinDNSubtree(dn, subtree)) + { + intersect.add(subtree); + } + else if (withinDNSubtree(subtree, dn)) + { + intersect.add(dn); + } + else + { + intersect.add(subtree); + intersect.add(dn); + } + } + + return intersect; + } + } + + private Set intersectEmail(Set permitted, Set emails) + { + Set intersect = new HashSet(); + for (Iterator it = emails.iterator(); it.hasNext(); ) + { + String email = extractNameAsString(((GeneralSubtree)it.next()) + .getBase()); + + if (permitted == null) + { + if (email != null) + { + intersect.add(email); + } + } + else + { + Iterator it2 = permitted.iterator(); + while (it2.hasNext()) + { + String _permitted = (String)it2.next(); + + intersectEmail(email, _permitted, intersect); + } + } + } + return intersect; + } + + private Set unionEmail(Set excluded, String email) + { + if (excluded.isEmpty()) + { + if (email == null) + { + return excluded; + } + excluded.add(email); + return excluded; + } + else + { + Set union = new HashSet(); + + Iterator it = excluded.iterator(); + while (it.hasNext()) + { + String _excluded = (String)it.next(); + + unionEmail(_excluded, email, union); + } + + return union; + } + } + + /** + * Returns the intersection of the permitted IP ranges in + * <code>permitted</code> with <code>ip</code>. + * + * @param permitted A <code>Set</code> of permitted IP addresses with + * their subnet mask as byte arrays. + * @param ips The IP address with its subnet mask. + * @return The <code>Set</code> of permitted IP ranges intersected with + * <code>ip</code>. + */ + private Set intersectIP(Set permitted, Set ips) + { + Set intersect = new HashSet(); + for (Iterator it = ips.iterator(); it.hasNext(); ) + { + byte[] ip = ASN1OctetString.getInstance( + ((GeneralSubtree)it.next()).getBase().getName()).getOctets(); + if (permitted == null) + { + if (ip != null) + { + intersect.add(ip); + } + } + else + { + Iterator it2 = permitted.iterator(); + while (it2.hasNext()) + { + byte[] _permitted = (byte[])it2.next(); + intersect.addAll(intersectIPRange(_permitted, ip)); + } + } + } + return intersect; + } + + /** + * Returns the union of the excluded IP ranges in <code>excluded</code> + * with <code>ip</code>. + * + * @param excluded A <code>Set</code> of excluded IP addresses with their + * subnet mask as byte arrays. + * @param ip The IP address with its subnet mask. + * @return The <code>Set</code> of excluded IP ranges unified with + * <code>ip</code> as byte arrays. + */ + private Set unionIP(Set excluded, byte[] ip) + { + if (excluded.isEmpty()) + { + if (ip == null) + { + return excluded; + } + excluded.add(ip); + + return excluded; + } + else + { + Set union = new HashSet(); + + Iterator it = excluded.iterator(); + while (it.hasNext()) + { + byte[] _excluded = (byte[])it.next(); + union.addAll(unionIPRange(_excluded, ip)); + } + + return union; + } + } + + /** + * Calculates the union if two IP ranges. + * + * @param ipWithSubmask1 The first IP address with its subnet mask. + * @param ipWithSubmask2 The second IP address with its subnet mask. + * @return A <code>Set</code> with the union of both addresses. + */ + private Set unionIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2) + { + Set set = new HashSet(); + + // difficult, adding always all IPs is not wrong + if (Arrays.areEqual(ipWithSubmask1, ipWithSubmask2)) + { + set.add(ipWithSubmask1); + } + else + { + set.add(ipWithSubmask1); + set.add(ipWithSubmask2); + } + return set; + } + + /** + * Calculates the interesction if two IP ranges. + * + * @param ipWithSubmask1 The first IP address with its subnet mask. + * @param ipWithSubmask2 The second IP address with its subnet mask. + * @return A <code>Set</code> with the single IP address with its subnet + * mask as a byte array or an empty <code>Set</code>. + */ + private Set intersectIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2) + { + if (ipWithSubmask1.length != ipWithSubmask2.length) + { + return Collections.EMPTY_SET; + } + byte[][] temp = extractIPsAndSubnetMasks(ipWithSubmask1, ipWithSubmask2); + byte ip1[] = temp[0]; + byte subnetmask1[] = temp[1]; + byte ip2[] = temp[2]; + byte subnetmask2[] = temp[3]; + + byte minMax[][] = minMaxIPs(ip1, subnetmask1, ip2, subnetmask2); + byte[] min; + byte[] max; + max = min(minMax[1], minMax[3]); + min = max(minMax[0], minMax[2]); + + // minimum IP address must be bigger than max + if (compareTo(min, max) == 1) + { + return Collections.EMPTY_SET; + } + // OR keeps all significant bits + byte[] ip = or(minMax[0], minMax[2]); + byte[] subnetmask = or(subnetmask1, subnetmask2); + return Collections.singleton(ipWithSubnetMask(ip, subnetmask)); + } + + /** + * Concatenates the IP address with its subnet mask. + * + * @param ip The IP address. + * @param subnetMask Its subnet mask. + * @return The concatenated IP address with its subnet mask. + */ + private byte[] ipWithSubnetMask(byte[] ip, byte[] subnetMask) + { + int ipLength = ip.length; + byte[] temp = new byte[ipLength * 2]; + System.arraycopy(ip, 0, temp, 0, ipLength); + System.arraycopy(subnetMask, 0, temp, ipLength, ipLength); + return temp; + } + + /** + * Splits the IP addresses and their subnet mask. + * + * @param ipWithSubmask1 The first IP address with the subnet mask. + * @param ipWithSubmask2 The second IP address with the subnet mask. + * @return An array with two elements. Each element contains the IP address + * and the subnet mask in this order. + */ + private byte[][] extractIPsAndSubnetMasks( + byte[] ipWithSubmask1, + byte[] ipWithSubmask2) + { + int ipLength = ipWithSubmask1.length / 2; + byte ip1[] = new byte[ipLength]; + byte subnetmask1[] = new byte[ipLength]; + System.arraycopy(ipWithSubmask1, 0, ip1, 0, ipLength); + System.arraycopy(ipWithSubmask1, ipLength, subnetmask1, 0, ipLength); + + byte ip2[] = new byte[ipLength]; + byte subnetmask2[] = new byte[ipLength]; + System.arraycopy(ipWithSubmask2, 0, ip2, 0, ipLength); + System.arraycopy(ipWithSubmask2, ipLength, subnetmask2, 0, ipLength); + return new byte[][] + {ip1, subnetmask1, ip2, subnetmask2}; + } + + /** + * Based on the two IP addresses and their subnet masks the IP range is + * computed for each IP address - subnet mask pair and returned as the + * minimum IP address and the maximum address of the range. + * + * @param ip1 The first IP address. + * @param subnetmask1 The subnet mask of the first IP address. + * @param ip2 The second IP address. + * @param subnetmask2 The subnet mask of the second IP address. + * @return A array with two elements. The first/second element contains the + * min and max IP address of the first/second IP address and its + * subnet mask. + */ + private byte[][] minMaxIPs( + byte[] ip1, + byte[] subnetmask1, + byte[] ip2, + byte[] subnetmask2) + { + int ipLength = ip1.length; + byte[] min1 = new byte[ipLength]; + byte[] max1 = new byte[ipLength]; + + byte[] min2 = new byte[ipLength]; + byte[] max2 = new byte[ipLength]; + + for (int i = 0; i < ipLength; i++) + { + min1[i] = (byte)(ip1[i] & subnetmask1[i]); + max1[i] = (byte)(ip1[i] & subnetmask1[i] | ~subnetmask1[i]); + + min2[i] = (byte)(ip2[i] & subnetmask2[i]); + max2[i] = (byte)(ip2[i] & subnetmask2[i] | ~subnetmask2[i]); + } + + return new byte[][]{min1, max1, min2, max2}; + } + + private void checkPermittedEmail(Set permitted, String email) + throws NameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + Iterator it = permitted.iterator(); + + while (it.hasNext()) + { + String str = ((String)it.next()); + + if (emailIsConstrained(email, str)) + { + return; + } + } + + if (email.length() == 0 && permitted.size() == 0) + { + return; + } + + throw new NameConstraintValidatorException( + "Subject email address is not from a permitted subtree."); + } + + private void checkExcludedEmail(Set excluded, String email) + throws NameConstraintValidatorException + { + if (excluded.isEmpty()) + { + return; + } + + Iterator it = excluded.iterator(); + + while (it.hasNext()) + { + String str = (String)it.next(); + + if (emailIsConstrained(email, str)) + { + throw new NameConstraintValidatorException( + "Email address is from an excluded subtree."); + } + } + } + + /** + * Checks if the IP <code>ip</code> is included in the permitted set + * <code>permitted</code>. + * + * @param permitted A <code>Set</code> of permitted IP addresses with + * their subnet mask as byte arrays. + * @param ip The IP address. + * @throws NameConstraintValidatorException if the IP is not permitted. + */ + private void checkPermittedIP(Set permitted, byte[] ip) + throws NameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + Iterator it = permitted.iterator(); + + while (it.hasNext()) + { + byte[] ipWithSubnet = (byte[])it.next(); + + if (isIPConstrained(ip, ipWithSubnet)) + { + return; + } + } + if (ip.length == 0 && permitted.size() == 0) + { + return; + } + throw new NameConstraintValidatorException( + "IP is not from a permitted subtree."); + } + + /** + * Checks if the IP <code>ip</code> is included in the excluded set + * <code>excluded</code>. + * + * @param excluded A <code>Set</code> of excluded IP addresses with their + * subnet mask as byte arrays. + * @param ip The IP address. + * @throws NameConstraintValidatorException if the IP is excluded. + */ + private void checkExcludedIP(Set excluded, byte[] ip) + throws NameConstraintValidatorException + { + if (excluded.isEmpty()) + { + return; + } + + Iterator it = excluded.iterator(); + + while (it.hasNext()) + { + byte[] ipWithSubnet = (byte[])it.next(); + + if (isIPConstrained(ip, ipWithSubnet)) + { + throw new NameConstraintValidatorException( + "IP is from an excluded subtree."); + } + } + } + + /** + * Checks if the IP address <code>ip</code> is constrained by + * <code>constraint</code>. + * + * @param ip The IP address. + * @param constraint The constraint. This is an IP address concatenated with + * its subnetmask. + * @return <code>true</code> if constrained, <code>false</code> + * otherwise. + */ + private boolean isIPConstrained(byte ip[], byte[] constraint) + { + int ipLength = ip.length; + + if (ipLength != (constraint.length / 2)) + { + return false; + } + + byte[] subnetMask = new byte[ipLength]; + System.arraycopy(constraint, ipLength, subnetMask, 0, ipLength); + + byte[] permittedSubnetAddress = new byte[ipLength]; + + byte[] ipSubnetAddress = new byte[ipLength]; + + // the resulting IP address by applying the subnet mask + for (int i = 0; i < ipLength; i++) + { + permittedSubnetAddress[i] = (byte)(constraint[i] & subnetMask[i]); + ipSubnetAddress[i] = (byte)(ip[i] & subnetMask[i]); + } + + return Arrays.areEqual(permittedSubnetAddress, ipSubnetAddress); + } + + private boolean emailIsConstrained(String email, String constraint) + { + String sub = email.substring(email.indexOf('@') + 1); + // a particular mailbox + if (constraint.indexOf('@') != -1) + { + if (email.equalsIgnoreCase(constraint)) + { + return true; + } + } + // on particular host + else if (!(constraint.charAt(0) == '.')) + { + if (sub.equalsIgnoreCase(constraint)) + { + return true; + } + } + // address in sub domain + else if (withinDomain(sub, constraint)) + { + return true; + } + return false; + } + + private boolean withinDomain(String testDomain, String domain) + { + String tempDomain = domain; + if (tempDomain.startsWith(".")) + { + tempDomain = tempDomain.substring(1); + } + String[] domainParts = Strings.split(tempDomain, '.'); + String[] testDomainParts = Strings.split(testDomain, '.'); + // must have at least one subdomain + if (testDomainParts.length <= domainParts.length) + { + return false; + } + int d = testDomainParts.length - domainParts.length; + for (int i = -1; i < domainParts.length; i++) + { + if (i == -1) + { + if (testDomainParts[i + d].equals("")) + { + return false; + } + } + else if (!domainParts[i].equalsIgnoreCase(testDomainParts[i + d])) + { + return false; + } + } + return true; + } + + private void checkPermittedDNS(Set permitted, String dns) + throws NameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + Iterator it = permitted.iterator(); + + while (it.hasNext()) + { + String str = ((String)it.next()); + + // is sub domain + if (withinDomain(dns, str) || dns.equalsIgnoreCase(str)) + { + return; + } + } + if (dns.length() == 0 && permitted.size() == 0) + { + return; + } + throw new NameConstraintValidatorException( + "DNS is not from a permitted subtree."); + } + + private void checkExcludedDNS(Set excluded, String dns) + throws NameConstraintValidatorException + { + if (excluded.isEmpty()) + { + return; + } + + Iterator it = excluded.iterator(); + + while (it.hasNext()) + { + String str = ((String)it.next()); + + // is sub domain or the same + if (withinDomain(dns, str) || dns.equalsIgnoreCase(str)) + { + throw new NameConstraintValidatorException( + "DNS is from an excluded subtree."); + } + } + } + + /** + * The common part of <code>email1</code> and <code>email2</code> is + * added to the union <code>union</code>. If <code>email1</code> and + * <code>email2</code> have nothing in common they are added both. + * + * @param email1 Email address constraint 1. + * @param email2 Email address constraint 2. + * @param union The union. + */ + private void unionEmail(String email1, String email2, Set union) + { + // email1 is a particular address + if (email1.indexOf('@') != -1) + { + String _sub = email1.substring(email1.indexOf('@') + 1); + // both are a particular mailbox + if (email2.indexOf('@') != -1) + { + if (email1.equalsIgnoreCase(email2)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(_sub, email2)) + { + union.add(email2); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a particular host + else + { + if (_sub.equalsIgnoreCase(email2)) + { + union.add(email2); + } + else + { + union.add(email1); + union.add(email2); + } + } + } + // email1 specifies a domain + else if (email1.startsWith(".")) + { + if (email2.indexOf('@') != -1) + { + String _sub = email2.substring(email1.indexOf('@') + 1); + if (withinDomain(_sub, email1)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(email1, email2) + || email1.equalsIgnoreCase(email2)) + { + union.add(email2); + } + else if (withinDomain(email2, email1)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + else + { + if (withinDomain(email2, email1)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + } + // email specifies a host + else + { + if (email2.indexOf('@') != -1) + { + String _sub = email2.substring(email1.indexOf('@') + 1); + if (_sub.equalsIgnoreCase(email1)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(email1, email2)) + { + union.add(email2); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a particular host + else + { + if (email1.equalsIgnoreCase(email2)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + } + } + + private void unionURI(String email1, String email2, Set union) + { + // email1 is a particular address + if (email1.indexOf('@') != -1) + { + String _sub = email1.substring(email1.indexOf('@') + 1); + // both are a particular mailbox + if (email2.indexOf('@') != -1) + { + if (email1.equalsIgnoreCase(email2)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(_sub, email2)) + { + union.add(email2); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a particular host + else + { + if (_sub.equalsIgnoreCase(email2)) + { + union.add(email2); + } + else + { + union.add(email1); + union.add(email2); + } + } + } + // email1 specifies a domain + else if (email1.startsWith(".")) + { + if (email2.indexOf('@') != -1) + { + String _sub = email2.substring(email1.indexOf('@') + 1); + if (withinDomain(_sub, email1)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(email1, email2) + || email1.equalsIgnoreCase(email2)) + { + union.add(email2); + } + else if (withinDomain(email2, email1)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + else + { + if (withinDomain(email2, email1)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + } + // email specifies a host + else + { + if (email2.indexOf('@') != -1) + { + String _sub = email2.substring(email1.indexOf('@') + 1); + if (_sub.equalsIgnoreCase(email1)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(email1, email2)) + { + union.add(email2); + } + else + { + union.add(email1); + union.add(email2); + } + } + // email2 specifies a particular host + else + { + if (email1.equalsIgnoreCase(email2)) + { + union.add(email1); + } + else + { + union.add(email1); + union.add(email2); + } + } + } + } + + private Set intersectDNS(Set permitted, Set dnss) + { + Set intersect = new HashSet(); + for (Iterator it = dnss.iterator(); it.hasNext(); ) + { + String dns = extractNameAsString(((GeneralSubtree)it.next()) + .getBase()); + if (permitted == null) + { + if (dns != null) + { + intersect.add(dns); + } + } + else + { + Iterator _iter = permitted.iterator(); + while (_iter.hasNext()) + { + String _permitted = (String)_iter.next(); + + if (withinDomain(_permitted, dns)) + { + intersect.add(_permitted); + } + else if (withinDomain(dns, _permitted)) + { + intersect.add(dns); + } + } + } + } + + return intersect; + } + + private Set unionDNS(Set excluded, String dns) + { + if (excluded.isEmpty()) + { + if (dns == null) + { + return excluded; + } + excluded.add(dns); + + return excluded; + } + else + { + Set union = new HashSet(); + + Iterator _iter = excluded.iterator(); + while (_iter.hasNext()) + { + String _permitted = (String)_iter.next(); + + if (withinDomain(_permitted, dns)) + { + union.add(dns); + } + else if (withinDomain(dns, _permitted)) + { + union.add(_permitted); + } + else + { + union.add(_permitted); + union.add(dns); + } + } + + return union; + } + } + + /** + * The most restricting part from <code>email1</code> and + * <code>email2</code> is added to the intersection <code>intersect</code>. + * + * @param email1 Email address constraint 1. + * @param email2 Email address constraint 2. + * @param intersect The intersection. + */ + private void intersectEmail(String email1, String email2, Set intersect) + { + // email1 is a particular address + if (email1.indexOf('@') != -1) + { + String _sub = email1.substring(email1.indexOf('@') + 1); + // both are a particular mailbox + if (email2.indexOf('@') != -1) + { + if (email1.equalsIgnoreCase(email2)) + { + intersect.add(email1); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(_sub, email2)) + { + intersect.add(email1); + } + } + // email2 specifies a particular host + else + { + if (_sub.equalsIgnoreCase(email2)) + { + intersect.add(email1); + } + } + } + // email specifies a domain + else if (email1.startsWith(".")) + { + if (email2.indexOf('@') != -1) + { + String _sub = email2.substring(email1.indexOf('@') + 1); + if (withinDomain(_sub, email1)) + { + intersect.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(email1, email2) + || email1.equalsIgnoreCase(email2)) + { + intersect.add(email1); + } + else if (withinDomain(email2, email1)) + { + intersect.add(email2); + } + } + else + { + if (withinDomain(email2, email1)) + { + intersect.add(email2); + } + } + } + // email1 specifies a host + else + { + if (email2.indexOf('@') != -1) + { + String _sub = email2.substring(email2.indexOf('@') + 1); + if (_sub.equalsIgnoreCase(email1)) + { + intersect.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(email1, email2)) + { + intersect.add(email1); + } + } + // email2 specifies a particular host + else + { + if (email1.equalsIgnoreCase(email2)) + { + intersect.add(email1); + } + } + } + } + + private void checkExcludedURI(Set excluded, String uri) + throws NameConstraintValidatorException + { + if (excluded.isEmpty()) + { + return; + } + + Iterator it = excluded.iterator(); + + while (it.hasNext()) + { + String str = ((String)it.next()); + + if (isUriConstrained(uri, str)) + { + throw new NameConstraintValidatorException( + "URI is from an excluded subtree."); + } + } + } + + private Set intersectURI(Set permitted, Set uris) + { + Set intersect = new HashSet(); + for (Iterator it = uris.iterator(); it.hasNext(); ) + { + String uri = extractNameAsString(((GeneralSubtree)it.next()) + .getBase()); + if (permitted == null) + { + if (uri != null) + { + intersect.add(uri); + } + } + else + { + Iterator _iter = permitted.iterator(); + while (_iter.hasNext()) + { + String _permitted = (String)_iter.next(); + intersectURI(_permitted, uri, intersect); + } + } + } + return intersect; + } + + private Set unionURI(Set excluded, String uri) + { + if (excluded.isEmpty()) + { + if (uri == null) + { + return excluded; + } + excluded.add(uri); + + return excluded; + } + else + { + Set union = new HashSet(); + + Iterator _iter = excluded.iterator(); + while (_iter.hasNext()) + { + String _excluded = (String)_iter.next(); + + unionURI(_excluded, uri, union); + } + + return union; + } + } + + private void intersectURI(String email1, String email2, Set intersect) + { + // email1 is a particular address + if (email1.indexOf('@') != -1) + { + String _sub = email1.substring(email1.indexOf('@') + 1); + // both are a particular mailbox + if (email2.indexOf('@') != -1) + { + if (email1.equalsIgnoreCase(email2)) + { + intersect.add(email1); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(_sub, email2)) + { + intersect.add(email1); + } + } + // email2 specifies a particular host + else + { + if (_sub.equalsIgnoreCase(email2)) + { + intersect.add(email1); + } + } + } + // email specifies a domain + else if (email1.startsWith(".")) + { + if (email2.indexOf('@') != -1) + { + String _sub = email2.substring(email1.indexOf('@') + 1); + if (withinDomain(_sub, email1)) + { + intersect.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(email1, email2) + || email1.equalsIgnoreCase(email2)) + { + intersect.add(email1); + } + else if (withinDomain(email2, email1)) + { + intersect.add(email2); + } + } + else + { + if (withinDomain(email2, email1)) + { + intersect.add(email2); + } + } + } + // email1 specifies a host + else + { + if (email2.indexOf('@') != -1) + { + String _sub = email2.substring(email2.indexOf('@') + 1); + if (_sub.equalsIgnoreCase(email1)) + { + intersect.add(email2); + } + } + // email2 specifies a domain + else if (email2.startsWith(".")) + { + if (withinDomain(email1, email2)) + { + intersect.add(email1); + } + } + // email2 specifies a particular host + else + { + if (email1.equalsIgnoreCase(email2)) + { + intersect.add(email1); + } + } + } + } + + private void checkPermittedURI(Set permitted, String uri) + throws NameConstraintValidatorException + { + if (permitted == null) + { + return; + } + + Iterator it = permitted.iterator(); + + while (it.hasNext()) + { + String str = ((String)it.next()); + + if (isUriConstrained(uri, str)) + { + return; + } + } + if (uri.length() == 0 && permitted.size() == 0) + { + return; + } + throw new NameConstraintValidatorException( + "URI is not from a permitted subtree."); + } + + private boolean isUriConstrained(String uri, String constraint) + { + String host = extractHostFromURL(uri); + // a host + if (!constraint.startsWith(".")) + { + if (host.equalsIgnoreCase(constraint)) + { + return true; + } + } + + // in sub domain or domain + else if (withinDomain(host, constraint)) + { + return true; + } + + return false; + } + + private static String extractHostFromURL(String url) + { + // see RFC 1738 + // remove ':' after protocol, e.g. http: + String sub = url.substring(url.indexOf(':') + 1); + // extract host from Common Internet Scheme Syntax, e.g. http:// + if (sub.indexOf("//") != -1) + { + sub = sub.substring(sub.indexOf("//") + 2); + } + // first remove port, e.g. http://test.com:21 + if (sub.lastIndexOf(':') != -1) + { + sub = sub.substring(0, sub.lastIndexOf(':')); + } + // remove user and password, e.g. http://john:password@test.com + sub = sub.substring(sub.indexOf(':') + 1); + sub = sub.substring(sub.indexOf('@') + 1); + // remove local parts, e.g. http://test.com/bla + if (sub.indexOf('/') != -1) + { + sub = sub.substring(0, sub.indexOf('/')); + } + return sub; + } + + private String extractNameAsString(GeneralName name) + { + return DERIA5String.getInstance(name.getName()).getString(); + } + + /** + * Returns the maximum IP address. + * + * @param ip1 The first IP address. + * @param ip2 The second IP address. + * @return The maximum IP address. + */ + private static byte[] max(byte[] ip1, byte[] ip2) + { + for (int i = 0; i < ip1.length; i++) + { + if ((ip1[i] & 0xFFFF) > (ip2[i] & 0xFFFF)) + { + return ip1; + } + } + return ip2; + } + + /** + * Returns the minimum IP address. + * + * @param ip1 The first IP address. + * @param ip2 The second IP address. + * @return The minimum IP address. + */ + private static byte[] min(byte[] ip1, byte[] ip2) + { + for (int i = 0; i < ip1.length; i++) + { + if ((ip1[i] & 0xFFFF) < (ip2[i] & 0xFFFF)) + { + return ip1; + } + } + return ip2; + } + + /** + * Compares IP address <code>ip1</code> with <code>ip2</code>. If ip1 + * is equal to ip2 0 is returned. If ip1 is bigger 1 is returned, -1 + * otherwise. + * + * @param ip1 The first IP address. + * @param ip2 The second IP address. + * @return 0 if ip1 is equal to ip2, 1 if ip1 is bigger, -1 otherwise. + */ + private static int compareTo(byte[] ip1, byte[] ip2) + { + if (Arrays.areEqual(ip1, ip2)) + { + return 0; + } + if (Arrays.areEqual(max(ip1, ip2), ip1)) + { + return 1; + } + return -1; + } + + /** + * Returns the logical OR of the IP addresses <code>ip1</code> and + * <code>ip2</code>. + * + * @param ip1 The first IP address. + * @param ip2 The second IP address. + * @return The OR of <code>ip1</code> and <code>ip2</code>. + */ + private static byte[] or(byte[] ip1, byte[] ip2) + { + byte[] temp = new byte[ip1.length]; + for (int i = 0; i < ip1.length; i++) + { + temp[i] = (byte)(ip1[i] | ip2[i]); + } + return temp; + } + + private int hashCollection(Collection coll) + { + if (coll == null) + { + return 0; + } + int hash = 0; + Iterator it1 = coll.iterator(); + while (it1.hasNext()) + { + Object o = it1.next(); + if (o instanceof byte[]) + { + hash += Arrays.hashCode((byte[])o); + } + else + { + hash += o.hashCode(); + } + } + return hash; + } + + private boolean collectionsAreEqual(Collection coll1, Collection coll2) + { + if (coll1 == coll2) + { + return true; + } + if (coll1 == null || coll2 == null) + { + return false; + } + if (coll1.size() != coll2.size()) + { + return false; + } + Iterator it1 = coll1.iterator(); + + while (it1.hasNext()) + { + Object a = it1.next(); + Iterator it2 = coll2.iterator(); + boolean found = false; + while (it2.hasNext()) + { + Object b = it2.next(); + if (equals(a, b)) + { + found = true; + break; + } + } + if (!found) + { + return false; + } + } + return true; + } + + private boolean equals(Object o1, Object o2) + { + if (o1 == o2) + { + return true; + } + if (o1 == null || o2 == null) + { + return false; + } + if (o1 instanceof byte[] && o2 instanceof byte[]) + { + return Arrays.areEqual((byte[])o1, (byte[])o2); + } + else + { + return o1.equals(o2); + } + } + + /** + * Stringifies an IPv4 or v6 address with subnet mask. + * + * @param ip The IP with subnet mask. + * @return The stringified IP address. + */ + private String stringifyIP(byte[] ip) + { + String temp = ""; + for (int i = 0; i < ip.length / 2; i++) + { + temp += Integer.toString(ip[i] & 0x00FF) + "."; + } + temp = temp.substring(0, temp.length() - 1); + temp += "/"; + for (int i = ip.length / 2; i < ip.length; i++) + { + temp += Integer.toString(ip[i] & 0x00FF) + "."; + } + temp = temp.substring(0, temp.length() - 1); + return temp; + } + + private String stringifyIPCollection(Set ips) + { + String temp = ""; + temp += "["; + for (Iterator it = ips.iterator(); it.hasNext(); ) + { + temp += stringifyIP((byte[])it.next()) + ","; + } + if (temp.length() > 1) + { + temp = temp.substring(0, temp.length() - 1); + } + temp += "]"; + return temp; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java index d1de26fc..97f752ae 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyInformation.java @@ -65,11 +65,13 @@ public class PolicyInformation return policyQualifiers; } - /* + /* + * <pre> * PolicyInformation ::= SEQUENCE { * policyIdentifier CertPolicyId, * policyQualifiers SEQUENCE SIZE (1..MAX) OF * PolicyQualifierInfo OPTIONAL } + * </pre> */ public ASN1Primitive toASN1Primitive() { @@ -84,4 +86,31 @@ public class PolicyInformation return new DERSequence(v); } + + public String toString() + { + StringBuffer sb = new StringBuffer(); + + sb.append("Policy information: "); + sb.append(policyIdentifier); + + if (policyQualifiers != null) + { + StringBuffer p = new StringBuffer(); + for (int i = 0; i < policyQualifiers.size(); i++) + { + if (p.length() != 0) + { + p.append(", "); + } + p.append(PolicyQualifierInfo.getInstance(policyQualifiers.getObjectAt(i))); + } + + sb.append("["); + sb.append(p); + sb.append("]"); + } + + return sb.toString(); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierId.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierId.java new file mode 100644 index 00000000..82835f6a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierId.java @@ -0,0 +1,31 @@ + +package org.bouncycastle.asn1.x509; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; + +/** + * PolicyQualifierId, used in the CertificatePolicies + * X509V3 extension. + * + * <pre> + * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + * PolicyQualifierId ::= + * OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice) + * </pre> + */ +public class PolicyQualifierId extends ASN1ObjectIdentifier +{ + private static final String id_qt = "1.3.6.1.5.5.7.2"; + + private PolicyQualifierId(String id) + { + super(id); + } + + public static final PolicyQualifierId id_qt_cps = + new PolicyQualifierId(id_qt + ".1"); + public static final PolicyQualifierId id_qt_unotice = + new PolicyQualifierId(id_qt + ".2"); +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java new file mode 100644 index 00000000..2f79a963 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java @@ -0,0 +1,117 @@ +package org.bouncycastle.asn1.x509; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERIA5String; +import org.bouncycastle.asn1.DERSequence; + +/** + * Policy qualifiers, used in the X509V3 CertificatePolicies + * extension. + * + * <pre> + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + * </pre> + */ +public class PolicyQualifierInfo + extends ASN1Object +{ + private ASN1ObjectIdentifier policyQualifierId; + private ASN1Encodable qualifier; + + /** + * Creates a new <code>PolicyQualifierInfo</code> instance. + * + * @param policyQualifierId a <code>PolicyQualifierId</code> value + * @param qualifier the qualifier, defined by the above field. + */ + public PolicyQualifierInfo( + ASN1ObjectIdentifier policyQualifierId, + ASN1Encodable qualifier) + { + this.policyQualifierId = policyQualifierId; + this.qualifier = qualifier; + } + + /** + * Creates a new <code>PolicyQualifierInfo</code> containing a + * cPSuri qualifier. + * + * @param cps the CPS (certification practice statement) uri as a + * <code>String</code>. + */ + public PolicyQualifierInfo( + String cps) + { + policyQualifierId = PolicyQualifierId.id_qt_cps; + qualifier = new DERIA5String (cps); + } + + /** + * Creates a new <code>PolicyQualifierInfo</code> instance. + * + * @param as <code>PolicyQualifierInfo</code> X509 structure + * encoded as an ASN1Sequence. + * @deprecated use PolicyQualifierInfo.getInstance() + */ + public PolicyQualifierInfo( + ASN1Sequence as) + { + if (as.size() != 2) + { + throw new IllegalArgumentException("Bad sequence size: " + + as.size()); + } + + policyQualifierId = ASN1ObjectIdentifier.getInstance(as.getObjectAt(0)); + qualifier = as.getObjectAt(1); + } + + public static PolicyQualifierInfo getInstance( + Object obj) + { + if (obj instanceof PolicyQualifierInfo) + { + return (PolicyQualifierInfo)obj; + } + else if (obj != null) + { + return new PolicyQualifierInfo(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + + public ASN1ObjectIdentifier getPolicyQualifierId() + { + return policyQualifierId; + } + + public ASN1Encodable getQualifier() + { + return qualifier; + } + + /** + * Returns a DER-encodable representation of this instance. + * + * @return a <code>ASN1Primitive</code> value + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector dev = new ASN1EncodableVector(); + dev.add(policyQualifierId); + dev.add(qualifier); + + return new DERSequence(dev); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java index 9e09cd72..0938a948 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java @@ -64,6 +64,9 @@ public class SubjectPublicKeyInfo this.algId = algId; } + /** + @deprecated use SubjectPublicKeyInfo.getInstance() + */ public SubjectPublicKeyInfo( ASN1Sequence seq) { @@ -104,7 +107,7 @@ public class SubjectPublicKeyInfo public ASN1Primitive parsePublicKey() throws IOException { - ASN1InputStream aIn = new ASN1InputStream(keyData.getBytes()); + ASN1InputStream aIn = new ASN1InputStream(keyData.getOctets()); return aIn.readObject(); } @@ -121,7 +124,7 @@ public class SubjectPublicKeyInfo public ASN1Primitive getPublicKey() throws IOException { - ASN1InputStream aIn = new ASN1InputStream(keyData.getBytes()); + ASN1InputStream aIn = new ASN1InputStream(keyData.getOctets()); return aIn.readObject(); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java index 5fdbcd67..23f99d0a 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java @@ -1,6 +1,7 @@ package org.bouncycastle.asn1.x509; import java.util.Enumeration; +import java.util.NoSuchElementException; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1GeneralizedTime; @@ -132,7 +133,7 @@ public class TBSCertList public Object nextElement() { - return null; // TODO: check exception handling + throw new NoSuchElementException("Empty Enumeration"); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java index e1c7a54b..e58220e6 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java @@ -6,22 +6,22 @@ public interface X509ObjectIdentifiers { /** Subject RDN components: commonName = 2.5.4.3 */ - static final ASN1ObjectIdentifier commonName = new ASN1ObjectIdentifier("2.5.4.3"); + static final ASN1ObjectIdentifier commonName = new ASN1ObjectIdentifier("2.5.4.3").intern(); /** Subject RDN components: countryName = 2.5.4.6 */ - static final ASN1ObjectIdentifier countryName = new ASN1ObjectIdentifier("2.5.4.6"); + static final ASN1ObjectIdentifier countryName = new ASN1ObjectIdentifier("2.5.4.6").intern(); /** Subject RDN components: localityName = 2.5.4.7 */ - static final ASN1ObjectIdentifier localityName = new ASN1ObjectIdentifier("2.5.4.7"); + static final ASN1ObjectIdentifier localityName = new ASN1ObjectIdentifier("2.5.4.7").intern(); /** Subject RDN components: stateOrProvinceName = 2.5.4.8 */ - static final ASN1ObjectIdentifier stateOrProvinceName = new ASN1ObjectIdentifier("2.5.4.8"); + static final ASN1ObjectIdentifier stateOrProvinceName = new ASN1ObjectIdentifier("2.5.4.8").intern(); /** Subject RDN components: organization = 2.5.4.10 */ - static final ASN1ObjectIdentifier organization = new ASN1ObjectIdentifier("2.5.4.10"); + static final ASN1ObjectIdentifier organization = new ASN1ObjectIdentifier("2.5.4.10").intern(); /** Subject RDN components: organizationalUnitName = 2.5.4.11 */ - static final ASN1ObjectIdentifier organizationalUnitName = new ASN1ObjectIdentifier("2.5.4.11"); + static final ASN1ObjectIdentifier organizationalUnitName = new ASN1ObjectIdentifier("2.5.4.11").intern(); /** Subject RDN components: telephone_number = 2.5.4.20 */ - static final ASN1ObjectIdentifier id_at_telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20"); + static final ASN1ObjectIdentifier id_at_telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20").intern(); /** Subject RDN components: name = 2.5.4.41 */ - static final ASN1ObjectIdentifier id_at_name = new ASN1ObjectIdentifier("2.5.4.41"); + static final ASN1ObjectIdentifier id_at_name = new ASN1ObjectIdentifier("2.5.4.41").intern(); /** * id-SHA1 OBJECT IDENTIFIER ::= @@ -29,7 +29,7 @@ public interface X509ObjectIdentifiers * <p> * OID: 1.3.14.3.2.27 */ - static final ASN1ObjectIdentifier id_SHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.26"); + static final ASN1ObjectIdentifier id_SHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.26").intern(); /** * ripemd160 OBJECT IDENTIFIER ::= @@ -37,7 +37,7 @@ public interface X509ObjectIdentifiers * <p> * OID: 1.3.36.3.2.1 */ - static final ASN1ObjectIdentifier ripemd160 = new ASN1ObjectIdentifier("1.3.36.3.2.1"); + static final ASN1ObjectIdentifier ripemd160 = new ASN1ObjectIdentifier("1.3.36.3.2.1").intern(); /** * ripemd160WithRSAEncryption OBJECT IDENTIFIER ::= @@ -45,11 +45,11 @@ public interface X509ObjectIdentifiers * <p> * OID: 1.3.36.3.3.1.2 */ - static final ASN1ObjectIdentifier ripemd160WithRSAEncryption = new ASN1ObjectIdentifier("1.3.36.3.3.1.2"); + static final ASN1ObjectIdentifier ripemd160WithRSAEncryption = new ASN1ObjectIdentifier("1.3.36.3.3.1.2").intern(); /** OID: 2.5.8.1.1 */ - static final ASN1ObjectIdentifier id_ea_rsa = new ASN1ObjectIdentifier("2.5.8.1.1"); + static final ASN1ObjectIdentifier id_ea_rsa = new ASN1ObjectIdentifier("2.5.8.1.1").intern(); /** id-pkix OID: 1.3.6.1.5.5.7 */ @@ -70,9 +70,9 @@ public interface X509ObjectIdentifiers /** id-pkix OID: 1.3.6.1.5.5.7.48 */ static final ASN1ObjectIdentifier id_ad = id_pkix.branch("48"); /** id-ad-caIssuers OID: 1.3.6.1.5.5.7.48.2 */ - static final ASN1ObjectIdentifier id_ad_caIssuers = id_ad.branch("2"); + static final ASN1ObjectIdentifier id_ad_caIssuers = id_ad.branch("2").intern(); /** id-ad-ocsp OID: 1.3.6.1.5.5.7.48.1 */ - static final ASN1ObjectIdentifier id_ad_ocsp = id_ad.branch("1"); + static final ASN1ObjectIdentifier id_ad_ocsp = id_ad.branch("1").intern(); /** OID for ocsp uri in AuthorityInformationAccess extension */ static final ASN1ObjectIdentifier ocspAccessMethod = id_ad_ocsp; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java index 509111ad..abff3635 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java @@ -12,6 +12,9 @@ import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERSequence; +/** + * @deprecated use DomainParameters + */ public class DHDomainParameters extends ASN1Object { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHPublicKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHPublicKey.java index 7c6d217e..a74188ac 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHPublicKey.java @@ -1,20 +1,41 @@ package org.bouncycastle.asn1.x9; +import java.math.BigInteger; + import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1TaggedObject; +/** + * X9.42 definition of a DHPublicKey + * <pre> + * DHPublicKey ::= INTEGER + * </pre> + */ public class DHPublicKey extends ASN1Object { private ASN1Integer y; + /** + * Return a DHPublicKey from the passed in tagged object. + * + * @param obj a tagged object. + * @param explicit true if the contents of the object is explictly tagged, false otherwise. + * @return a DHPublicKey + */ public static DHPublicKey getInstance(ASN1TaggedObject obj, boolean explicit) { return getInstance(ASN1Integer.getInstance(obj, explicit)); } + /** + * Return a DHPublicKey from the passed in object. + * + * @param obj an object for conversion or a byte[]. + * @return a DHPublicKey + */ public static DHPublicKey getInstance(Object obj) { if (obj == null || obj instanceof DHPublicKey) @@ -30,7 +51,7 @@ public class DHPublicKey throw new IllegalArgumentException("Invalid DHPublicKey: " + obj.getClass().getName()); } - public DHPublicKey(ASN1Integer y) + private DHPublicKey(ASN1Integer y) { if (y == null) { @@ -40,13 +61,38 @@ public class DHPublicKey this.y = y; } - public ASN1Integer getY() + /** + * Base constructor. + * + * @param y the public value Y. + */ + public DHPublicKey(BigInteger y) { - return this.y; + if (y == null) + { + throw new IllegalArgumentException("'y' cannot be null"); + } + + this.y = new ASN1Integer(y); + } + + /** + * Return the public value Y for the key. + * + * @return the Y value. + */ + public BigInteger getY() + { + return this.y.getPositiveValue(); } + /** + * Return an ASN.1 primitive representation of this object. + * + * @return an ASN1Integer. + */ public ASN1Primitive toASN1Primitive() { return this.y; } -} +}
\ No newline at end of file diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java index b3020e0a..db384590 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java @@ -9,6 +9,9 @@ import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERSequence; +/** + * @deprecated use ValidationParams + */ public class DHValidationParms extends ASN1Object { private DERBitString seed; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DomainParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DomainParameters.java new file mode 100644 index 00000000..e23f1b84 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DomainParameters.java @@ -0,0 +1,223 @@ +package org.bouncycastle.asn1.x9; + +import java.math.BigInteger; +import java.util.Enumeration; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERSequence; + +/** + * X9.44 Diffie-Hellman domain parameters. + * <pre> + * DomainParameters ::= SEQUENCE { + * p INTEGER, -- odd prime, p=jq +1 + * g INTEGER, -- generator, g + * q INTEGER, -- factor of p-1 + * j INTEGER OPTIONAL, -- subgroup factor, j>= 2 + * validationParams ValidationParams OPTIONAL + * } + * </pre> + */ +public class DomainParameters + extends ASN1Object +{ + private final ASN1Integer p, g, q, j; + private final ValidationParams validationParams; + + /** + * Return a DomainParameters object from the passed in tagged object. + * + * @param obj a tagged object. + * @param explicit true if the contents of the object is explictly tagged, false otherwise. + * @return a DomainParameters + */ + public static DomainParameters getInstance(ASN1TaggedObject obj, boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + /** + * Return a DomainParameters object from the passed in object. + * + * @param obj an object for conversion or a byte[]. + * @return a DomainParameters + */ + public static DomainParameters getInstance(Object obj) + { + if (obj instanceof DomainParameters) + { + return (DomainParameters)obj; + } + else if (obj != null) + { + return new DomainParameters(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + /** + * Base constructor - the full domain parameter set. + * + * @param p the prime p defining the Galois field. + * @param g the generator of the multiplicative subgroup of order g. + * @param q specifies the prime factor of p - 1 + * @param j optionally specifies the value that satisfies the equation p = jq+1 + * @param validationParams parameters for validating these domain parameters. + */ + public DomainParameters(BigInteger p, BigInteger g, BigInteger q, BigInteger j, + ValidationParams validationParams) + { + if (p == null) + { + throw new IllegalArgumentException("'p' cannot be null"); + } + if (g == null) + { + throw new IllegalArgumentException("'g' cannot be null"); + } + if (q == null) + { + throw new IllegalArgumentException("'q' cannot be null"); + } + + this.p = new ASN1Integer(p); + this.g = new ASN1Integer(g); + this.q = new ASN1Integer(q); + + if (j != null) + { + this.j = new ASN1Integer(j); + } + else + { + this.j = null; + } + this.validationParams = validationParams; + } + + private DomainParameters(ASN1Sequence seq) + { + if (seq.size() < 3 || seq.size() > 5) + { + throw new IllegalArgumentException("Bad sequence size: " + seq.size()); + } + + Enumeration e = seq.getObjects(); + this.p = ASN1Integer.getInstance(e.nextElement()); + this.g = ASN1Integer.getInstance(e.nextElement()); + this.q = ASN1Integer.getInstance(e.nextElement()); + + ASN1Encodable next = getNext(e); + + if (next != null && next instanceof ASN1Integer) + { + this.j = ASN1Integer.getInstance(next); + next = getNext(e); + } + else + { + this.j = null; + } + + if (next != null) + { + this.validationParams = ValidationParams.getInstance(next.toASN1Primitive()); + } + else + { + this.validationParams = null; + } + } + + private static ASN1Encodable getNext(Enumeration e) + { + return e.hasMoreElements() ? (ASN1Encodable)e.nextElement() : null; + } + + /** + * Return the prime p defining the Galois field. + * + * @return the prime p. + */ + public BigInteger getP() + { + return this.p.getPositiveValue(); + } + + /** + * Return the generator of the multiplicative subgroup of order g. + * + * @return the generator g. + */ + public BigInteger getG() + { + return this.g.getPositiveValue(); + } + + /** + * Return q, the prime factor of p - 1 + * + * @return q value + */ + public BigInteger getQ() + { + return this.q.getPositiveValue(); + } + + /** + * Return the value that satisfies the equation p = jq+1 (if present). + * + * @return j value or null. + */ + public BigInteger getJ() + { + if (this.j == null) + { + return null; + } + + return this.j.getPositiveValue(); + } + + /** + * Return the validation parameters for this set (if present). + * + * @return validation parameters, or null if absent. + */ + public ValidationParams getValidationParams() + { + return this.validationParams; + } + + /** + * Return an ASN.1 primitive representation of this object. + * + * @return a DERSequence containing the parameter values. + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + v.add(this.p); + v.add(this.g); + v.add(this.q); + + if (this.j != null) + { + v.add(this.j); + } + + if (this.validationParams != null) + { + v.add(this.validationParams); + } + + return new DERSequence(v); + } +}
\ No newline at end of file diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java index cf3c7603..5abcca9f 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java @@ -4,6 +4,10 @@ import java.util.Enumeration; import java.util.Vector; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +// BEGIN android-removed +// import org.bouncycastle.asn1.anssi.ANSSINamedCurves; +// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; +// END android-removed import org.bouncycastle.asn1.nist.NISTNamedCurves; import org.bouncycastle.asn1.sec.SECNamedCurves; // BEGIN android-removed @@ -32,18 +36,23 @@ public class ECNamedCurveTable ecP = SECNamedCurves.getByName(name); } + if (ecP == null) + { + ecP = NISTNamedCurves.getByName(name); + } + // BEGIN android-removed // if (ecP == null) // { // ecP = TeleTrusTNamedCurves.getByName(name); // } + // + // if (ecP == null) + // { + // ecP = ANSSINamedCurves.getByName(name); + // } // END android-removed - if (ecP == null) - { - ecP = NISTNamedCurves.getByName(name); - } - return ecP; } @@ -63,19 +72,63 @@ public class ECNamedCurveTable oid = SECNamedCurves.getOID(name); } + if (oid == null) + { + oid = NISTNamedCurves.getOID(name); + } + // BEGIN android-removed // if (oid == null) // { // oid = TeleTrusTNamedCurves.getOID(name); // } + // + // if (oid == null) + // { + // oid = ANSSINamedCurves.getOID(name); + // } // END android-removed - if (oid == null) + return oid; + } + + /** + * return a X9ECParameters object representing the passed in named + * curve. + * + * @param oid the object id of the curve requested + * @return a standard name for the curve. + */ + public static String getName( + ASN1ObjectIdentifier oid) + { + String name = NISTNamedCurves.getName(oid); + + if (name == null) { - oid = NISTNamedCurves.getOID(name); + name = SECNamedCurves.getName(oid); } - return oid; + // BEGIN android-removed + // if (name == null) + // { + // name = TeleTrusTNamedCurves.getName(oid); + // } + // END android-removed + + if (name == null) + { + name = X962NamedCurves.getName(oid); + } + + // BEGIN android-removed + // if (name == null) + // { + // name = ECGOST3410NamedCurves.getName(oid); + // } + // END android-removed + + return name; } /** @@ -95,15 +148,20 @@ public class ECNamedCurveTable ecP = SECNamedCurves.getByOID(oid); } + // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup + // BEGIN android-removed // if (ecP == null) // { // ecP = TeleTrusTNamedCurves.getByOID(oid); // } + // + // if (ecP == null) + // { + // ecP = ANSSINamedCurves.getByOID(oid); + // } // END android-removed - // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup - return ecP; } @@ -121,6 +179,7 @@ public class ECNamedCurveTable addEnumeration(v, NISTNamedCurves.getNames()); // BEGIN android-removed // addEnumeration(v, TeleTrusTNamedCurves.getNames()); + // addEnumeration(v, ANSSINamedCurves.getNames()); // END android-removed return v.elements(); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ValidationParams.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ValidationParams.java new file mode 100644 index 00000000..34ad746a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ValidationParams.java @@ -0,0 +1,99 @@ +package org.bouncycastle.asn1.x9; + +import java.math.BigInteger; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DERSequence; + +/** + * ValidationParams ::= SEQUENCE { + * seed BIT STRING, + * pgenCounter INTEGER + * } + */ +public class ValidationParams + extends ASN1Object +{ + private DERBitString seed; + private ASN1Integer pgenCounter; + + public static ValidationParams getInstance(ASN1TaggedObject obj, boolean explicit) + { + return getInstance(ASN1Sequence.getInstance(obj, explicit)); + } + + public static ValidationParams getInstance(Object obj) + { + if (obj instanceof ValidationParams) + { + return (ValidationParams)obj; + } + else if (obj != null) + { + return new ValidationParams(ASN1Sequence.getInstance(obj)); + } + + return null; + } + + public ValidationParams(byte[] seed, int pgenCounter) + { + if (seed == null) + { + throw new IllegalArgumentException("'seed' cannot be null"); + } + + this.seed = new DERBitString(seed); + this.pgenCounter = new ASN1Integer(pgenCounter); + } + + public ValidationParams(DERBitString seed, ASN1Integer pgenCounter) + { + if (seed == null) + { + throw new IllegalArgumentException("'seed' cannot be null"); + } + if (pgenCounter == null) + { + throw new IllegalArgumentException("'pgenCounter' cannot be null"); + } + + this.seed = seed; + this.pgenCounter = pgenCounter; + } + + private ValidationParams(ASN1Sequence seq) + { + if (seq.size() != 2) + { + throw new IllegalArgumentException("Bad sequence size: " + seq.size()); + } + + this.seed = DERBitString.getInstance(seq.getObjectAt(0)); + this.pgenCounter = ASN1Integer.getInstance(seq.getObjectAt(1)); + } + + public byte[] getSeed() + { + return this.seed.getBytes(); + } + + public BigInteger getPgenCounter() + { + return this.pgenCounter.getPositiveValue(); + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + v.add(this.seed); + v.add(this.pgenCounter); + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java index 25312feb..84574a3a 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java @@ -30,7 +30,7 @@ public class X962NamedCurves return new X9ECParameters( cFp192v1, - cFp192v1.decodePoint( + new X9ECPoint(cFp192v1, Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), n, h, Hex.decode("3045AE6FC8422f64ED579528D38120EAE12196D5")); @@ -52,7 +52,7 @@ public class X962NamedCurves return new X9ECParameters( cFp192v2, - cFp192v2.decodePoint( + new X9ECPoint(cFp192v2, Hex.decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")), n, h, Hex.decode("31a92ee2029fd10d901b113e990710f0d21ac6b6")); @@ -74,7 +74,7 @@ public class X962NamedCurves return new X9ECParameters( cFp192v3, - cFp192v3.decodePoint( + new X9ECPoint(cFp192v3, Hex.decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")), n, h, Hex.decode("c469684435deb378c4b65ca9591e2a5763059a2e")); @@ -96,7 +96,7 @@ public class X962NamedCurves return new X9ECParameters( cFp239v1, - cFp239v1.decodePoint( + new X9ECPoint(cFp239v1, Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), n, h, Hex.decode("e43bb460f0b80cc0c0b075798e948060f8321b7d")); @@ -118,7 +118,7 @@ public class X962NamedCurves return new X9ECParameters( cFp239v2, - cFp239v2.decodePoint( + new X9ECPoint(cFp239v2, Hex.decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")), n, h, Hex.decode("e8b4011604095303ca3b8099982be09fcb9ae616")); @@ -140,7 +140,7 @@ public class X962NamedCurves return new X9ECParameters( cFp239v3, - cFp239v3.decodePoint( + new X9ECPoint(cFp239v3, Hex.decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")), n, h, Hex.decode("7d7374168ffe3471b60a857686a19475d3bfa2ff")); @@ -162,7 +162,7 @@ public class X962NamedCurves return new X9ECParameters( cFp256v1, - cFp256v1.decodePoint( + new X9ECPoint(cFp256v1, Hex.decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")), n, h, Hex.decode("c49d360886e704936a6678e1139d26b7819f7e90")); @@ -188,7 +188,7 @@ public class X962NamedCurves return new X9ECParameters( c2m163v1, - c2m163v1.decodePoint( + new X9ECPoint(c2m163v1, Hex.decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")), c2m163v1n, c2m163v1h, Hex.decode("D2C0FB15760860DEF1EEF4D696E6768756151754")); @@ -211,7 +211,7 @@ public class X962NamedCurves return new X9ECParameters( c2m163v2, - c2m163v2.decodePoint( + new X9ECPoint(c2m163v2, Hex.decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")), c2m163v2n, c2m163v2h, null); @@ -234,7 +234,7 @@ public class X962NamedCurves return new X9ECParameters( c2m163v3, - c2m163v3.decodePoint( + new X9ECPoint(c2m163v3, Hex.decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")), c2m163v3n, c2m163v3h, null); @@ -257,7 +257,7 @@ public class X962NamedCurves return new X9ECParameters( c2m176w1, - c2m176w1.decodePoint( + new X9ECPoint(c2m176w1, Hex.decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")), c2m176w1n, c2m176w1h, null); @@ -280,7 +280,7 @@ public class X962NamedCurves return new X9ECParameters( c2m191v1, - c2m191v1.decodePoint( + new X9ECPoint(c2m191v1, Hex.decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")), c2m191v1n, c2m191v1h, Hex.decode("4E13CA542744D696E67687561517552F279A8C84")); @@ -303,7 +303,7 @@ public class X962NamedCurves return new X9ECParameters( c2m191v2, - c2m191v2.decodePoint( + new X9ECPoint(c2m191v2, Hex.decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")), c2m191v2n, c2m191v2h, null); @@ -326,7 +326,7 @@ public class X962NamedCurves return new X9ECParameters( c2m191v3, - c2m191v3.decodePoint( + new X9ECPoint(c2m191v3, Hex.decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")), c2m191v3n, c2m191v3h, null); @@ -349,7 +349,7 @@ public class X962NamedCurves return new X9ECParameters( c2m208w1, - c2m208w1.decodePoint( + new X9ECPoint(c2m208w1, Hex.decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")), c2m208w1n, c2m208w1h, null); @@ -372,7 +372,7 @@ public class X962NamedCurves return new X9ECParameters( c2m239v1, - c2m239v1.decodePoint( + new X9ECPoint(c2m239v1, Hex.decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")), c2m239v1n, c2m239v1h, null); @@ -395,7 +395,7 @@ public class X962NamedCurves return new X9ECParameters( c2m239v2, - c2m239v2.decodePoint( + new X9ECPoint(c2m239v2, Hex.decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")), c2m239v2n, c2m239v2h, null); @@ -418,7 +418,7 @@ public class X962NamedCurves return new X9ECParameters( c2m239v3, - c2m239v3.decodePoint( + new X9ECPoint(c2m239v3, Hex.decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")), c2m239v3n, c2m239v3h, null); @@ -441,7 +441,7 @@ public class X962NamedCurves return new X9ECParameters( c2m272w1, - c2m272w1.decodePoint( + new X9ECPoint(c2m272w1, Hex.decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")), c2m272w1n, c2m272w1h, null); @@ -464,7 +464,7 @@ public class X962NamedCurves return new X9ECParameters( c2m304w1, - c2m304w1.decodePoint( + new X9ECPoint(c2m304w1, Hex.decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")), c2m304w1n, c2m304w1h, null); @@ -487,7 +487,7 @@ public class X962NamedCurves return new X9ECParameters( c2m359v1, - c2m359v1.decodePoint( + new X9ECPoint(c2m359v1, Hex.decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")), c2m359v1n, c2m359v1h, null); @@ -510,7 +510,7 @@ public class X962NamedCurves return new X9ECParameters( c2m368w1, - c2m368w1.decodePoint( + new X9ECPoint(c2m368w1, Hex.decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")), c2m368w1n, c2m368w1h, null); @@ -533,7 +533,7 @@ public class X962NamedCurves return new X9ECParameters( c2m431r1, - c2m431r1.decodePoint( + new X9ECPoint(c2m431r1, Hex.decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")), c2m431r1n, c2m431r1h, null); @@ -546,7 +546,7 @@ public class X962NamedCurves static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder) { - objIds.put(name, oid); + objIds.put(name.toLowerCase(), oid); names.put(oid, name); curves.put(oid, holder); } @@ -581,14 +581,8 @@ public class X962NamedCurves public static X9ECParameters getByName( String name) { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name)); - - if (oid != null) - { - return getByOID(oid); - } - - return null; + ASN1ObjectIdentifier oid = getOID(name); + return oid == null ? null : getByOID(oid); } /** @@ -601,13 +595,7 @@ public class X962NamedCurves ASN1ObjectIdentifier oid) { X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid); - - if (holder != null) - { - return holder.getParameters(); - } - - return null; + return holder == null ? null : holder.getParameters(); } /** @@ -637,6 +625,6 @@ public class X962NamedCurves */ public static Enumeration getNames() { - return objIds.keys(); + return names.elements(); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java index a4348dec..a06aa85f 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java @@ -1,5 +1,7 @@ package org.bouncycastle.asn1.x9; +import java.io.IOException; + import org.bouncycastle.asn1.ASN1Choice; import org.bouncycastle.asn1.ASN1Null; import org.bouncycastle.asn1.ASN1Object; @@ -7,6 +9,9 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1TaggedObject; +/** + * The Parameters ASN.1 CHOICE from X9.62. + */ public class X962Parameters extends ASN1Object implements ASN1Choice @@ -25,7 +30,19 @@ public class X962Parameters { return new X962Parameters((ASN1Primitive)obj); } - + + if (obj instanceof byte[]) + { + try + { + return new X962Parameters(ASN1Primitive.fromByteArray((byte[])obj)); + } + catch (IOException e) + { + throw new IllegalArgumentException("unable to parse encoded data: " + e.getMessage()); + } + } + throw new IllegalArgumentException("unknown object in getInstance()"); } @@ -49,6 +66,15 @@ public class X962Parameters } public X962Parameters( + ASN1Null obj) + { + this.params = obj; + } + + /** + * @deprecated use getInstance() + */ + public X962Parameters( ASN1Primitive obj) { this.params = obj; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java index 302c1300..85163651 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java @@ -26,7 +26,7 @@ public class X9ECParameters private X9FieldID fieldID; private ECCurve curve; - private ECPoint g; + private X9ECPoint g; private BigInteger n; private BigInteger h; private byte[] seed; @@ -49,11 +49,11 @@ public class X9ECParameters if (p instanceof X9ECPoint) { - this.g = ((X9ECPoint)p).getPoint(); + this.g = ((X9ECPoint)p); } else { - this.g = new X9ECPoint(curve, (ASN1OctetString)p).getPoint(); + this.g = new X9ECPoint(curve, (ASN1OctetString)p); } this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue(); @@ -85,7 +85,16 @@ public class X9ECParameters ECPoint g, BigInteger n) { - this(curve, g, n, ONE, null); + this(curve, g, n, null, null); + } + + public X9ECParameters( + ECCurve curve, + X9ECPoint g, + BigInteger n, + BigInteger h) + { + this(curve, g, n, h, null); } public X9ECParameters( @@ -104,8 +113,18 @@ public class X9ECParameters BigInteger h, byte[] seed) { + this(curve, new X9ECPoint(g), n, h, seed); + } + + public X9ECParameters( + ECCurve curve, + X9ECPoint g, + BigInteger n, + BigInteger h, + byte[] seed) + { this.curve = curve; - this.g = g.normalize(); + this.g = g; this.n = n; this.h = h; this.seed = seed; @@ -144,7 +163,7 @@ public class X9ECParameters public ECPoint getG() { - return g; + return g.getPoint(); } public BigInteger getN() @@ -154,11 +173,6 @@ public class X9ECParameters public BigInteger getH() { - if (h == null) - { - return ONE; // TODO - this should be calculated, it will cause issues with custom curves. - } - return h; } @@ -168,6 +182,36 @@ public class X9ECParameters } /** + * Return the ASN.1 entry representing the Curve. + * + * @return the X9Curve for the curve in these parameters. + */ + public X9Curve getCurveEntry() + { + return new X9Curve(curve, seed); + } + + /** + * Return the ASN.1 entry representing the FieldID. + * + * @return the X9FieldID for the FieldID in these parameters. + */ + public X9FieldID getFieldIDEntry() + { + return fieldID; + } + + /** + * Return the ASN.1 entry representing the base point G. + * + * @return the X9ECPoint for the base point in these parameters. + */ + public X9ECPoint getBaseEntry() + { + return g; + } + + /** * Produce an object suitable for an ASN1OutputStream. * <pre> * ECParameters ::= SEQUENCE { @@ -184,10 +228,10 @@ public class X9ECParameters { ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(new ASN1Integer(1)); + v.add(new ASN1Integer(ONE)); v.add(fieldID); v.add(new X9Curve(curve, seed)); - v.add(new X9ECPoint(g)); + v.add(g); v.add(new ASN1Integer(n)); if (h != null) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java index 47361f89..96130c6a 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java @@ -4,7 +4,7 @@ public abstract class X9ECParametersHolder { private X9ECParameters params; - public X9ECParameters getParameters() + public synchronized X9ECParameters getParameters() { if (params == null) { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java index cbb91160..57b0fda4 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java @@ -6,6 +6,7 @@ import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.util.Arrays; /** * class for describing an ECPoint as a DER object. @@ -13,26 +14,61 @@ import org.bouncycastle.math.ec.ECPoint; public class X9ECPoint extends ASN1Object { - ECPoint p; + private final ASN1OctetString encoding; + + private ECCurve c; + private ECPoint p; public X9ECPoint( ECPoint p) { + this(p, false); + } + + public X9ECPoint( + ECPoint p, + boolean compressed) + { this.p = p.normalize(); + this.encoding = new DEROctetString(p.getEncoded(compressed)); + } + + public X9ECPoint( + ECCurve c, + byte[] encoding) + { + this.c = c; + this.encoding = new DEROctetString(Arrays.clone(encoding)); } public X9ECPoint( ECCurve c, ASN1OctetString s) { - this.p = c.decodePoint(s.getOctets()); + this(c, s.getOctets()); + } + + public byte[] getPointEncoding() + { + return Arrays.clone(encoding.getOctets()); } public ECPoint getPoint() { + if (p == null) + { + p = c.decodePoint(encoding.getOctets()).normalize(); + } + return p; } + public boolean isPointCompressed() + { + byte[] octets = encoding.getOctets(); + return octets != null && octets.length > 0 && (octets[0] == 2 || octets[0] == 3); + } + /** * Produce an object suitable for an ASN1OutputStream. * <pre> @@ -43,6 +79,6 @@ public class X9ECPoint */ public ASN1Primitive toASN1Primitive() { - return new DEROctetString(p.getEncoded()); + return encoding; } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java index 53a4373c..1317b4ab 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java @@ -204,4 +204,21 @@ public interface X9ObjectIdentifiers static final ASN1ObjectIdentifier mqv2 = x9_42_schemes.branch("7"); /** X9.42 MQV1 OID: 1.2.840.10046.3.8 */ static final ASN1ObjectIdentifier mqv1 = x9_42_schemes.branch("8"); + + /** + * X9.44 + * <pre> + * x9-44 OID ::= { + * iso(1) identified-organization(3) tc68(133) country(16) x9(840) + * x9Standards(9) x9-44(44) + * } + * </pre> + */ + + ASN1ObjectIdentifier x9_44 = new ASN1ObjectIdentifier("1.3.133.16.840.9.44"); + + ASN1ObjectIdentifier x9_44_components = x9_44.branch("1"); + + ASN1ObjectIdentifier id_kdf_kdf2 = x9_44_components.branch("1"); + ASN1ObjectIdentifier id_kdf_kdf3 = x9_44_components.branch("2"); } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java index 39f59da8..8ab2cdc5 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java @@ -115,7 +115,14 @@ public class BufferedBlockCipher if (pgpCFB) { - leftOver = total % buf.length - (cipher.getBlockSize() + 2); + if (forEncryption) + { + leftOver = total % buf.length - (cipher.getBlockSize() + 2); + } + else + { + leftOver = total % buf.length; + } } else { diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java index 29692bad..011e97c5 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java @@ -70,39 +70,44 @@ public abstract class GeneralDigest int inOff, int len) { + len = Math.max(0, len); + // // fill the current word // - while ((xBufOff != 0) && (len > 0)) + int i = 0; + if (xBufOff != 0) { - update(in[inOff]); - - inOff++; - len--; + while (i < len) + { + xBuf[xBufOff++] = in[inOff + i++]; + if (xBufOff == 4) + { + processWord(xBuf, 0); + xBufOff = 0; + break; + } + } } // // process whole words. // - while (len > xBuf.length) + int limit = ((len - i) & ~3) + i; + for (; i < limit; i += 4) { - processWord(in, inOff); - - inOff += xBuf.length; - len -= xBuf.length; - byteCount += xBuf.length; + processWord(in, inOff + i); } // // load in the remainder. // - while (len > 0) + while (i < len) { - update(in[inOff]); - - inOff++; - len--; + xBuf[xBufOff++] = in[inOff + i++]; } + + byteCount += len; } public void finish() diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java index 3b4b2e6e..e3c596d9 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java @@ -3,15 +3,21 @@ package org.bouncycastle.crypto.ec; import java.math.BigInteger; import java.util.Enumeration; import java.util.Hashtable; +import java.util.Vector; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ECParametersHolder; +import org.bouncycastle.asn1.x9.X9ECPoint; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; // BEGIN android-removed // import org.bouncycastle.math.ec.custom.djb.Curve25519; +// import org.bouncycastle.math.ec.custom.sec.SecP128R1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecP160K1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecP160R1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecP160R2Curve; // END android-removed import org.bouncycastle.math.ec.custom.sec.SecP192K1Curve; import org.bouncycastle.math.ec.custom.sec.SecP192R1Curve; @@ -21,6 +27,26 @@ import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve; import org.bouncycastle.math.ec.custom.sec.SecP256R1Curve; import org.bouncycastle.math.ec.custom.sec.SecP384R1Curve; import org.bouncycastle.math.ec.custom.sec.SecP521R1Curve; +// BEGIN android-removed +// import org.bouncycastle.math.ec.custom.sec.SecT113R1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT113R2Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT131R1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT131R2Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT163K1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT163R1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT163R2Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT193R1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT193R2Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT233K1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT233R1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT239K1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT283K1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT283R1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT409K1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT409R1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT571K1Curve; +// import org.bouncycastle.math.ec.custom.sec.SecT571R1Curve; +// END android-removed import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism; import org.bouncycastle.math.ec.endo.GLVTypeBParameters; import org.bouncycastle.util.Strings; @@ -44,24 +70,100 @@ public class CustomNamedCurves // */ // static X9ECParametersHolder curve25519 = new X9ECParametersHolder() // { + // protected X9ECParameters createParameters() + // { + // byte[] S = null; + // ECCurve curve = configureCurve(new Curve25519()); + // + // /* + // * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form + // * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3). + // * + // * The Curve25519 paper doesn't say which of the two possible y values the base + // * point has. The choice here is guided by language in the Ed25519 paper. + // * + // * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14) + // */ + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A" + // + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9")); + // + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + // + // /* + // * secp128r1 + // */ + // static X9ECParametersHolder secp128r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679"); + // ECCurve curve = configureCurve(new SecP128R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "161FF7528B899B2D0C28607CA52C5B86" + // + "CF5AC8395BAFEB13C02DA292DDED7A83")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + // + // /* + // * secp160k1 + // */ + // static X9ECParametersHolder secp160k1 = new X9ECParametersHolder() + // { // protected X9ECParameters createParameters() // { // byte[] S = null; - // ECCurve curve = configureCurve(new Curve25519()); + // GLVTypeBParameters glv = new GLVTypeBParameters( + // new BigInteger("9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a", 16), + // new BigInteger("c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4", 16), + // new BigInteger[]{ + // new BigInteger("9162fbe73984472a0a9e", 16), + // new BigInteger("-96341f1138933bc2f505", 16) }, + // new BigInteger[]{ + // new BigInteger("127971af8721782ecffa3", 16), + // new BigInteger("9162fbe73984472a0a9e", 16) }, + // new BigInteger("9162fbe73984472a0a9d0590", 16), + // new BigInteger("96341f1138933bc2f503fd44", 16), + // 176); + // ECCurve curve = configureCurveGLV(new SecP160K1Curve(), glv); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB" + // + "938CF935318FDCED6BC28286531733C3F03C4FEE")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; // - // /* - // * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form - // * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3). - // * - // * The Curve25519 paper doesn't say which of the two possible y values the base - // * point has. The choice here is guided by language in the Ed25519 paper. - // * - // * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14) - // */ - // ECPoint G = curve.decodePoint(Hex.decode("04" - // + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A" - // + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9")); + // /* + // * secp160r1 + // */ + // static X9ECParametersHolder secp160r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345"); + // ECCurve curve = configureCurve(new SecP160R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "4A96B5688EF573284664698968C38BB913CBFC82" + // + "23A628553168947D59DCC912042351377AC5FB32")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; // + // /* + // * secp160r2 + // */ + // static X9ECParametersHolder secp160r2 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("B99B99B099B323E02709A4D696E6768756151751"); + // ECCurve curve = configureCurve(new SecP160R2Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "52DCB034293A117E1F4FF11B30F7199D3144CE6D" + // + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E")); // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); // } // }; @@ -88,7 +190,7 @@ public class CustomNamedCurves new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16), 208); ECCurve curve = configureCurveGLV(new SecP192K1Curve(), glv); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D" + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D")); return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); @@ -104,7 +206,7 @@ public class CustomNamedCurves { byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5"); ECCurve curve = configureCurve(new SecP192R1Curve()); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")); return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); @@ -132,7 +234,7 @@ public class CustomNamedCurves new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16), 240); ECCurve curve = configureCurveGLV(new SecP224K1Curve(), glv); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C" + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5")); return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); @@ -148,7 +250,7 @@ public class CustomNamedCurves { byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5"); ECCurve curve = configureCurve(new SecP224R1Curve()); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")); return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); @@ -176,7 +278,7 @@ public class CustomNamedCurves new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16), 272); ECCurve curve = configureCurveGLV(new SecP256K1Curve(), glv); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")); return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); @@ -192,7 +294,7 @@ public class CustomNamedCurves { byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90"); ECCurve curve = configureCurve(new SecP256R1Curve()); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")); return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); @@ -208,7 +310,7 @@ public class CustomNamedCurves { byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73"); ECCurve curve = configureCurve(new SecP384R1Curve()); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7" + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")); return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); @@ -224,36 +326,338 @@ public class CustomNamedCurves { byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA"); ECCurve curve = configureCurve(new SecP521R1Curve()); - ECPoint G = curve.decodePoint(Hex.decode("04" + X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650")); return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); } }; + // BEGIN android-removed + // /* + // * sect113r1 + // */ + // static X9ECParametersHolder sect113r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("10E723AB14D696E6768756151756FEBF8FCB49A9"); + // ECCurve curve = configureCurve(new SecT113R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "009D73616F35F4AB1407D73562C10F" + // + "00A52830277958EE84D1315ED31886")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect113r2 + // */ + // static X9ECParametersHolder sect113r2 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("10C0FB15760860DEF1EEF4D696E676875615175D"); + // ECCurve curve = configureCurve(new SecT113R2Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "01A57A6A7B26CA5EF52FCDB8164797" + // + "00B3ADC94ED1FE674C06E695BABA1D")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect131r1 + // */ + // static X9ECParametersHolder sect131r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("4D696E676875615175985BD3ADBADA21B43A97E2"); + // ECCurve curve = configureCurve(new SecT131R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "0081BAF91FDF9833C40F9C181343638399" + // + "078C6E7EA38C001F73C8134B1B4EF9E150")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect131r2 + // */ + // static X9ECParametersHolder sect131r2 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("985BD3ADBAD4D696E676875615175A21B43A97E3"); + // ECCurve curve = configureCurve(new SecT131R2Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "0356DCD8F2F95031AD652D23951BB366A8" + // + "0648F06D867940A5366D9E265DE9EB240F")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect163k1 + // */ + // static X9ECParametersHolder sect163k1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = null; + // ECCurve curve = configureCurve(new SecT163K1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8" + // + "0289070FB05D38FF58321F2E800536D538CCDAA3D9")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect163r1 + // */ + // static X9ECParametersHolder sect163r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("24B7B137C8A14D696E6768756151756FD0DA2E5C"); + // ECCurve curve = configureCurve(new SecT163R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "0369979697AB43897789566789567F787A7876A654" + // + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect163r2 + // */ + // static X9ECParametersHolder sect163r2 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("85E25BFE5C86226CDB12016F7553F9D0E693A268"); + // ECCurve curve = configureCurve(new SecT163R2Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "03F0EBA16286A2D57EA0991168D4994637E8343E36" + // + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect193r1 + // */ + // static X9ECParametersHolder sect193r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("103FAEC74D696E676875615175777FC5B191EF30"); + // ECCurve curve = configureCurve(new SecT193R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1" + // + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect193r2 + // */ + // static X9ECParametersHolder sect193r2 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("10B7B4D696E676875615175137C8A16FD0DA2211"); + // ECCurve curve = configureCurve(new SecT193R2Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F" + // + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect233k1 + // */ + // static X9ECParametersHolder sect233k1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = null; + // ECCurve curve = configureCurve(new SecT233K1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126" + // + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect233r1 + // */ + // static X9ECParametersHolder sect233r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3"); + // ECCurve curve = configureCurve(new SecT233R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B" + // + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect239k1 + // */ + // static X9ECParametersHolder sect239k1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = null; + // ECCurve curve = configureCurve(new SecT239K1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC" + // + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect283k1 + // */ + // static X9ECParametersHolder sect283k1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = null; + // ECCurve curve = configureCurve(new SecT283K1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836" + // + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect283r1 + // */ + // static X9ECParametersHolder sect283r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE"); + // ECCurve curve = configureCurve(new SecT283R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053" + // + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect409k1 + // */ + // static X9ECParametersHolder sect409k1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = null; + // ECCurve curve = configureCurve(new SecT409K1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746" + // + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect409r1 + // */ + // static X9ECParametersHolder sect409r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("4099B5A457F9D69F79213D094C4BCD4D4262210B"); + // ECCurve curve = configureCurve(new SecT409R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7" + // + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect571k1 + // */ + // static X9ECParametersHolder sect571k1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = null; + // ECCurve curve = configureCurve(new SecT571K1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972" + // + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + + // /* + // * sect571r1 + // */ + // static X9ECParametersHolder sect571r1 = new X9ECParametersHolder() + // { + // protected X9ECParameters createParameters() + // { + // byte[] S = Hex.decode("2AA058F73A0E33AB486B0F610410C53A7F132310"); + // ECCurve curve = configureCurve(new SecT571R1Curve()); + // X9ECPoint G = new X9ECPoint(curve, Hex.decode("04" + // + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19" + // + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B")); + // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + // } + // }; + // END android-removed + + static final Hashtable nameToCurve = new Hashtable(); static final Hashtable nameToOID = new Hashtable(); static final Hashtable oidToCurve = new Hashtable(); static final Hashtable oidToName = new Hashtable(); + static final Vector names = new Vector(); static void defineCurve(String name, X9ECParametersHolder holder) { + names.addElement(name); + name = Strings.toLowerCase(name); nameToCurve.put(name, holder); } static void defineCurveWithOID(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder) { - nameToCurve.put(name, holder); - nameToOID.put(name, oid); + names.addElement(name); oidToName.put(oid, name); oidToCurve.put(oid, holder); + name = Strings.toLowerCase(name); + nameToOID.put(name, oid); + nameToCurve.put(name, holder); } - static void defineCurveAlias(String alias, ASN1ObjectIdentifier oid) + static void defineCurveAlias(String name, ASN1ObjectIdentifier oid) { - alias = Strings.toLowerCase(alias); - nameToOID.put(alias, oid); - nameToCurve.put(alias, oidToCurve.get(oid)); + Object curve = oidToCurve.get(oid); + if (curve == null) + { + throw new IllegalStateException(); + } + + name = Strings.toLowerCase(name); + nameToOID.put(name, oid); + nameToCurve.put(name, curve); } static @@ -262,6 +666,17 @@ public class CustomNamedCurves // defineCurve("curve25519", curve25519); // END android-removed +// defineCurveWithOID("secp112r1", SECObjectIdentifiers.secp112r1, secp112r1); +// defineCurveWithOID("secp112r2", SECObjectIdentifiers.secp112r2, secp112r2); + // BEGIN android-removed + // defineCurveWithOID("secp128r1", SECObjectIdentifiers.secp128r1, secp128r1); + // END android-removed +// defineCurveWithOID("secp128r2", SECObjectIdentifiers.secp128r2, secp128r2); + // BEGIN android-removed + // defineCurveWithOID("secp160k1", SECObjectIdentifiers.secp160k1, secp160k1); + // defineCurveWithOID("secp160r1", SECObjectIdentifiers.secp160r1, secp160r1); + // defineCurveWithOID("secp160r2", SECObjectIdentifiers.secp160r2, secp160r2); + // END android-removed defineCurveWithOID("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1); defineCurveWithOID("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1); defineCurveWithOID("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1); @@ -271,6 +686,39 @@ public class CustomNamedCurves defineCurveWithOID("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1); defineCurveWithOID("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1); + // BEGIN android-removed + // defineCurveWithOID("sect113r1", SECObjectIdentifiers.sect113r1, sect113r1); + // defineCurveWithOID("sect113r2", SECObjectIdentifiers.sect113r2, sect113r2); + // defineCurveWithOID("sect131r1", SECObjectIdentifiers.sect131r1, sect131r1); + // defineCurveWithOID("sect131r2", SECObjectIdentifiers.sect131r2, sect131r2); + // defineCurveWithOID("sect163k1", SECObjectIdentifiers.sect163k1, sect163k1); + // defineCurveWithOID("sect163r1", SECObjectIdentifiers.sect163r1, sect163r1); + // defineCurveWithOID("sect163r2", SECObjectIdentifiers.sect163r2, sect163r2); + // defineCurveWithOID("sect193r1", SECObjectIdentifiers.sect193r1, sect193r1); + // defineCurveWithOID("sect193r2", SECObjectIdentifiers.sect193r2, sect193r2); + // defineCurveWithOID("sect233k1", SECObjectIdentifiers.sect233k1, sect233k1); + // defineCurveWithOID("sect233r1", SECObjectIdentifiers.sect233r1, sect233r1); + // defineCurveWithOID("sect239k1", SECObjectIdentifiers.sect239k1, sect239k1); + // defineCurveWithOID("sect283k1", SECObjectIdentifiers.sect283k1, sect283k1); + // defineCurveWithOID("sect283r1", SECObjectIdentifiers.sect283r1, sect283r1); + // defineCurveWithOID("sect409k1", SECObjectIdentifiers.sect409k1, sect409k1); + // defineCurveWithOID("sect409r1", SECObjectIdentifiers.sect409r1, sect409r1); + // defineCurveWithOID("sect571k1", SECObjectIdentifiers.sect571k1, sect571k1); + // defineCurveWithOID("sect571r1", SECObjectIdentifiers.sect571r1, sect571r1); + + // defineCurveAlias("B-163", SECObjectIdentifiers.sect163r2); + // defineCurveAlias("B-233", SECObjectIdentifiers.sect233r1); + // defineCurveAlias("B-283", SECObjectIdentifiers.sect283r1); + // defineCurveAlias("B-409", SECObjectIdentifiers.sect409r1); + // defineCurveAlias("B-571", SECObjectIdentifiers.sect571r1); + + // defineCurveAlias("K-163", SECObjectIdentifiers.sect163k1); + // defineCurveAlias("K-233", SECObjectIdentifiers.sect233k1); + // defineCurveAlias("K-283", SECObjectIdentifiers.sect283k1); + // defineCurveAlias("K-409", SECObjectIdentifiers.sect409k1); + // defineCurveAlias("K-571", SECObjectIdentifiers.sect571k1); + // END android-removed + defineCurveAlias("P-192", SECObjectIdentifiers.secp192r1); defineCurveAlias("P-224", SECObjectIdentifiers.secp224r1); defineCurveAlias("P-256", SECObjectIdentifiers.secp256r1); @@ -321,6 +769,6 @@ public class CustomNamedCurves */ public static Enumeration getNames() { - return nameToCurve.keys(); + return names.elements(); } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java index 7ba71c73..71ca7f7d 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java @@ -18,15 +18,20 @@ public class PKCS1Encoding implements AsymmetricBlockCipher { /** + * @deprecated use NOT_STRICT_LENGTH_ENABLED_PROPERTY + */ + public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.strict"; + + /** * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to - * work with one of these set the system property org.bouncycastle.pkcs1.strict to false. + * work with one of these set the system property org.bouncycastle.pkcs1.not_strict to true. * <p> - * The system property is checked during construction of the encoding object, it is set to - * true by default. + * The system property is checked during construction of the encoding object, it is set to + * false by default. * </p> */ - public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.strict"; - + public static final String NOT_STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.not_strict"; + private static final int HEADER_LENGTH = 10; private SecureRandom random; @@ -97,6 +102,18 @@ public class PKCS1Encoding return System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY); } }); + String notStrict = (String)AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + return System.getProperty(NOT_STRICT_LENGTH_ENABLED_PROPERTY); + } + }); + + if (notStrict != null) + { + return !notStrict.equals("true"); + } return strict == null || strict.equals("true"); } @@ -121,8 +138,11 @@ public class PKCS1Encoding } else { - this.random = new SecureRandom(); kParam = (AsymmetricKeyParameter)param; + if (!kParam.isPrivate() && forEncryption) + { + this.random = new SecureRandom(); + } } engine.init(forEncryption, param); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java index a0fd0840..924dff35 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java @@ -5,6 +5,7 @@ import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.util.Pack; /** * an implementation of the AES (Rijndael), from FIPS-197. @@ -230,12 +231,22 @@ private static final int[] Tinv0 = private static final int m1 = 0x80808080; private static final int m2 = 0x7f7f7f7f; private static final int m3 = 0x0000001b; + private static final int m4 = 0xC0C0C0C0; + private static final int m5 = 0x3f3f3f3f; private static int FFmulX(int x) { return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3)); } + private static int FFmulX2(int x) + { + int t0 = (x & m5) << 2; + int t1 = (x & m4); + t1 ^= (t1 >>> 1); + return t0 ^ (t1 >>> 2) ^ (t1 >>> 5); + } + /* The following defines provide alternative definitions of FFmulX that might give improved performance if a fast 32-bit multiply is not available. @@ -248,12 +259,13 @@ private static final int[] Tinv0 = private static int inv_mcol(int x) { - int f2 = FFmulX(x); - int f4 = FFmulX(f2); - int f8 = FFmulX(f4); - int f9 = x ^ f8; - - return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24); + int t0, t1; + t0 = x; + t1 = t0 ^ shift(t0, 8); + t0 ^= FFmulX(t1); + t1 ^= FFmulX2(t0); + t0 ^= t1 ^ shift(t1, 16); + return t0; } private static int subWord(int x) @@ -267,59 +279,128 @@ private static final int[] Tinv0 = * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits * This code is written assuming those are the only possible values */ - private int[][] generateWorkingKey( - byte[] key, - boolean forEncryption) + private int[][] generateWorkingKey(byte[] key, boolean forEncryption) { - int KC = key.length / 4; // key length in words - int t; - - if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length)) + int keyLen = key.length; + if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0) { throw new IllegalArgumentException("Key length not 128/192/256 bits."); } + int KC = keyLen >>> 2; ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes int[][] W = new int[ROUNDS+1][4]; // 4 words in a block - - // - // copy the key into the round key array - // - - t = 0; - int i = 0; - while (i < key.length) + + switch (KC) + { + case 4: + { + int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0; + int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1; + int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2; + int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3; + + for (int i = 1; i <= 10; ++i) { - W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24); - i+=4; - t++; + int u = subWord(shift(t3, 8)) ^ rcon[i - 1]; + t0 ^= u; W[i][0] = t0; + t1 ^= t0; W[i][1] = t1; + t2 ^= t1; W[i][2] = t2; + t3 ^= t2; W[i][3] = t3; } - - // - // while not enough round key material calculated - // calculate new values - // - int k = (ROUNDS + 1) << 2; - for (i = KC; (i < k); i++) + + break; + } + case 6: + { + int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0; + int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1; + int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2; + int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3; + int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4; + int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5; + + int rcon = 1; + int u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[1][2] = t0; + t1 ^= t0; W[1][3] = t1; + t2 ^= t1; W[2][0] = t2; + t3 ^= t2; W[2][1] = t3; + t4 ^= t3; W[2][2] = t4; + t5 ^= t4; W[2][3] = t5; + + for (int i = 3; i < 12; i += 3) { - int temp = W[(i-1)>>2][(i-1)&3]; - if ((i % KC) == 0) - { - temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1]; - } - else if ((KC > 6) && ((i % KC) == 4)) - { - temp = subWord(temp); - } - - W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp; + u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i ][0] = t0; + t1 ^= t0; W[i ][1] = t1; + t2 ^= t1; W[i ][2] = t2; + t3 ^= t2; W[i ][3] = t3; + t4 ^= t3; W[i + 1][0] = t4; + t5 ^= t4; W[i + 1][1] = t5; + u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i + 1][2] = t0; + t1 ^= t0; W[i + 1][3] = t1; + t2 ^= t1; W[i + 2][0] = t2; + t3 ^= t2; W[i + 2][1] = t3; + t4 ^= t3; W[i + 2][2] = t4; + t5 ^= t4; W[i + 2][3] = t5; } + u = subWord(shift(t5, 8)) ^ rcon; + t0 ^= u; W[12][0] = t0; + t1 ^= t0; W[12][1] = t1; + t2 ^= t1; W[12][2] = t2; + t3 ^= t2; W[12][3] = t3; + + break; + } + case 8: + { + int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0; + int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1; + int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2; + int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3; + int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4; + int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5; + int t6 = Pack.littleEndianToInt(key, 24); W[1][2] = t6; + int t7 = Pack.littleEndianToInt(key, 28); W[1][3] = t7; + + int u, rcon = 1; + + for (int i = 2; i < 14; i += 2) + { + u = subWord(shift(t7, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i ][0] = t0; + t1 ^= t0; W[i ][1] = t1; + t2 ^= t1; W[i ][2] = t2; + t3 ^= t2; W[i ][3] = t3; + u = subWord(t3); + t4 ^= u; W[i + 1][0] = t4; + t5 ^= t4; W[i + 1][1] = t5; + t6 ^= t5; W[i + 1][2] = t6; + t7 ^= t6; W[i + 1][3] = t7; + } + + u = subWord(shift(t7, 8)) ^ rcon; + t0 ^= u; W[14][0] = t0; + t1 ^= t0; W[14][1] = t1; + t2 ^= t1; W[14][2] = t2; + t3 ^= t2; W[14][3] = t3; + + break; + } + default: + { + throw new IllegalStateException("Should never get here"); + } + } + if (!forEncryption) { for (int j = 1; j < ROUNDS; j++) { - for (i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { W[j][i] = inv_mcol(W[j][i]); } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java index e2b00d3a..11e1bce8 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java @@ -557,12 +557,22 @@ public class AESFastEngine private static final int m1 = 0x80808080; private static final int m2 = 0x7f7f7f7f; private static final int m3 = 0x0000001b; + private static final int m4 = 0xC0C0C0C0; + private static final int m5 = 0x3f3f3f3f; private static int FFmulX(int x) { return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3)); } + private static int FFmulX2(int x) + { + int t0 = (x & m5) << 2; + int t1 = (x & m4); + t1 ^= (t1 >>> 1); + return t0 ^ (t1 >>> 2) ^ (t1 >>> 5); + } + /* The following defines provide alternative definitions of FFmulX that might give improved performance if a fast 32-bit multiply is not available. @@ -575,12 +585,13 @@ public class AESFastEngine private static int inv_mcol(int x) { - int f2 = FFmulX(x); - int f4 = FFmulX(f2); - int f8 = FFmulX(f4); - int f9 = x ^ f8; - - return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24); + int t0, t1; + t0 = x; + t1 = t0 ^ shift(t0, 8); + t0 ^= FFmulX(t1); + t1 ^= FFmulX2(t0); + t0 ^= t1 ^ shift(t1, 16); + return t0; } private static int subWord(int x) @@ -596,59 +607,128 @@ public class AESFastEngine * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits * This code is written assuming those are the only possible values */ - private int[][] generateWorkingKey( - byte[] key, - boolean forEncryption) + private int[][] generateWorkingKey(byte[] key, boolean forEncryption) { - int KC = key.length / 4; // key length in words - int t; - - if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length)) + int keyLen = key.length; + if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0) { throw new IllegalArgumentException("Key length not 128/192/256 bits."); } + int KC = keyLen >>> 2; ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes int[][] W = new int[ROUNDS+1][4]; // 4 words in a block - - // - // copy the key into the round key array - // - - t = 0; - int i = 0; - while (i < key.length) + + switch (KC) + { + case 4: { - W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24); - i+=4; - t++; + int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0; + int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1; + int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2; + int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3; + + for (int i = 1; i <= 10; ++i) + { + int u = subWord(shift(t3, 8)) ^ rcon[i - 1]; + t0 ^= u; W[i][0] = t0; + t1 ^= t0; W[i][1] = t1; + t2 ^= t1; W[i][2] = t2; + t3 ^= t2; W[i][3] = t3; + } + + break; } - - // - // while not enough round key material calculated - // calculate new values - // - int k = (ROUNDS + 1) << 2; - for (i = KC; (i < k); i++) + case 6: { - int temp = W[(i - 1) >> 2][(i - 1) & 3]; - if ((i % KC) == 0) + int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0; + int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1; + int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2; + int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3; + int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4; + int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5; + + int rcon = 1; + int u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[1][2] = t0; + t1 ^= t0; W[1][3] = t1; + t2 ^= t1; W[2][0] = t2; + t3 ^= t2; W[2][1] = t3; + t4 ^= t3; W[2][2] = t4; + t5 ^= t4; W[2][3] = t5; + + for (int i = 3; i < 12; i += 3) { - temp = subWord(shift(temp, 8)) ^ rcon[(i / KC) - 1]; + u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i ][0] = t0; + t1 ^= t0; W[i ][1] = t1; + t2 ^= t1; W[i ][2] = t2; + t3 ^= t2; W[i ][3] = t3; + t4 ^= t3; W[i + 1][0] = t4; + t5 ^= t4; W[i + 1][1] = t5; + u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i + 1][2] = t0; + t1 ^= t0; W[i + 1][3] = t1; + t2 ^= t1; W[i + 2][0] = t2; + t3 ^= t2; W[i + 2][1] = t3; + t4 ^= t3; W[i + 2][2] = t4; + t5 ^= t4; W[i + 2][3] = t5; } - else if ((KC > 6) && ((i % KC) == 4)) + + u = subWord(shift(t5, 8)) ^ rcon; + t0 ^= u; W[12][0] = t0; + t1 ^= t0; W[12][1] = t1; + t2 ^= t1; W[12][2] = t2; + t3 ^= t2; W[12][3] = t3; + + break; + } + case 8: + { + int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0; + int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1; + int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2; + int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3; + int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4; + int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5; + int t6 = Pack.littleEndianToInt(key, 24); W[1][2] = t6; + int t7 = Pack.littleEndianToInt(key, 28); W[1][3] = t7; + + int u, rcon = 1; + + for (int i = 2; i < 14; i += 2) { - temp = subWord(temp); + u = subWord(shift(t7, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i ][0] = t0; + t1 ^= t0; W[i ][1] = t1; + t2 ^= t1; W[i ][2] = t2; + t3 ^= t2; W[i ][3] = t3; + u = subWord(t3); + t4 ^= u; W[i + 1][0] = t4; + t5 ^= t4; W[i + 1][1] = t5; + t6 ^= t5; W[i + 1][2] = t6; + t7 ^= t6; W[i + 1][3] = t7; } - W[i >> 2][i & 3] = W[(i - KC) >> 2][(i - KC) & 3] ^ temp; + u = subWord(shift(t7, 8)) ^ rcon; + t0 ^= u; W[14][0] = t0; + t1 ^= t0; W[14][1] = t1; + t2 ^= t1; W[14][2] = t2; + t3 ^= t2; W[14][3] = t3; + + break; + } + default: + { + throw new IllegalStateException("Should never get here"); + } } if (!forEncryption) { for (int j = 1; j < ROUNDS; j++) { - for (i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { W[j][i] = inv_mcol(W[j][i]); } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java index 197b151b..ba75c8d7 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java @@ -17,12 +17,11 @@ import org.bouncycastle.util.Arrays; /** * Wrap keys according to - * <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-smime-key-wrap-01.txt"> - * draft-ietf-smime-key-wrap-01.txt</A>. + * <A HREF="https://www.ietf.org/rfc/rfc3217.txt"> + * RFC 3217</A>. * <p> * Note: * <ul> - * <li>this is based on a draft, and as such is subject to change - don't use this class for anything requiring long term storage. * <li>if you are using this to wrap triple-des keys you need to set the * parity bits on the key and, if it's a two-key triple-des key, pad it * yourself. diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java index c9765bf8..d74e2b3c 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java @@ -110,6 +110,11 @@ public class RSABlindedEngine BigInteger rInv = r.modInverse(m); result = blindedResult.multiply(rInv).mod(m); + // defence against Arjen Lenstra’s CRT attack + if (!input.equals(result.modPow(e, m))) + { + throw new IllegalStateException("RSA engine faulty decryption/signing detected"); + } } else { diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java index 3cab983d..19a2ecfd 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java @@ -6,6 +6,8 @@ import org.bouncycastle.crypto.params.DESedeParameters; public class DESedeKeyGenerator extends DESKeyGenerator { + private static final int MAX_IT = 20; + /** * initialise the key generator - if strength is set to zero * the key generated will be 192 bits in size, otherwise @@ -42,6 +44,7 @@ public class DESedeKeyGenerator public byte[] generateKey() { byte[] newKey = new byte[strength]; + int count = 0; do { @@ -49,7 +52,12 @@ public class DESedeKeyGenerator DESedeParameters.setOddParity(newKey); } - while (DESedeParameters.isWeakKey(newKey, 0, newKey.length)); + while (++count < MAX_IT && (DESedeParameters.isWeakKey(newKey, 0, newKey.length) || !DESedeParameters.isRealEDEKey(newKey, 0))); + + if (DESedeParameters.isWeakKey(newKey, 0, newKey.length) || !DESedeParameters.isRealEDEKey(newKey, 0)) + { + throw new IllegalStateException("Unable to generate DES-EDE key"); + } return newKey; } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java index 36b41cc7..61b4bea9 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java @@ -19,17 +19,17 @@ import org.bouncycastle.util.encoders.Hex; */ public class DSAParametersGenerator { - private Digest digest; - private int L, N; - private int certainty; - private SecureRandom random; - private static final BigInteger ZERO = BigInteger.valueOf(0); private static final BigInteger ONE = BigInteger.valueOf(1); private static final BigInteger TWO = BigInteger.valueOf(2); - private boolean use186_3; - private int usageIndex; + private Digest digest; + private int L, N; + private int certainty; + private int iterations; + private SecureRandom random; + private boolean use186_3; + private int usageIndex; public DSAParametersGenerator() { @@ -55,11 +55,13 @@ public class DSAParametersGenerator int certainty, SecureRandom random) { - this.use186_3 = false; this.L = size; this.N = getDefaultN(size); this.certainty = certainty; + this.iterations = Math.max(getMinimumIterations(L), (certainty + 1) / 2); this.random = random; + this.use186_3 = false; + this.usageIndex = -1; } /** @@ -73,13 +75,7 @@ public class DSAParametersGenerator public void init( DSAParameterGenerationParameters params) { - // TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1? - this.use186_3 = true; - this.L = params.getL(); - this.N = params.getN(); - this.certainty = params.getCertainty(); - this.random = params.getRandom(); - this.usageIndex = params.getUsageIndex(); + int L = params.getL(), N = params.getN(); if ((L < 1024 || L > 3072) || L % 1024 != 0) { @@ -102,6 +98,14 @@ public class DSAParametersGenerator { throw new IllegalStateException("Digest output size too small for value of N"); } + + this.L = L; + this.N = N; + this.certainty = params.getCertainty(); + this.iterations = Math.max(getMinimumIterations(L), (certainty + 1) / 2); + this.random = params.getRandom(); + this.use186_3 = true; + this.usageIndex = params.getUsageIndex(); } /** @@ -137,10 +141,10 @@ public class DSAParametersGenerator { random.nextBytes(seed); - hash(digest, seed, part1); + hash(digest, seed, part1, 0); System.arraycopy(seed, 0, part2, 0, seed.length); inc(part2); - hash(digest, part2, part2); + hash(digest, part2, part2, 0); for (int i = 0; i != u.length; i++) { @@ -152,7 +156,7 @@ public class DSAParametersGenerator BigInteger q = new BigInteger(1, u); - if (!q.isProbablePrime(certainty)) + if (!isProbablePrime(q)) { continue; } @@ -162,18 +166,20 @@ public class DSAParametersGenerator for (int counter = 0; counter < 4096; ++counter) { - for (int k = 0; k < n; k++) { - inc(offset); - hash(digest, offset, part1); - System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length); - } + for (int k = 1; k <= n; k++) + { + inc(offset); + hash(digest, offset, w, w.length - k * part1.length); + } - inc(offset); - hash(digest, offset, part1); - System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length); + int remaining = w.length - (n * part1.length); + inc(offset); + hash(digest, offset, part1, 0); + System.arraycopy(part1, part1.length - remaining, w, 0, remaining); - w[0] |= (byte)0x80; + w[0] |= (byte)0x80; + } BigInteger x = new BigInteger(1, w); @@ -186,7 +192,7 @@ public class DSAParametersGenerator continue; } - if (p.isProbablePrime(certainty)) + if (isProbablePrime(p)) { BigInteger g = calculateGenerator_FIPS186_2(p, q, random); @@ -238,6 +244,7 @@ public class DSAParametersGenerator // 4. b = L - 1 - (n * outlen). int b = (L - 1) % outlen; + byte[] w = new byte[L / 8]; byte[] output = new byte[d.getDigestSize()]; for (;;) { @@ -245,16 +252,15 @@ public class DSAParametersGenerator random.nextBytes(seed); // 6. U = Hash (domain_parameter_seed) mod 2^(N–1). - hash(d, seed, output); + hash(d, seed, output, 0); BigInteger U = new BigInteger(1, output).mod(ONE.shiftLeft(N - 1)); // 7. q = 2^(N–1) + U + 1 – ( U mod 2). - BigInteger q = ONE.shiftLeft(N - 1).add(U).add(ONE).subtract(U.mod(TWO)); + BigInteger q = U.setBit(0).setBit(N - 1); // 8. Test whether or not q is prime as specified in Appendix C.3. - // TODO Review C.3 for primality checking - if (!q.isProbablePrime(certainty)) + if (!isProbablePrime(q)) { // 9. If q is not a prime, then go to step 5. continue; @@ -271,24 +277,23 @@ public class DSAParametersGenerator // 11.1 For j = 0 to n do // Vj = Hash ((domain_parameter_seed + offset + j) mod 2^seedlen). // 11.2 W = V0 + (V1 ∗ 2^outlen) + ... + (V^(n–1) ∗ 2^((n–1) ∗ outlen)) + ((Vn mod 2^b) ∗ 2^(n ∗ outlen)). - // TODO Assemble w as a byte array - BigInteger W = ZERO; - for (int j = 0, exp = 0; j <= n; ++j, exp += outlen) { - inc(offset); - hash(d, offset, output); - - BigInteger Vj = new BigInteger(1, output); - if (j == n) + for (int j = 1; j <= n; ++j) { - Vj = Vj.mod(ONE.shiftLeft(b)); + inc(offset); + hash(d, offset, w, w.length - j * output.length); } - W = W.add(Vj.shiftLeft(exp)); + int remaining = w.length - (n * output.length); + inc(offset); + hash(d, offset, output, 0); + System.arraycopy(output, output.length - remaining, w, 0, remaining); + +// 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2^(L–1); hence, 2^(L–1) ≤ X < 2^L. + w[0] |= (byte)0x80; } -// 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2L–1; hence, 2L–1 ≤ X < 2L. - BigInteger X = W.add(ONE.shiftLeft(L - 1)); + BigInteger X = new BigInteger(1, w); // 11.4 c = X mod 2q. BigInteger c = X.mod(q.shiftLeft(1)); @@ -296,15 +301,14 @@ public class DSAParametersGenerator // 11.5 p = X - (c - 1). Comment: p ≡ 1 (mod 2q). BigInteger p = X.subtract(c.subtract(ONE)); -// 11.6 If (p < 2^(L - 1)), then go to step 11.9 +// 11.6 If (p < 2^(L-1)), then go to step 11.9 if (p.bitLength() != L) { continue; } // 11.7 Test whether or not p is prime as specified in Appendix C.3. - // TODO Review C.3 for primality checking - if (p.isProbablePrime(certainty)) + if (isProbablePrime(p)) { // 11.8 If p is determined to be prime, then return VALID and the values of p, q and // (optionally) the values of domain_parameter_seed and counter. @@ -331,6 +335,16 @@ public class DSAParametersGenerator } } + private boolean isProbablePrime(BigInteger x) + { + /* + * TODO Use Primes class for FIPS 186-4 C.3 primality checking - but it breaks existing + * tests using FixedSecureRandom + */ +// return !Primes.hasAnySmallFactors(x) && Primes.isMRProbablePrime(x, random, iterations); + return x.isProbablePrime(certainty); + } + private static BigInteger calculateGenerator_FIPS186_3_Unverifiable(BigInteger p, BigInteger q, SecureRandom r) { @@ -354,7 +368,7 @@ public class DSAParametersGenerator for (int count = 1; count < (1 << 16); ++count) { inc(U); - hash(d, U, w); + hash(d, U, w, 0); BigInteger W = new BigInteger(1, w); BigInteger g = W.modPow(e, p); if (g.compareTo(TWO) >= 0) @@ -366,10 +380,10 @@ public class DSAParametersGenerator return null; } - private static void hash(Digest d, byte[] input, byte[] output) + private static void hash(Digest d, byte[] input, byte[] output, int outputPos) { d.update(input, 0, input.length); - d.doFinal(output, 0); + d.doFinal(output, outputPos); } private static int getDefaultN(int L) @@ -377,6 +391,12 @@ public class DSAParametersGenerator return L > 1024 ? 256 : 160; } + private static int getMinimumIterations(int L) + { + // Values based on FIPS 186-4 C.3 Table C.1 + return L <= 1024 ? 40 : (48 + 8 * ((L - 1) / 1024)); + } + private static void inc(byte[] buf) { for (int i = buf.length - 1; i >= 0; --i) diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java index 4f46a38d..c7660719 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java @@ -56,12 +56,6 @@ public class ECKeyPairGenerator continue; } - /* - * Require a minimum weight of the NAF representation, since low-weight primes may be - * weak against a version of the number-field-sieve for the discrete-logarithm-problem. - * - * See "The number field sieve for integers of low weight", Oliver Schirokauer. - */ if (WNafUtil.getNafWeight(d) < minWeight) { continue; diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java index 082a1c8a..9a2239e2 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java @@ -10,6 +10,7 @@ import org.bouncycastle.crypto.digests.AndroidDigestFactory; import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.util.Arrays; /** * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2. @@ -116,7 +117,7 @@ public class PKCS5S2ParametersGenerator { keySize = keySize / 8; - byte[] dKey = generateDerivedKey(keySize); + byte[] dKey = Arrays.copyOfRange(generateDerivedKey(keySize), 0, keySize); return new KeyParameter(dKey, 0, keySize); } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java index 7277045e..f23f654b 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java @@ -8,6 +8,7 @@ import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.params.RSAKeyGenerationParameters; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; +import org.bouncycastle.math.Primes; import org.bouncycastle.math.ec.WNafUtil; /** @@ -19,10 +20,12 @@ public class RSAKeyPairGenerator private static final BigInteger ONE = BigInteger.valueOf(1); private RSAKeyGenerationParameters param; + private int iterations; public void init(KeyGenerationParameters param) { this.param = (RSAKeyGenerationParameters)param; + this.iterations = getNumberOfIterations(this.param.getStrength(), this.param.getCertainty()); } public AsymmetricCipherKeyPair generateKeyPair() @@ -30,36 +33,46 @@ public class RSAKeyPairGenerator AsymmetricCipherKeyPair result = null; boolean done = false; - while (!done) + // + // p and q values should have a length of half the strength in bits + // + int strength = param.getStrength(); + int pbitlength = (strength + 1) / 2; + int qbitlength = strength - pbitlength; + int mindiffbits = (strength / 2) - 100; + + if (mindiffbits < strength / 3) { - BigInteger p, q, n, d, e, pSub1, qSub1, phi, lcm, dLowerBound; + mindiffbits = strength / 3; + } - // - // p and q values should have a length of half the strength in bits - // - int strength = param.getStrength(); - int pbitlength = (strength + 1) / 2; - int qbitlength = strength - pbitlength; - int mindiffbits = strength / 3; - int minWeight = strength >> 2; + int minWeight = strength >> 2; - e = param.getPublicExponent(); + // d lower bound is 2^(strength / 2) + BigInteger dLowerBound = BigInteger.valueOf(2).pow(strength / 2); + // squared bound (sqrt(2)*2^(nlen/2-1))^2 + BigInteger squaredBound = ONE.shiftLeft(strength - 1); + // 2^(nlen/2 - 100) + BigInteger minDiff = ONE.shiftLeft(mindiffbits); - // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes) - // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") + while (!done) + { + BigInteger p, q, n, d, e, pSub1, qSub1, gcd, lcm; - p = chooseRandomPrime(pbitlength, e); + e = param.getPublicExponent(); + + p = chooseRandomPrime(pbitlength, e, squaredBound); // // generate a modulus of the required length // - for (;;) + for (; ; ) { - q = chooseRandomPrime(qbitlength, e); + q = chooseRandomPrime(qbitlength, e, squaredBound); // p and q should not be too close together (or equal!) BigInteger diff = q.subtract(p).abs(); - if (diff.bitLength() < mindiffbits) + if (diff.bitLength() < mindiffbits || diff.compareTo(minDiff) <= 0) { continue; } @@ -80,14 +93,14 @@ public class RSAKeyPairGenerator } /* - * Require a minimum weight of the NAF representation, since low-weight composites may + * Require a minimum weight of the NAF representation, since low-weight composites may * be weak against a version of the number-field-sieve for factoring. * * See "The number field sieve for integers of low weight", Oliver Schirokauer. */ if (WNafUtil.getNafWeight(n) < minWeight) { - p = chooseRandomPrime(pbitlength, e); + p = chooseRandomPrime(pbitlength, e, squaredBound); continue; } @@ -96,26 +109,22 @@ public class RSAKeyPairGenerator if (p.compareTo(q) < 0) { - phi = p; + gcd = p; p = q; - q = phi; + q = gcd; } pSub1 = p.subtract(ONE); qSub1 = q.subtract(ONE); - phi = pSub1.multiply(qSub1); - lcm = phi.divide(pSub1.gcd(qSub1)); + gcd = pSub1.gcd(qSub1); + lcm = pSub1.divide(gcd).multiply(qSub1); // // calculate the private exponent // d = e.modInverse(lcm); - // if d is less than or equal to dLowerBound, we need to start over - // also, for backward compatibility, if d is not the same as - // e.modInverse(phi), we need to start over - - if (d.bitLength() <= qbitlength || !d.equals(e.modInverse(phi))) + if (d.compareTo(dLowerBound) <= 0) { continue; } @@ -143,33 +152,80 @@ public class RSAKeyPairGenerator /** * Choose a random prime value for use with RSA - * + * * @param bitlength the bit-length of the returned prime - * @param e the RSA public exponent - * @return a prime p, with (p-1) relatively prime to e + * @param e the RSA public exponent + * @return A prime p, with (p-1) relatively prime to e */ - protected BigInteger chooseRandomPrime(int bitlength, BigInteger e) + protected BigInteger chooseRandomPrime(int bitlength, BigInteger e, BigInteger sqrdBound) { - for (;;) + for (int i = 0; i != 5 * bitlength; i++) { BigInteger p = new BigInteger(bitlength, 1, param.getRandom()); - + if (p.mod(e).equals(ONE)) { continue; } - - if (!p.isProbablePrime(param.getCertainty())) + + if (p.multiply(p).compareTo(sqrdBound) < 0) + { + continue; + } + + if (!isProbablePrime(p)) { continue; } - if (!e.gcd(p.subtract(ONE)).equals(ONE)) + if (!e.gcd(p.subtract(ONE)).equals(ONE)) { continue; } - + return p; } + + throw new IllegalStateException("unable to generate prime number for RSA key"); + } + + protected boolean isProbablePrime(BigInteger x) + { + /* + * Primes class for FIPS 186-4 C.3 primality checking + */ + return !Primes.hasAnySmallFactors(x) && Primes.isMRProbablePrime(x, param.getRandom(), iterations); + } + + private static int getNumberOfIterations(int bits, int certainty) + { + /* + * NOTE: We enforce a minimum 'certainty' of 100 for bits >= 1024 (else 80). Where the + * certainty is higher than the FIPS 186-4 tables (C.2/C.3) cater to, extra iterations + * are added at the "worst case rate" for the excess. + */ + if (bits >= 1536) + { + return certainty <= 100 ? 3 + : certainty <= 128 ? 4 + : 4 + (certainty - 128 + 1) / 2; + } + else if (bits >= 1024) + { + return certainty <= 100 ? 4 + : certainty <= 112 ? 5 + : 5 + (certainty - 112 + 1) / 2; + } + else if (bits >= 512) + { + return certainty <= 80 ? 5 + : certainty <= 100 ? 7 + : 7 + (certainty - 100 + 1) / 2; + } + else + { + return certainty <= 80 ? 40 + : 40 + (certainty - 80 + 1) / 2; + } } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java index 7f870ca2..088c7283 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java @@ -87,7 +87,7 @@ public class CCMBlockCipher } else { - throw new IllegalArgumentException("invalid parameters passed to CCM"); + throw new IllegalArgumentException("invalid parameters passed to CCM: " + params.getClass().getName()); } // NOTE: Very basic support for key re-use, but no performance gain from it @@ -277,7 +277,9 @@ public class CCMBlockCipher calculateMac(in, inOff, inLen, macBlock); - ctrCipher.processBlock(macBlock, 0, macBlock, 0); // S0 + byte[] encMac = new byte[blockSize]; + + ctrCipher.processBlock(macBlock, 0, encMac, 0); // S0 while (inIndex < (inOff + inLen - blockSize)) // S1... { @@ -294,7 +296,7 @@ public class CCMBlockCipher System.arraycopy(block, 0, output, outIndex, inLen + inOff - inIndex); - System.arraycopy(macBlock, 0, output, outOff + inLen, macSize); + System.arraycopy(encMac, 0, output, outOff + inLen, macSize); } else { diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java index 9e8c3c30..ed89ef7d 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java @@ -362,21 +362,30 @@ public class GCMBlockCipher } int extra = bufOff; - if (!forEncryption) + + if (forEncryption) + { + if (out.length < (outOff + extra + macSize)) + { + throw new OutputLengthException("Output buffer too short"); + } + } + else { if (extra < macSize) { throw new InvalidCipherTextException("data too short"); } extra -= macSize; - } - if (extra > 0) - { if (out.length < (outOff + extra)) { throw new OutputLengthException("Output buffer too short"); } + } + + if (extra > 0) + { gCTRPartial(bufBlock, 0, extra, out, outOff); } @@ -442,10 +451,6 @@ public class GCMBlockCipher if (forEncryption) { - if (out.length < (outOff + extra + macSize)) - { - throw new OutputLengthException("Output buffer too short"); - } // Append T to the message System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize); resultLen += macSize; @@ -550,16 +555,11 @@ public class GCMBlockCipher private byte[] getNextCounterBlock() { - for (int i = 15; i >= 12; --i) - { - byte b = (byte)((counter[i] + 1) & 0xff); - counter[i] = b; - - if (b != 0) - { - break; - } - } + int c = 1; + c += counter[15] & 0xFF; counter[15] = (byte)c; c >>>= 8; + c += counter[14] & 0xFF; counter[14] = (byte)c; c >>>= 8; + c += counter[13] & 0xFF; counter[13] = (byte)c; c >>>= 8; + c += counter[12] & 0xFF; counter[12] = (byte)c; byte[] tmp = new byte[BLOCK_SIZE]; // TODO Sure would be nice if ciphers could operate on int[] diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java index fbc8bf45..ae4256f6 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java @@ -6,6 +6,7 @@ import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.SkippingStreamCipher; import org.bouncycastle.crypto.StreamBlockCipher; import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Pack; /** @@ -18,7 +19,7 @@ public class SICBlockCipher { private final BlockCipher cipher; private final int blockSize; - + private byte[] IV; private byte[] counter; private byte[] counterOut; @@ -49,8 +50,19 @@ public class SICBlockCipher if (params instanceof ParametersWithIV) { ParametersWithIV ivParam = (ParametersWithIV)params; - byte[] iv = ivParam.getIV(); - System.arraycopy(iv, 0, IV, 0, IV.length); + this.IV = Arrays.clone(ivParam.getIV()); + + if (blockSize < IV.length) + { + throw new IllegalArgumentException("CTR/SIC mode requires IV no greater than: " + blockSize + " bytes."); + } + + int maxCounterSize = (8 > blockSize / 2) ? blockSize / 2 : 8; + + if (blockSize - IV.length > maxCounterSize) + { + throw new IllegalArgumentException("CTR/SIC mode requires IV of at least: " + (blockSize - maxCounterSize) + " bytes."); + } // if null it's an IV changed only. if (ivParam.getParameters() != null) @@ -62,7 +74,7 @@ public class SICBlockCipher } else { - throw new IllegalArgumentException("SIC mode requires ParametersWithIV"); + throw new IllegalArgumentException("CTR/SIC mode requires ParametersWithIV"); } } @@ -100,94 +112,63 @@ public class SICBlockCipher { byteCount = 0; - incrementCounter(); + incrementCounterAt(0); + + checkCounter(); } return rv; } - private void incrementCounterPow2(int pow2Div8) + private void checkCounter() { - // increment counter by 1 << 8 * pow2Div8 - for (int i = counter.length - (1 + pow2Div8); i >= 0 && ++counter[i] == 0; i--) - { - ; // do nothing - pre-increment and test for 0 in counter does the job. - } - } - - private void incrementCounter(int offSet) - { - byte old = counter[counter.length - 1]; - - counter[counter.length - 1] += offSet; - - if (old != 0 && counter[counter.length - 1] < old) + // if the IV is the same as the blocksize we assume the user knows what they are doing + if (IV.length < blockSize) { - incrementCounterPow2(1); + for (int i = 0; i != IV.length; i++) + { + if (counter[i] != IV[i]) + { + throw new IllegalStateException("Counter in CTR/SIC mode out of range."); + } + } } } - private void incrementCounter() + private void incrementCounterAt(int pos) { - // increment counter by 1. - for (int i = counter.length - 1; i >= 0 && ++counter[i] == 0; i--) + int i = counter.length - pos; + while (--i >= 0) { - ; // do nothing - pre-increment and test for 0 in counter does the job. + if (++counter[i] != 0) + { + break; + } } } - private void decrementCounterPow2(int pow2Div8) + private void incrementCounter(int offSet) { - if (counter[pow2Div8] == 0) - { - boolean nonZero = false; - - for (int i = counter.length - (1 + pow2Div8); i > 0; i--) - { - if (counter[i] != 0) - { - nonZero = true; - } - } + byte old = counter[counter.length - 1]; - if (!nonZero) - { - throw new IllegalStateException("attempt to reduce counter past zero."); - } - } + counter[counter.length - 1] += offSet; - // decrement counter by 1. - for (int i = counter.length - (1 + pow2Div8); i >= 0 && --counter[i] == -1; i--) + if (old != 0 && counter[counter.length - 1] < old) { - ; + incrementCounterAt(1); } } - private void decrementCounter() + private void decrementCounterAt(int pos) { - if (counter[0] == 0) + int i = counter.length - pos; + while (--i >= 0) { - boolean nonZero = false; - - for (int i = counter.length - 1; i > 0; i--) - { - if (counter[i] != 0) - { - nonZero = true; - } - } - - if (!nonZero) + if (--counter[i] != -1) { - throw new IllegalStateException("attempt to reduce counter past zero."); + return; } } - - // decrement counter by 1. - for (int i = counter.length - 1; i >= 0 && --counter[i] == -1; i--) - { - ; - } } private void adjustCounter(long n) @@ -196,62 +177,45 @@ public class SICBlockCipher { long numBlocks = (n + byteCount) / blockSize; - if (numBlocks > 255) + long rem = numBlocks; + if (rem > 255) { - long gap = numBlocks; - for (int i = 5; i >= 1; i--) { long diff = 1L << (8 * i); - - while (gap >= diff) + while (rem >= diff) { - incrementCounterPow2(i); - - gap -= diff; + incrementCounterAt(i); + rem -= diff; } } - - incrementCounter((int)gap); - } - else - { - incrementCounter((int)numBlocks); } + incrementCounter((int)rem); + byteCount = (int)((n + byteCount) - (blockSize * numBlocks)); } else { long numBlocks = (-n - byteCount) / blockSize; - if (numBlocks > 255) + long rem = numBlocks; + if (rem > 255) { - long gap = numBlocks; - for (int i = 5; i >= 1; i--) { long diff = 1L << (8 * i); - - while (gap > diff) + while (rem > diff) { - decrementCounterPow2(i); - - gap -= diff; + decrementCounterAt(i); + rem -= diff; } } - - for (long i = 0; i != gap; i++) - { - decrementCounter(); - } } - else + + for (long i = 0; i != rem; i++) { - for (long i = 0; i != numBlocks; i++) - { - decrementCounter(); - } + decrementCounterAt(0); } int gap = (int)(byteCount + n + (blockSize * numBlocks)); @@ -262,7 +226,7 @@ public class SICBlockCipher } else { - decrementCounter(); + decrementCounterAt(0); byteCount = blockSize + gap; } } @@ -270,7 +234,8 @@ public class SICBlockCipher public void reset() { - System.arraycopy(IV, 0, counter, 0, counter.length); + Arrays.fill(counter, (byte)0); + System.arraycopy(IV, 0, counter, 0, IV.length); cipher.reset(); this.byteCount = 0; } @@ -279,6 +244,8 @@ public class SICBlockCipher { adjustCounter(numberOfBytes); + checkCounter(); + cipher.processBlock(counter, 0, counterOut, 0); return numberOfBytes; @@ -293,13 +260,21 @@ public class SICBlockCipher public long getPosition() { - byte[] res = new byte[IV.length]; + byte[] res = new byte[counter.length]; System.arraycopy(counter, 0, res, 0, res.length); for (int i = res.length - 1; i >= 1; i--) { - int v = (res[i] & 0xff) - (IV[i] & 0xff); + int v; + if (i < IV.length) + { + v = (res[i] & 0xff) - (IV[i] & 0xff); + } + else + { + v = (res[i] & 0xff); + } if (v < 0) { diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java index 58f40788..f08f71f3 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java @@ -123,9 +123,9 @@ public abstract class GCMUtil r13 ^= (r03 & m1); int m2 = (r03 << 31) >> 8; - r03 = (r03 >>> 1) | (r02 << 63); - r02 = (r02 >>> 1) | (r01 << 63); - r01 = (r01 >>> 1) | (r00 << 63); + r03 = (r03 >>> 1) | (r02 << 31); + r02 = (r02 >>> 1) | (r01 << 31); + r01 = (r01 >>> 1) | (r00 << 31); r00 = (r00 >>> 1) ^ (m2 & E1); } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java index 3a4bbfca..5b2d0d46 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DESedeParameters.java @@ -54,4 +54,53 @@ public class DESedeParameters { return isWeakKey(key, offset, key.length - offset); } + + /** + * return true if the passed in key is a real 2/3 part DES-EDE key. + * + * @param key bytes making up the key + * @param offset offset into the byte array the key starts at + */ + public static boolean isRealEDEKey(byte[] key, int offset) + { + return key.length == 16 ? isReal2Key(key, offset) : isReal3Key(key, offset); + } + + /** + * return true if the passed in key is a real 2 part DES-EDE key. + * + * @param key bytes making up the key + * @param offset offset into the byte array the key starts at + */ + public static boolean isReal2Key(byte[] key, int offset) + { + boolean isValid = false; + for (int i = offset; i != offset + 8; i++) + { + if (key[i] != key[i + 8]) + { + isValid = true; + } + } + + return isValid; + } + + /** + * return true if the passed in key is a real 3 part DES-EDE key. + * + * @param key bytes making up the key + * @param offset offset into the byte array the key starts at + */ + public static boolean isReal3Key(byte[] key, int offset) + { + boolean diff12 = false, diff13 = false, diff23 = false; + for (int i = offset; i != offset + 8; i++) + { + diff12 |= (key[i] != key[i + 8]); + diff13 |= (key[i] != key[i + 16]); + diff23 |= (key[i + 8] != key[i + 16]); + } + return diff12 && diff13 && diff23; + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java new file mode 100644 index 00000000..f3bac647 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFParameters.java @@ -0,0 +1,31 @@ +package org.bouncycastle.crypto.params; + +import org.bouncycastle.crypto.DerivationParameters; + +/** + * parameters for Key derivation functions for IEEE P1363a + */ +public class KDFParameters + implements DerivationParameters +{ + byte[] iv; + byte[] shared; + + public KDFParameters( + byte[] shared, + byte[] iv) + { + this.shared = shared; + this.iv = iv; + } + + public byte[] getSharedSecret() + { + return shared; + } + + public byte[] getIV() + { + return iv; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java index dc33ec5b..ea98de2c 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/RC2Parameters.java @@ -1,11 +1,8 @@ package org.bouncycastle.crypto.params; -import org.bouncycastle.crypto.CipherParameters; - public class RC2Parameters - implements CipherParameters + extends KeyParameter { - private byte[] key; private int bits; public RC2Parameters( @@ -18,15 +15,8 @@ public class RC2Parameters byte[] key, int bits) { - this.key = new byte[key.length]; + super(key); this.bits = bits; - - System.arraycopy(key, 0, this.key, 0, key.length); - } - - public byte[] getKey() - { - return key; } public int getEffectiveKeyBits() diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java index 5fce1121..adb2558a 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java @@ -12,6 +12,8 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.math.ec.ECAlgorithms; import org.bouncycastle.math.ec.ECConstants; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECFieldElement; import org.bouncycastle.math.ec.ECMultiplier; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.FixedPointCombMultiplier; @@ -159,7 +161,7 @@ public class ECDSASigner ECPoint G = ec.getG(); ECPoint Q = ((ECPublicKeyParameters)key).getQ(); - ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2).normalize(); + ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2); // components must be bogus. if (point.isInfinity()) @@ -167,8 +169,44 @@ public class ECDSASigner return false; } - BigInteger v = point.getAffineXCoord().toBigInteger().mod(n); + /* + * If possible, avoid normalizing the point (to save a modular inversion in the curve field). + * + * There are ~cofactor elements of the curve field that reduce (modulo the group order) to 'r'. + * If the cofactor is known and small, we generate those possible field values and project each + * of them to the same "denominator" (depending on the particular projective coordinates in use) + * as the calculated point.X. If any of the projected values matches point.X, then we have: + * (point.X / Denominator mod p) mod n == r + * as required, and verification succeeds. + * + * Based on an original idea by Gregory Maxwell (https://github.com/gmaxwell), as implemented in + * the libsecp256k1 project (https://github.com/bitcoin/secp256k1). + */ + ECCurve curve = point.getCurve(); + if (curve != null) + { + BigInteger cofactor = curve.getCofactor(); + if (cofactor != null && cofactor.compareTo(EIGHT) <= 0) + { + ECFieldElement D = getDenominator(curve.getCoordinateSystem(), point); + if (D != null && !D.isZero()) + { + ECFieldElement X = point.getXCoord(); + while (curve.isValidFieldElement(r)) + { + ECFieldElement R = curve.fromBigInteger(r).multiply(D); + if (R.equals(X)) + { + return true; + } + r = r.add(n); + } + return false; + } + } + } + BigInteger v = point.normalize().getAffineXCoord().toBigInteger().mod(n); return v.equals(r); } @@ -190,6 +228,23 @@ public class ECDSASigner return new FixedPointCombMultiplier(); } + protected ECFieldElement getDenominator(int coordinateSystem, ECPoint p) + { + switch (coordinateSystem) + { + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + case ECCurve.COORD_SKEWED: + return p.getZCoord(0); + case ECCurve.COORD_JACOBIAN: + case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: + case ECCurve.COORD_JACOBIAN_MODIFIED: + return p.getZCoord(0).square(); + default: + return null; + } + } + protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided) { return !needed ? null : (provided != null) ? provided : new SecureRandom(); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java index 2b333213..042c68ef 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java @@ -22,10 +22,10 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.DSAParameter; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; -import org.bouncycastle.asn1.x9.DHDomainParameters; import org.bouncycastle.asn1.x9.DHPublicKey; -import org.bouncycastle.asn1.x9.DHValidationParms; +import org.bouncycastle.asn1.x9.DomainParameters; import org.bouncycastle.asn1.x9.ECNamedCurveTable; +import org.bouncycastle.asn1.x9.ValidationParams; import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ECPoint; @@ -98,26 +98,26 @@ public class PublicKeyFactory { DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey()); - BigInteger y = dhPublicKey.getY().getValue(); + BigInteger y = dhPublicKey.getY(); - DHDomainParameters dhParams = DHDomainParameters.getInstance(algId.getParameters()); + DomainParameters dhParams = DomainParameters.getInstance(algId.getParameters()); - BigInteger p = dhParams.getP().getValue(); - BigInteger g = dhParams.getG().getValue(); - BigInteger q = dhParams.getQ().getValue(); + BigInteger p = dhParams.getP(); + BigInteger g = dhParams.getG(); + BigInteger q = dhParams.getQ(); BigInteger j = null; if (dhParams.getJ() != null) { - j = dhParams.getJ().getValue(); + j = dhParams.getJ(); } DHValidationParameters validation = null; - DHValidationParms dhValidationParms = dhParams.getValidationParms(); + ValidationParams dhValidationParms = dhParams.getValidationParams(); if (dhValidationParms != null) { - byte[] seed = dhValidationParms.getSeed().getBytes(); - BigInteger pgenCounter = dhValidationParms.getPgenCounter().getValue(); + byte[] seed = dhValidationParms.getSeed(); + BigInteger pgenCounter = dhValidationParms.getPgenCounter(); // TODO Check pgenCounter size? diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java new file mode 100644 index 00000000..ae3d2ebd --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PBKDFKey.java @@ -0,0 +1,11 @@ +package org.bouncycastle.jcajce; + +import javax.crypto.SecretKey; + +/** + * Base interface for keys associated with various password based key derivation functions (PBKDF). + */ +public interface PBKDFKey + extends SecretKey +{ +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12Key.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12Key.java new file mode 100644 index 00000000..db63ecdb --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12Key.java @@ -0,0 +1,82 @@ +package org.bouncycastle.jcajce; + +import org.bouncycastle.crypto.PBEParametersGenerator; + +/** + * A password based key for use with PKCS#12. + */ +public class PKCS12Key + implements PBKDFKey +{ + private final char[] password; + private final boolean useWrongZeroLengthConversion; + /** + * Basic constructor for a password based key - secret key generation parameters will be passed separately.. + * + * @param password password to use. + */ + public PKCS12Key(char[] password) + { + this(password, false); + } + + /** + * Unfortunately there seems to be some confusion about how to handle zero length + * passwords. + * + * @param password password to use. + * @param useWrongZeroLengthConversion use the incorrect encoding approach (add pad bytes) + */ + public PKCS12Key(char[] password, boolean useWrongZeroLengthConversion) + { + this.password = new char[password.length]; + this.useWrongZeroLengthConversion = useWrongZeroLengthConversion; + + System.arraycopy(password, 0, this.password, 0, password.length); + } + + /** + * Return a reference to the char[] array holding the password. + * + * @return a reference to the password array. + */ + public char[] getPassword() + { + return password; + } + + /** + * Return the password based key derivation function this key is for, + * + * @return the string "PKCS12" + */ + public String getAlgorithm() + { + return "PKCS12"; + } + + /** + * Return the format encoding. + * + * @return the string "PKCS12", representing the char[] to byte[] conversion. + */ + public String getFormat() + { + return "PKCS12"; + } + + /** + * Return the password converted to bytes. + * + * @return the password converted to a byte array. + */ + public byte[] getEncoded() + { + if (useWrongZeroLengthConversion && password.length == 0) + { + return new byte[2]; + } + + return PBEParametersGenerator.PKCS12PasswordToBytes(password); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12KeyWithParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12KeyWithParameters.java new file mode 100644 index 00000000..bd055966 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12KeyWithParameters.java @@ -0,0 +1,69 @@ +package org.bouncycastle.jcajce; + +import javax.crypto.interfaces.PBEKey; + +import org.bouncycastle.util.Arrays; + +/** + * A password based key for use with PKCS#12 with full PBE parameters. + */ +public class PKCS12KeyWithParameters + extends PKCS12Key + implements PBEKey +{ + private final byte[] salt; + private final int iterationCount; + + /** + * Basic constructor for a password based key with generation parameters. + * + * @param password password to use. + * @param salt salt for generation algorithm + * @param iterationCount iteration count for generation algorithm. + */ + public PKCS12KeyWithParameters(char[] password, byte[] salt, int iterationCount) + { + super(password); + + this.salt = Arrays.clone(salt); + this.iterationCount = iterationCount; + } + + + /** + * Basic constructor for a password based key with generation parameters, specifying the wrong conversion for + * zero length passwords. + * + * @param password password to use. + * @param salt salt for generation algorithm + * @param iterationCount iteration count for generation algorithm. + * @param useWrongZeroLengthConversion use the incorrect encoding approach (add pad bytes) + */ + public PKCS12KeyWithParameters(char[] password, boolean useWrongZeroLengthConversion, byte[] salt, int iterationCount) + { + super(password, useWrongZeroLengthConversion); + + this.salt = Arrays.clone(salt); + this.iterationCount = iterationCount; + } + + /** + * Return the salt to use in the key derivation function. + * + * @return the salt to use in the KDF. + */ + public byte[] getSalt() + { + return salt; + } + + /** + * Return the iteration count to use in the key derivation function. + * + * @return the iteration count to use in the KDF. + */ + public int getIterationCount() + { + return iterationCount; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStore.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStore.java index b3447207..1592055f 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStore.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStore.java @@ -7,9 +7,21 @@ import org.bouncycastle.util.Selector; import org.bouncycastle.util.Store; import org.bouncycastle.util.StoreException; +/** + * Generic interface for a PKIX based CRL store. + * + * @param <T> the CRL type. + */ public interface PKIXCRLStore<T extends CRL> extends Store<T> { + /** + * Return the matches associated with the passed in selector. + * + * @param selector the selector defining the match criteria. + * @return a collection of matches with the selector, an empty selector if there are none. + * @throws StoreException in the event of an issue doing a match. + */ Collection<T> getMatches(Selector<T> selector) throws StoreException; } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStoreSelector.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStoreSelector.java index 9c684332..e7dbcce0 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStoreSelector.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStoreSelector.java @@ -25,6 +25,9 @@ import org.bouncycastle.util.Selector; public class PKIXCRLStoreSelector<T extends CRL> implements Selector<T> { + /** + * Builder for a PKIXCRLStoreSelector. + */ public static class Builder { private final CRLSelector baseSelector; @@ -35,9 +38,14 @@ public class PKIXCRLStoreSelector<T extends CRL> private byte[] issuingDistributionPoint = null; private boolean issuingDistributionPointEnabled = false; - public Builder(CRLSelector certSelector) + /** + * Constructor initializing a builder with a CertSelector. + * + * @param crlSelector the CertSelector to copy the match details from. + */ + public Builder(CRLSelector crlSelector) { - this.baseSelector = (CRLSelector)certSelector.clone(); + this.baseSelector = (CRLSelector)crlSelector.clone(); } @@ -124,6 +132,11 @@ public class PKIXCRLStoreSelector<T extends CRL> this.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint); } + /** + * Build a selector. + * + * @return a new PKIXCRLStoreSelector + */ public PKIXCRLStoreSelector<? extends CRL> build() { return new PKIXCRLStoreSelector(this); @@ -291,23 +304,44 @@ public class PKIXCRLStoreSelector<T extends CRL> public X509Certificate getCertificateChecking() { - return ((X509CRLSelector)baseSelector).getCertificateChecking(); + if (baseSelector instanceof X509CRLSelector) + { + return ((X509CRLSelector)baseSelector).getCertificateChecking(); + } + + return null; } public static Collection<? extends CRL> getCRLs(final PKIXCRLStoreSelector selector, CertStore certStore) throws CertStoreException { - return certStore.getCRLs(new CRLSelector() + return certStore.getCRLs(new SelectorClone(selector)); + } + + private static class SelectorClone + extends X509CRLSelector + { + private final PKIXCRLStoreSelector selector; + + SelectorClone(PKIXCRLStoreSelector selector) { - public boolean match(CRL crl) - { - return selector.match(crl); - } + this.selector = selector; - public Object clone() + if (selector.baseSelector instanceof X509CRLSelector) { - return this; + X509CRLSelector baseSelector = (X509CRLSelector)selector.baseSelector; + + this.setCertificateChecking(baseSelector.getCertificateChecking()); + this.setDateAndTime(baseSelector.getDateAndTime()); + this.setIssuers(baseSelector.getIssuers()); + this.setMinCRLNumber(baseSelector.getMinCRL()); + this.setMaxCRLNumber(baseSelector.getMaxCRL()); } - }); + } + + public boolean match(CRL crl) + { + return (selector == null) ? (crl != null) : selector.match(crl); + } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStore.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStore.java index 092872f1..853e2d11 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStore.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStore.java @@ -7,9 +7,21 @@ import org.bouncycastle.util.Selector; import org.bouncycastle.util.Store; import org.bouncycastle.util.StoreException; +/** + * Generic interface for a PKIX based certificate store. + * + * @param <T> the certificate type. + */ public interface PKIXCertStore<T extends Certificate> extends Store<T> { + /** + * Return the matches associated with the passed in selector. + * + * @param selector the selector defining the match criteria. + * @return a collection of matches with the selector, an empty selector if there are none. + * @throws StoreException in the event of an issue doing a match. + */ Collection<T> getMatches(Selector<T> selector) throws StoreException; } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStoreSelector.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStoreSelector.java index 1775de72..faf25d1a 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStoreSelector.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStoreSelector.java @@ -1,9 +1,11 @@ package org.bouncycastle.jcajce; +import java.io.IOException; import java.security.cert.CertSelector; import java.security.cert.CertStore; import java.security.cert.CertStoreException; import java.security.cert.Certificate; +import java.security.cert.X509CertSelector; import java.util.Collection; import org.bouncycastle.util.Selector; @@ -16,15 +18,28 @@ import org.bouncycastle.util.Selector; public class PKIXCertStoreSelector<T extends Certificate> implements Selector<T> { + /** + * Builder for a PKIXCertStoreSelector. + */ public static class Builder { private final CertSelector baseSelector; + /** + * Constructor initializing a builder with a CertSelector. + * + * @param certSelector the CertSelector to copy the match details from. + */ public Builder(CertSelector certSelector) { this.baseSelector = (CertSelector)certSelector.clone(); } + /** + * Build a selector. + * + * @return a new PKIXCertStoreSelector + */ public PKIXCertStoreSelector<? extends Certificate> build() { return new PKIXCertStoreSelector(baseSelector); @@ -51,17 +66,54 @@ public class PKIXCertStoreSelector<T extends Certificate> public static Collection<? extends Certificate> getCertificates(final PKIXCertStoreSelector selector, CertStore certStore) throws CertStoreException { - return certStore.getCertificates(new CertSelector() + return certStore.getCertificates(new SelectorClone(selector)); + } + + private static class SelectorClone + extends X509CertSelector + { + private final PKIXCertStoreSelector selector; + + SelectorClone(PKIXCertStoreSelector selector) { - public boolean match(Certificate certificate) - { - return (selector == null) ? true : selector.match(certificate); - } + this.selector = selector; - public Object clone() + if (selector.baseSelector instanceof X509CertSelector) { - return this; + X509CertSelector baseSelector = (X509CertSelector)selector.baseSelector; + + this.setAuthorityKeyIdentifier(baseSelector.getAuthorityKeyIdentifier()); + this.setBasicConstraints(baseSelector.getBasicConstraints()); + this.setCertificate(baseSelector.getCertificate()); + this.setCertificateValid(baseSelector.getCertificateValid()); + this.setKeyUsage(baseSelector.getKeyUsage()); + this.setMatchAllSubjectAltNames(baseSelector.getMatchAllSubjectAltNames()); + this.setPrivateKeyValid(baseSelector.getPrivateKeyValid()); + this.setSerialNumber(baseSelector.getSerialNumber()); + this.setSubjectKeyIdentifier(baseSelector.getSubjectKeyIdentifier()); + this.setSubjectPublicKey(baseSelector.getSubjectPublicKey()); + + try + { + this.setExtendedKeyUsage(baseSelector.getExtendedKeyUsage()); + this.setIssuer(baseSelector.getIssuerAsBytes()); + this.setNameConstraints(baseSelector.getNameConstraints()); + this.setPathToNames(baseSelector.getPathToNames()); + this.setPolicy(baseSelector.getPolicy()); + this.setSubject(baseSelector.getSubjectAsBytes()); + this.setSubjectAlternativeNames(baseSelector.getSubjectAlternativeNames()); + this.setSubjectPublicKeyAlgID(baseSelector.getSubjectPublicKeyAlgID()); + } + catch (IOException e) + { + throw new IllegalStateException("base selector invalid: " + e.getMessage(), e); + } } - }); + } + + public boolean match(Certificate certificate) + { + return (selector == null) ? (certificate != null) : selector.match(certificate); + } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedBuilderParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedBuilderParameters.java index 3369d0d2..382a23c2 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedBuilderParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedBuilderParameters.java @@ -11,11 +11,14 @@ import java.util.Set; /** * This class contains extended parameters for PKIX certification path builders. * - * @see java.security.cert.PKIXBuilderParameters + * @see PKIXBuilderParameters */ public class PKIXExtendedBuilderParameters implements CertPathParameters { + /** + * Builder for a PKIXExtendedBuilderParameters object. + */ public static class Builder { private final PKIXExtendedParameters baseParameters; @@ -64,7 +67,7 @@ public class PKIXExtendedBuilderParameters * * @param maxPathLength the maximum number of non-self-issued intermediate * certificates in the certification path - * @throws java.security.InvalidParameterException if <code>maxPathLength</code> is set + * @throws InvalidParameterException if <code>maxPathLength</code> is set * to a value less than -1 * * @see #getMaxPathLength diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java index 3a86f2a6..cd24f069 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java @@ -27,7 +27,7 @@ public class PKIXExtendedParameters * verifies that all involved certificates must have been valid at the * current time. The modified PKIX model verifies that all involved * certificates were valid at the signing time. Both are indirectly choosen - * with the {@link java.security.cert.PKIXParameters#setDate(java.util.Date)} method, so this + * with the {@link PKIXParameters#setDate(Date)} method, so this * methods sets the Date when <em>all</em> certificates must have been * valid. */ @@ -40,15 +40,15 @@ public class PKIXExtendedParameters * CA certificate which signed the end certificate must have been valid, * when the end certificate was signed. The CA (or Root CA) certificate must * have been valid, when the CA certificate was signed and so on. So the - * {@link java.security.cert.PKIXParameters#setDate(java.util.Date)} method sets the time, when - * the <em>end certificate</em> must have been valid. - * <p> - * It is used e.g. + * {@link PKIXParameters#setDate(Date)} method sets the time, when + * the <em>end certificate</em> must have been valid. <p/> It is used e.g. * in the German signature law. - * </p> */ public static final int CHAIN_VALIDITY_MODEL = 1; + /** + * Builder for a PKIXExtendedParameters object. + */ public static class Builder { private final PKIXParameters baseParameters; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java index d43924d0..889d957d 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java @@ -24,6 +24,10 @@ public class DH provider.addAlgorithm("KeyAgreement.DH", PREFIX + "KeyAgreementSpi"); provider.addAlgorithm("Alg.Alias.KeyAgreement.DIFFIEHELLMAN", "DH"); + // BEGIN android-removed + // provider.addAlgorithm("KeyAgreement", PKCSObjectIdentifiers.id_alg_ESDH, PREFIX + "KeyAgreementSpi$DHwithRFC2631KDF"); + // provider.addAlgorithm("KeyAgreement", PKCSObjectIdentifiers.id_alg_SSDH, PREFIX + "KeyAgreementSpi$DHwithRFC2631KDF"); + // END android-removed provider.addAlgorithm("KeyFactory.DH", PREFIX + "KeyFactorySpi"); provider.addAlgorithm("Alg.Alias.KeyFactory.DIFFIEHELLMAN", "DH"); @@ -34,12 +38,22 @@ public class DH provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator.DIFFIEHELLMAN", "DH"); provider.addAlgorithm("AlgorithmParameterGenerator.DH", PREFIX + "AlgorithmParameterGeneratorSpi"); - + // BEGIN android-removed + // provider.addAlgorithm("Cipher.IES", PREFIX + "IESCipher$IES"); + // provider.addAlgorithm("Cipher.IESwithAES", PREFIX + "IESCipher$IESwithAES"); + // provider.addAlgorithm("Cipher.IESWITHAES", PREFIX + "IESCipher$IESwithAES"); + // provider.addAlgorithm("Cipher.IESWITHDESEDE", PREFIX + "IESCipher$IESwithDESede"); + // // provider.addAlgorithm("Cipher.DHIES", PREFIX + "IESCipher$IES"); // provider.addAlgorithm("Cipher.DHIESwithAES", PREFIX + "IESCipher$IESwithAES"); // provider.addAlgorithm("Cipher.DHIESWITHAES", PREFIX + "IESCipher$IESwithAES"); // provider.addAlgorithm("Cipher.DHIESWITHDESEDE", PREFIX + "IESCipher$IESwithDESede"); + // + // provider.addAlgorithm("Cipher.OLDDHIES", PREFIX + "IESCipher$OldIES"); + // provider.addAlgorithm("Cipher.OLDDHIESwithAES", PREFIX + "IESCipher$OldIESwithAES"); + // provider.addAlgorithm("Cipher.OLDDHIESWITHAES", PREFIX + "IESCipher$OldIESwithAES"); + // provider.addAlgorithm("Cipher.OLDDHIESWITHDESEDE", PREFIX + "IESCipher$OldIESwithDESede"); // END android-removed registerOid(provider, PKCSObjectIdentifiers.dhKeyAgreement, "DH", new KeyFactorySpi()); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java index 1266abd0..91500c9c 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java @@ -3,12 +3,16 @@ package org.bouncycastle.jcajce.provider.asymmetric; // BEGIN android-removed // import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers; // import org.bouncycastle.asn1.eac.EACObjectIdentifiers; +// import org.bouncycastle.asn1.sec.SECObjectIdentifiers; // import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; // END android-removed import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi; import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; import org.bouncycastle.jcajce.provider.util.AsymmetricAlgorithmProvider; +// BEGIN android-removed +// import org.bouncycastle.util.Properties; +// END android-removed public class EC { @@ -23,31 +27,116 @@ public class EC public void configure(ConfigurableProvider provider) { + // BEGIN android-removed + // provider.addAlgorithm("AlgorithmParameters.EC", PREFIX + "AlgorithmParametersSpi"); + // END android-removed + provider.addAlgorithm("KeyAgreement.ECDH", PREFIX + "KeyAgreementSpi$DH"); // BEGIN android-removed // provider.addAlgorithm("KeyAgreement.ECDHC", PREFIX + "KeyAgreementSpi$DHC"); - // provider.addAlgorithm("KeyAgreement.ECMQV", PREFIX + "KeyAgreementSpi$MQV"); - // provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA1KDF"); - // provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA1KDF"); + // provider.addAlgorithm("KeyAgreement.ECCDH", PREFIX + "KeyAgreementSpi$DHC"); + // + // provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA1KDFAndSharedInfo"); + // provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_cofactorDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA1KDFAndSharedInfo"); + // + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA224KDFAndSharedInfo"); + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA224KDFAndSharedInfo"); + // + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA256KDFAndSharedInfo"); + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA256KDFAndSharedInfo"); + // + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA384KDFAndSharedInfo"); + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA384KDFAndSharedInfo"); + // + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA512KDFAndSharedInfo"); + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA512KDFAndSharedInfo"); + // // provider.addAlgorithm("KeyAgreement.ECDHWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHwithSHA1KDF"); + // + // provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA1CKDF", PREFIX + "KeyAgreementSpi$DHwithSHA1CKDF"); + // provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA256CKDF", PREFIX + "KeyAgreementSpi$DHwithSHA256CKDF"); + // provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA384CKDF", PREFIX + "KeyAgreementSpi$DHwithSHA384CKDF"); + // provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA512CKDF", PREFIX + "KeyAgreementSpi$DHwithSHA512CKDF"); // END android-removed registerOid(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC", new KeyFactorySpi.EC()); - // TODO Should this be an alias for ECDH? + // BEGIN android-added + // We were having this one in 1.52. As of 1.54 this one is under + // if (!Properties.isOverrideSet("org.bouncycastle.ec.disable_mqv")) + // below registerOid(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC", new KeyFactorySpi.EC()); + // END android-added + // BEGIN android-removed + // registerOid(provider, X9ObjectIdentifiers.dhSinglePass_cofactorDH_sha1kdf_scheme, "EC", new KeyFactorySpi.EC()); // registerOid(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV()); // + // registerOid(provider, SECObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme, "EC", new KeyFactorySpi.EC()); + // registerOid(provider, SECObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme, "EC", new KeyFactorySpi.EC()); + // + // registerOid(provider, SECObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme, "EC", new KeyFactorySpi.EC()); + // registerOid(provider, SECObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme, "EC", new KeyFactorySpi.EC()); + // + // registerOid(provider, SECObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme, "EC", new KeyFactorySpi.EC()); + // registerOid(provider, SECObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme, "EC", new KeyFactorySpi.EC()); + // + // registerOid(provider, SECObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme, "EC", new KeyFactorySpi.EC()); + // registerOid(provider, SECObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme, "EC", new KeyFactorySpi.EC()); + // // // Android comment: the registration below is causing CTS tests to fail and doesn't seem // // to be implemented by bouncycastle (so looks like an bug in bouncycastle). + // // TODO(26929227): check this still happens // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC"); - // END android-removed - // TODO Should this be an alias for ECDH? - // BEGIN android-removed - // // Android comment: the registration below is causing CTS tests to fail and doesn't seem - // // to be implemented by bouncycastle (so looks like an bug in bouncycastle). + // // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC"); - // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "EC"); + // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_cofactorDH_sha1kdf_scheme, "EC"); + // + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme, "EC"); + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme, "EC"); + // + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme, "EC"); + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme, "EC"); + // + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme, "EC"); + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme, "EC"); + // + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme, "EC"); + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme, "EC"); + // + // if (!Properties.isOverrideSet("org.bouncycastle.ec.disable_mqv")) + // { + // provider.addAlgorithm("KeyAgreement.ECMQV", PREFIX + "KeyAgreementSpi$MQV"); + // + // provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA1CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA1CKDF"); + // provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA224CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA224CKDF"); + // provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA256CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA256CKDF"); + // provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA384CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA384CKDF"); + // provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA512CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA512CKDF"); + // + // provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA1KDFAndSharedInfo"); + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.mqvSinglePass_sha224kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA224KDFAndSharedInfo"); + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.mqvSinglePass_sha256kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA256KDFAndSharedInfo"); + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.mqvSinglePass_sha384kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA384KDFAndSharedInfo"); + // provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.mqvSinglePass_sha512kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA512KDFAndSharedInfo"); + // + // registerOid(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC", new KeyFactorySpi.EC()); + // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "EC"); + // + // registerOid(provider, SECObjectIdentifiers.mqvSinglePass_sha224kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV()); + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.mqvSinglePass_sha256kdf_scheme, "EC"); + // + // registerOid(provider, SECObjectIdentifiers.mqvSinglePass_sha256kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV()); + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.mqvSinglePass_sha224kdf_scheme, "EC"); + // + // registerOid(provider, SECObjectIdentifiers.mqvSinglePass_sha384kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV()); + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.mqvSinglePass_sha384kdf_scheme, "EC"); + // + // registerOid(provider, SECObjectIdentifiers.mqvSinglePass_sha512kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV()); + // registerOidAlgorithmParameters(provider, SECObjectIdentifiers.mqvSinglePass_sha512kdf_scheme, "EC"); + // + // provider.addAlgorithm("KeyFactory.ECMQV", PREFIX + "KeyFactorySpi$ECMQV"); + // provider.addAlgorithm("KeyPairGenerator.ECMQV", PREFIX + "KeyPairGeneratorSpi$ECMQV"); + // } // END android-removed provider.addAlgorithm("KeyFactory.EC", PREFIX + "KeyFactorySpi$EC"); @@ -55,7 +144,6 @@ public class EC // provider.addAlgorithm("KeyFactory.ECDSA", PREFIX + "KeyFactorySpi$ECDSA"); // provider.addAlgorithm("KeyFactory.ECDH", PREFIX + "KeyFactorySpi$ECDH"); // provider.addAlgorithm("KeyFactory.ECDHC", PREFIX + "KeyFactorySpi$ECDHC"); - // provider.addAlgorithm("KeyFactory.ECMQV", PREFIX + "KeyFactorySpi$ECMQV"); // END android-removed provider.addAlgorithm("KeyPairGenerator.EC", PREFIX + "KeyPairGeneratorSpi$EC"); @@ -65,7 +153,6 @@ public class EC // provider.addAlgorithm("KeyPairGenerator.ECDHWITHSHA1KDF", PREFIX + "KeyPairGeneratorSpi$ECDH"); // provider.addAlgorithm("KeyPairGenerator.ECDHC", PREFIX + "KeyPairGeneratorSpi$ECDHC"); // provider.addAlgorithm("KeyPairGenerator.ECIES", PREFIX + "KeyPairGeneratorSpi$ECDH"); - // provider.addAlgorithm("KeyPairGenerator.ECMQV", PREFIX + "KeyPairGeneratorSpi$ECMQV"); // // provider.addAlgorithm("Cipher.ECIES", PREFIX + "IESCipher$ECIES"); // provider.addAlgorithm("Cipher.ECIESwithAES", PREFIX + "IESCipher$ECIESwithAES"); @@ -76,6 +163,16 @@ public class EC // provider.addAlgorithm("Cipher.ECIESWITHAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC"); // provider.addAlgorithm("Cipher.ECIESwithDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC"); // provider.addAlgorithm("Cipher.ECIESWITHDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC"); + // + // provider.addAlgorithm("Cipher.OldECIES", PREFIX + "IESCipher$OldECIES"); + // provider.addAlgorithm("Cipher.OldECIESwithAES", PREFIX + "IESCipher$OldECIESwithAES"); + // provider.addAlgorithm("Cipher.OldECIESWITHAES", PREFIX + "IESCipher$OldECIESwithAES"); + // provider.addAlgorithm("Cipher.OldECIESwithDESEDE", PREFIX + "IESCipher$OldECIESwithDESede"); + // provider.addAlgorithm("Cipher.OldECIESWITHDESEDE", PREFIX + "IESCipher$OldECIESwithDESede"); + // provider.addAlgorithm("Cipher.OldECIESwithAES-CBC", PREFIX + "IESCipher$OldECIESwithAESCBC"); + // provider.addAlgorithm("Cipher.OldECIESWITHAES-CBC", PREFIX + "IESCipher$OldECIESwithAESCBC"); + // provider.addAlgorithm("Cipher.OldECIESwithDESEDE-CBC", PREFIX + "IESCipher$OldECIESwithDESedeCBC"); + // provider.addAlgorithm("Cipher.OldECIESWITHDESEDE-CBC", PREFIX + "IESCipher$OldECIESwithDESedeCBC"); // END android-removed provider.addAlgorithm("Signature.ECDSA", PREFIX + "SignatureSpi$ecDSA"); @@ -91,12 +188,19 @@ public class EC // BEGIN android-removed // provider.addAlgorithm("Alg.Alias.Signature." + TeleTrusTObjectIdentifiers.ecSignWithSha1, "ECDSA"); // - // provider.addAlgorithm("Signature.DETECDSA", PREFIX + "SignatureSpi$ecDetDSA"); - // provider.addAlgorithm("Signature.SHA1WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA"); - // provider.addAlgorithm("Signature.SHA224WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA224"); - // provider.addAlgorithm("Signature.SHA256WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA256"); - // provider.addAlgorithm("Signature.SHA384WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA384"); - // provider.addAlgorithm("Signature.SHA512WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA512"); + // provider.addAlgorithm("Signature.ECDDSA", PREFIX + "SignatureSpi$ecDetDSA"); + // provider.addAlgorithm("Signature.SHA1WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSA"); + // provider.addAlgorithm("Signature.SHA224WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSA224"); + // provider.addAlgorithm("Signature.SHA256WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSA256"); + // provider.addAlgorithm("Signature.SHA384WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSA384"); + // provider.addAlgorithm("Signature.SHA512WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSA512"); + // + // provider.addAlgorithm("Alg.Alias.Signature.DETECDSA", "ECDDSA"); + // provider.addAlgorithm("Alg.Alias.Signature.SHA1WITHDETECDSA", "SHA1WITHECDDSA"); + // provider.addAlgorithm("Alg.Alias.Signature.SHA224WITHDETECDSA", "SHA224WITHECDDSA"); + // provider.addAlgorithm("Alg.Alias.Signature.SHA256WITHDETECDSA", "SHA256WITHECDDSA"); + // provider.addAlgorithm("Alg.Alias.Signature.SHA384WITHDETECDSA", "SHA384WITHECDDSA"); + // provider.addAlgorithm("Alg.Alias.Signature.SHA512WITHDETECDSA", "SHA512WITHECDDSA"); // END android-removed addSignatureAlgorithm(provider, "SHA224", "ECDSA", PREFIX + "SignatureSpi$ecDSA224", X9ObjectIdentifiers.ecdsa_with_SHA224); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java index 37ca5139..5098c33d 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java @@ -53,12 +53,12 @@ public class RSA // END android-changed // BEGIN android-removed // provider.addAlgorithm("Cipher.RSA/PKCS1", PREFIX + "CipherSpi$PKCS1v1_5Padding"); - // provider.addAlgorithm("Cipher.1.2.840.113549.1.1.1", PREFIX + "CipherSpi$PKCS1v1_5Padding"); - // provider.addAlgorithm("Cipher.2.5.8.1.1", PREFIX + "CipherSpi$PKCS1v1_5Padding"); + // provider.addAlgorithm("Cipher", PKCSObjectIdentifiers.rsaEncryption, PREFIX + "CipherSpi$PKCS1v1_5Padding"); + // provider.addAlgorithm("Cipher", X509ObjectIdentifiers.id_ea_rsa, PREFIX + "CipherSpi$PKCS1v1_5Padding"); // provider.addAlgorithm("Cipher.RSA/1", PREFIX + "CipherSpi$PKCS1v1_5Padding_PrivateOnly"); // provider.addAlgorithm("Cipher.RSA/2", PREFIX + "CipherSpi$PKCS1v1_5Padding_PublicOnly"); // provider.addAlgorithm("Cipher.RSA/OAEP", PREFIX + "CipherSpi$OAEPPadding"); - // provider.addAlgorithm("Cipher." + PKCSObjectIdentifiers.id_RSAES_OAEP, PREFIX + "CipherSpi$OAEPPadding"); + // provider.addAlgorithm("Cipher", PKCSObjectIdentifiers.id_RSAES_OAEP, PREFIX + "CipherSpi$OAEPPadding"); // provider.addAlgorithm("Cipher.RSA/ISO9796-1", PREFIX + "CipherSpi$ISO9796d1Padding"); // END android-removed @@ -86,20 +86,10 @@ public class RSA // registerOidAlgorithmParameters(provider, PKCSObjectIdentifiers.id_RSAES_OAEP, "OAEP"); // registerOidAlgorithmParameters(provider, PKCSObjectIdentifiers.id_RSASSA_PSS, "PSS"); // - // // provider.addAlgorithm("Signature.RSASSA-PSS", PREFIX + "PSSSignatureSpi$PSSwithRSA"); // provider.addAlgorithm("Signature." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA"); // provider.addAlgorithm("Signature.OID." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA"); // - // provider.addAlgorithm("Signature.SHA224WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA224withRSA"); - // provider.addAlgorithm("Signature.SHA256WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA256withRSA"); - // provider.addAlgorithm("Signature.SHA384WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA384withRSA"); - // provider.addAlgorithm("Signature.SHA512WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA512withRSA"); - // provider.addAlgorithm("Signature.SHA224withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA224withRSA"); - // provider.addAlgorithm("Signature.SHA256withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA256withRSA"); - // provider.addAlgorithm("Signature.SHA384withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA384withRSA"); - // provider.addAlgorithm("Signature.SHA512withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA512withRSA"); - // // provider.addAlgorithm("Signature.RSA", PREFIX + "DigestSignatureSpi$noneRSA"); // provider.addAlgorithm("Signature.RAWRSASSA-PSS", PREFIX + "PSSSignatureSpi$nonePSS"); // @@ -111,11 +101,12 @@ public class RSA // provider.addAlgorithm("Alg.Alias.Signature.NONEWITHRSAANDMGF1", "RAWRSASSA-PSS"); // provider.addAlgorithm("Alg.Alias.Signature.RSAPSS", "RSASSA-PSS"); // - // - // provider.addAlgorithm("Alg.Alias.Signature.SHA224withRSAandMGF1", "SHA224withRSA/PSS"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA256withRSAandMGF1", "SHA256withRSA/PSS"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA384withRSAandMGF1", "SHA384withRSA/PSS"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA512withRSAandMGF1", "SHA512withRSA/PSS"); + // addPSSSignature(provider, "SHA224", PREFIX + "PSSSignatureSpi$SHA224withRSA"); + // addPSSSignature(provider, "SHA256", PREFIX + "PSSSignatureSpi$SHA256withRSA"); + // addPSSSignature(provider, "SHA384", PREFIX + "PSSSignatureSpi$SHA384withRSA"); + // addPSSSignature(provider, "SHA512", PREFIX + "PSSSignatureSpi$SHA512withRSA"); + // addPSSSignature(provider, "SHA512(224)", PREFIX + "PSSSignatureSpi$SHA512_224withRSA"); + // addPSSSignature(provider, "SHA512(256)", PREFIX + "PSSSignatureSpi$SHA512_256withRSA"); // // if (provider.hasAlgorithm("MessageDigest", "MD2")) // { @@ -131,9 +122,8 @@ public class RSA if (provider.hasAlgorithm("MessageDigest", "MD5")) { addDigestSignature(provider, "MD5", PREFIX + "DigestSignatureSpi$MD5", PKCSObjectIdentifiers.md5WithRSAEncryption); - // END android-removed - // provider.addAlgorithm("Signature.MD5withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$MD5WithRSAEncryption"); - // provider.addAlgorithm("Alg.Alias.Signature.MD5WithRSA/ISO9796-2", "MD5withRSA/ISO9796-2"); + // BEGIN android-removed + // addISO9796Signature(provider, "MD5", PREFIX + "ISOSignatureSpi$MD5WithRSAEncryption"); // END android-removed } @@ -142,24 +132,19 @@ public class RSA // BEGIN android-removed // provider.addAlgorithm("Alg.Alias.AlgorithmParameters.SHA1withRSA/PSS", "PSS"); // provider.addAlgorithm("Alg.Alias.AlgorithmParameters.SHA1WITHRSAANDMGF1", "PSS"); - // provider.addAlgorithm("Signature.SHA1withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA1withRSA"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA1withRSAandMGF1", "SHA1withRSA/PSS"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA1WITHRSAANDMGF1", "SHA1withRSA/PSS"); + // + // addPSSSignature(provider, "SHA1", PREFIX + "PSSSignatureSpi$SHA1withRSA"); // END android-removed - addDigestSignature(provider, "SHA1", PREFIX + "DigestSignatureSpi$SHA1", PKCSObjectIdentifiers.sha1WithRSAEncryption); - // BEGIN android-removed - // provider.addAlgorithm("Alg.Alias.Signature.SHA1WithRSA/ISO9796-2", "SHA1withRSA/ISO9796-2"); - // provider.addAlgorithm("Signature.SHA1withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$SHA1WithRSAEncryption"); + // addISO9796Signature(provider, "SHA1", PREFIX + "ISOSignatureSpi$SHA1WithRSAEncryption"); // END android-removed + provider.addAlgorithm("Alg.Alias.Signature." + OIWObjectIdentifiers.sha1WithRSA, "SHA1WITHRSA"); provider.addAlgorithm("Alg.Alias.Signature.OID." + OIWObjectIdentifiers.sha1WithRSA, "SHA1WITHRSA"); // BEGIN android-removed - // provider.addAlgorithm("Alg.Alias.Signature.SHA1withRSA/X9.31", "SHA1WITHRSA/X9.31"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA1WithRSA/X9.31", "SHA1WITHRSA/X9.31"); - // provider.addAlgorithm("Signature.SHA1WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA1WithRSAEncryption"); + // addX931Signature(provider, "SHA1", PREFIX + "X931SignatureSpi$SHA1WithRSAEncryption"); // END android-removed } @@ -169,18 +154,22 @@ public class RSA addDigestSignature(provider, "SHA512", PREFIX + "DigestSignatureSpi$SHA512", PKCSObjectIdentifiers.sha512WithRSAEncryption); // BEGIN android-removed - // provider.addAlgorithm("Alg.Alias.Signature.SHA224withRSA/X9.31", "SHA224WITHRSA/X9.31"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA224WithRSA/X9.31", "SHA224WITHRSA/X9.31"); - // provider.addAlgorithm("Signature.SHA224WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA224WithRSAEncryption"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA256withRSA/X9.31", "SHA256WITHRSA/X9.31"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA256WithRSA/X9.31", "SHA256WITHRSA/X9.31"); - // provider.addAlgorithm("Signature.SHA256WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA256WithRSAEncryption"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA384withRSA/X9.31", "SHA384WITHRSA/X9.31"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA384WithRSA/X9.31", "SHA384WITHRSA/X9.31"); - // provider.addAlgorithm("Signature.SHA384WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA384WithRSAEncryption"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA512withRSA/X9.31", "SHA512WITHRSA/X9.31"); - // provider.addAlgorithm("Alg.Alias.Signature.SHA512WithRSA/X9.31", "SHA512WITHRSA/X9.31"); - // provider.addAlgorithm("Signature.SHA512WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA512WithRSAEncryption"); + // addDigestSignature(provider, "SHA512(224)", PREFIX + "DigestSignatureSpi$SHA512_224", null); + // addDigestSignature(provider, "SHA512(256)", PREFIX + "DigestSignatureSpi$SHA512_256", null); + + // addISO9796Signature(provider, "SHA224", PREFIX + "ISOSignatureSpi$SHA224WithRSAEncryption"); + // addISO9796Signature(provider, "SHA256", PREFIX + "ISOSignatureSpi$SHA256WithRSAEncryption"); + // addISO9796Signature(provider, "SHA384", PREFIX + "ISOSignatureSpi$SHA384WithRSAEncryption"); + // addISO9796Signature(provider, "SHA512", PREFIX + "ISOSignatureSpi$SHA512WithRSAEncryption"); + // addISO9796Signature(provider, "SHA512(224)", PREFIX + "ISOSignatureSpi$SHA512_224WithRSAEncryption"); + // addISO9796Signature(provider, "SHA512(256)", PREFIX + "ISOSignatureSpi$SHA512_256WithRSAEncryption"); + // + // addX931Signature(provider, "SHA224", PREFIX + "X931SignatureSpi$SHA224WithRSAEncryption"); + // addX931Signature(provider, "SHA256", PREFIX + "X931SignatureSpi$SHA256WithRSAEncryption"); + // addX931Signature(provider, "SHA384", PREFIX + "X931SignatureSpi$SHA384WithRSAEncryption"); + // addX931Signature(provider, "SHA512", PREFIX + "X931SignatureSpi$SHA512WithRSAEncryption"); + // addX931Signature(provider, "SHA512(224)", PREFIX + "X931SignatureSpi$SHA512_224WithRSAEncryption"); + // addX931Signature(provider, "SHA512(256)", PREFIX + "X931SignatureSpi$SHA512_256WithRSAEncryption"); // // if (provider.hasAlgorithm("MessageDigest", "RIPEMD128")) // { @@ -246,5 +235,37 @@ public class RSA provider.addAlgorithm("Alg.Alias.Signature.OID." + oid, mainName); } } + + private void addISO9796Signature( + ConfigurableProvider provider, + String digest, + String className) + { + provider.addAlgorithm("Alg.Alias.Signature." + digest + "withRSA/ISO9796-2", digest + "WITHRSA/ISO9796-2"); + provider.addAlgorithm("Alg.Alias.Signature." + digest + "WithRSA/ISO9796-2", digest + "WITHRSA/ISO9796-2"); + provider.addAlgorithm("Signature." + digest + "WITHRSA/ISO9796-2", className); + } + + private void addPSSSignature( + ConfigurableProvider provider, + String digest, + String className) + { + provider.addAlgorithm("Alg.Alias.Signature." + digest + "withRSA/PSS", digest + "WITHRSAANDMGF1"); + provider.addAlgorithm("Alg.Alias.Signature." + digest + "WithRSA/PSS", digest + "WITHRSAANDMGF1"); + provider.addAlgorithm("Alg.Alias.Signature." + digest + "withRSAandMGF1", digest + "WITHRSAANDMGF1"); + provider.addAlgorithm("Alg.Alias.Signature." + digest + "WithRSAAndMGF1", digest + "WITHRSAANDMGF1"); + provider.addAlgorithm("Signature." + digest + "WITHRSAANDMGF1", className); + } + + private void addX931Signature( + ConfigurableProvider provider, + String digest, + String className) + { + provider.addAlgorithm("Alg.Alias.Signature." + digest + "withRSA/X9.31", digest + "WITHRSA/X9.31"); + provider.addAlgorithm("Alg.Alias.Signature." + digest + "WithRSA/X9.31", digest + "WITHRSA/X9.31"); + provider.addAlgorithm("Signature." + digest + "WITHRSA/X9.31", className); + } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParametersSpi.java index c7711238..608171bf 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParametersSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParametersSpi.java @@ -73,7 +73,7 @@ public class AlgorithmParametersSpi Class paramSpec) throws InvalidParameterSpecException { - if (paramSpec == DHParameterSpec.class) + if (paramSpec == DHParameterSpec.class || paramSpec == AlgorithmParameterSpec.class) { return currentSpec; } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPrivateKey.java index d5516dce..6fb54b67 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPrivateKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPrivateKey.java @@ -20,6 +20,7 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x9.DHDomainParameters; +import org.bouncycastle.asn1.x9.DomainParameters; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.DHPrivateKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl; @@ -82,9 +83,9 @@ public class BCDHPrivateKey } else if (id.equals(X9ObjectIdentifiers.dhpublicnumber)) { - DHDomainParameters params = DHDomainParameters.getInstance(seq); + DomainParameters params = DomainParameters.getInstance(seq); - this.dhSpec = new DHParameterSpec(params.getP().getValue(), params.getG().getValue()); + this.dhSpec = new DHParameterSpec(params.getP(), params.getG()); } else { diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java index 0697f757..ef743095 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java @@ -17,6 +17,7 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.DHDomainParameters; +import org.bouncycastle.asn1.x9.DomainParameters; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.DHPublicKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; @@ -96,9 +97,9 @@ public class BCDHPublicKey } else if (id.equals(X9ObjectIdentifiers.dhpublicnumber)) { - DHDomainParameters params = DHDomainParameters.getInstance(seq); + DomainParameters params = DomainParameters.getInstance(seq); - this.dhSpec = new DHParameterSpec(params.getP().getValue(), params.getG().getValue()); + this.dhSpec = new DHParameterSpec(params.getP(), params.getG()); } else { diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java index f2b5314f..3de8ffe5 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java @@ -4,9 +4,9 @@ import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; +import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; -import java.util.Hashtable; import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; @@ -15,9 +15,13 @@ import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.SecretKeySpec; -import org.bouncycastle.crypto.params.DESParameters; -import org.bouncycastle.util.Integers; -import org.bouncycastle.util.Strings; +import org.bouncycastle.crypto.DerivationFunction; +// BEGIN android-removed +// import org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator; +// END android-removed +import org.bouncycastle.crypto.digests.SHA1Digest; +import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi; +import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec; /** * Diffie-Hellman key agreement. There's actually a better way of doing this @@ -25,29 +29,25 @@ import org.bouncycastle.util.Strings; * details. */ public class KeyAgreementSpi - extends javax.crypto.KeyAgreementSpi + extends BaseAgreementSpi { private BigInteger x; private BigInteger p; private BigInteger g; - private BigInteger result; - private static final Hashtable algorithms = new Hashtable(); + public KeyAgreementSpi() + { + super("Diffie-Hellman", null); + } - static + public KeyAgreementSpi( + String kaAlgorithm, + DerivationFunction kdf) { - Integer i64 = Integers.valueOf(64); - Integer i192 = Integers.valueOf(192); - Integer i128 = Integers.valueOf(128); - Integer i256 = Integers.valueOf(256); - - algorithms.put("DES", i64); - algorithms.put("DESEDE", i192); - algorithms.put("BLOWFISH", i128); - algorithms.put("AES", i256); + super(kaAlgorithm, kdf); } - private byte[] bigIntToBytes( + protected byte[] bigIntToBytes( BigInteger r) { // @@ -122,7 +122,7 @@ public class KeyAgreementSpi throw new IllegalStateException("Diffie-Hellman not initialised."); } - return bigIntToBytes(result); + return super.engineGenerateSecret(); } protected int engineGenerateSecret( @@ -135,45 +135,27 @@ public class KeyAgreementSpi throw new IllegalStateException("Diffie-Hellman not initialised."); } - byte[] secret = bigIntToBytes(result); - - if (sharedSecret.length - offset < secret.length) - { - throw new ShortBufferException("DHKeyAgreement - buffer too short"); - } - - System.arraycopy(secret, 0, sharedSecret, offset, secret.length); - - return secret.length; + return super.engineGenerateSecret(sharedSecret, offset); } protected SecretKey engineGenerateSecret( - String algorithm) + String algorithm) + throws NoSuchAlgorithmException { if (x == null) { throw new IllegalStateException("Diffie-Hellman not initialised."); } - String algKey = Strings.toUpperCase(algorithm); byte[] res = bigIntToBytes(result); - if (algorithms.containsKey(algKey)) + // for JSSE compatibility + if (algorithm.equals("TlsPremasterSecret")) { - Integer length = (Integer)algorithms.get(algKey); - - byte[] key = new byte[length.intValue() / 8]; - System.arraycopy(res, 0, key, 0, key.length); - - if (algKey.startsWith("DES")) - { - DESParameters.setOddParity(key); - } - - return new SecretKeySpec(key, algorithm); + return new SecretKeySpec(trimZeroes(res), algorithm); } - return new SecretKeySpec(res, algorithm); + return super.engineGenerateSecret(algorithm); } protected void engineInit( @@ -190,14 +172,23 @@ public class KeyAgreementSpi if (params != null) { - if (!(params instanceof DHParameterSpec)) + if (params instanceof DHParameterSpec) // p, g override. + { + DHParameterSpec p = (DHParameterSpec)params; + + this.p = p.getP(); + this.g = p.getG(); + } + else if (params instanceof UserKeyingMaterialSpec) + { + this.p = privKey.getParams().getP(); + this.g = privKey.getParams().getG(); + this.ukmParameters = ((UserKeyingMaterialSpec)params).getUserKeyingMaterial(); + } + else { throw new InvalidAlgorithmParameterException("DHKeyAgreement only accepts DHParameterSpec"); } - DHParameterSpec p = (DHParameterSpec)params; - - this.p = p.getP(); - this.g = p.getG(); } else { @@ -224,4 +215,15 @@ public class KeyAgreementSpi this.g = privKey.getParams().getG(); this.x = this.result = privKey.getX(); } + + // BEGIN android-removed + // public static class DHwithRFC2631KDF + // extends KeyAgreementSpi + // { + // public DHwithRFC2631KDF() + // { + // super("DHwithRFC2631KDF", new DHKEKGenerator(new SHA1Digest())); + // } + // } + // END android-removed } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java index 57224797..c6aac7c0 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java @@ -69,7 +69,7 @@ public class AlgorithmParametersSpi Class paramSpec) throws InvalidParameterSpecException { - if (paramSpec == DSAParameterSpec.class) + if (paramSpec == DSAParameterSpec.class || paramSpec == AlgorithmParameterSpec.class) { return currentSpec; } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java index e66330b3..3a7b3121 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java @@ -18,6 +18,7 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.DSAPublicKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.bouncycastle.util.Strings; public class BCDSAPublicKey implements DSAPublicKey @@ -119,7 +120,7 @@ public class BCDSAPublicKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("DSA Public Key").append(nl); buf.append(" y: ").append(this.getY().toString(16)).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java new file mode 100644 index 00000000..6af71e80 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java @@ -0,0 +1,167 @@ +package org.bouncycastle.jcajce.provider.asymmetric.ec; + +import java.io.IOException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.InvalidParameterSpecException; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.x9.ECNamedCurveTable; +import org.bouncycastle.asn1.x9.X962Parameters; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; +import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.math.ec.ECCurve; + +public class AlgorithmParametersSpi + extends java.security.AlgorithmParametersSpi +{ + private ECParameterSpec ecParameterSpec; + private String curveName; + + protected boolean isASN1FormatString(String format) + { + return format == null || format.equals("ASN.1"); + } + + @Override + protected void engineInit(AlgorithmParameterSpec algorithmParameterSpec) + throws InvalidParameterSpecException + { + if (algorithmParameterSpec instanceof ECGenParameterSpec) + { + ECGenParameterSpec ecGenParameterSpec = (ECGenParameterSpec)algorithmParameterSpec; + X9ECParameters params = ECUtils.getDomainParametersFromGenSpec(ecGenParameterSpec); + + if (params == null) + { + throw new InvalidParameterSpecException("EC curve name not recognized: " + ecGenParameterSpec.getName()); + } + curveName = ecGenParameterSpec.getName(); + ecParameterSpec = EC5Util.convertToSpec(params); + } + else if (algorithmParameterSpec instanceof ECParameterSpec) + { + curveName = null; + ecParameterSpec = (ECParameterSpec)algorithmParameterSpec; + } + else + { + throw new InvalidParameterSpecException("AlgorithmParameterSpec class not recognized: " + algorithmParameterSpec.getClass().getName()); + } + } + + @Override + protected void engineInit(byte[] bytes) + throws IOException + { + engineInit(bytes, "ASN.1"); + } + + @Override + protected void engineInit(byte[] bytes, String format) + throws IOException + { + if (isASN1FormatString(format)) + { + X962Parameters params = X962Parameters.getInstance(bytes); + + ECCurve curve = EC5Util.getCurve(BouncyCastleProvider.CONFIGURATION, params); + + if (params.isNamedCurve()) + { + curveName = ECNamedCurveTable.getName(ASN1ObjectIdentifier.getInstance(params.getParameters())); + } + + ecParameterSpec = EC5Util.convertToSpec(params, curve); + } + else + { + throw new IOException("Unknown encoded parameters format in AlgorithmParameters object: " + format); + } + } + + @Override + protected <T extends AlgorithmParameterSpec> T engineGetParameterSpec(Class<T> paramSpec) + throws InvalidParameterSpecException + { + if (ECParameterSpec.class.isAssignableFrom(paramSpec) || paramSpec == AlgorithmParameterSpec.class) + { + return (T)ecParameterSpec; + } + else if (ECGenParameterSpec.class.isAssignableFrom(paramSpec)) + { + if (curveName != null) + { + ASN1ObjectIdentifier namedCurveOid = ECUtil.getNamedCurveOid(curveName); + + if (namedCurveOid != null) + { + return (T)new ECGenParameterSpec(namedCurveOid.getId()); + } + return (T)new ECGenParameterSpec(curveName); + } + else + { + ASN1ObjectIdentifier namedCurveOid = ECUtil.getNamedCurveOid(EC5Util.convertSpec(ecParameterSpec, false)); + + if (namedCurveOid != null) + { + return (T)new ECGenParameterSpec(namedCurveOid.getId()); + } + } + } + throw new InvalidParameterSpecException("EC AlgorithmParameters cannot convert to " + paramSpec.getName()); + } + + @Override + protected byte[] engineGetEncoded() + throws IOException + { + return engineGetEncoded("ASN.1"); + } + + @Override + protected byte[] engineGetEncoded(String format) + throws IOException + { + if (isASN1FormatString(format)) + { + X962Parameters params; + + if (ecParameterSpec == null) // implicitly CA + { + params = new X962Parameters(DERNull.INSTANCE); + } + else if (curveName != null) + { + params = new X962Parameters(ECUtil.getNamedCurveOid(curveName)); + } + else + { + org.bouncycastle.jce.spec.ECParameterSpec ecSpec = EC5Util.convertSpec(ecParameterSpec, false); + X9ECParameters ecP = new X9ECParameters( + ecSpec.getCurve(), + ecSpec.getG(), + ecSpec.getN(), + ecSpec.getH(), + ecSpec.getSeed()); + + params = new X962Parameters(ecP); + } + + return params.getEncoded(); + } + + throw new IOException("Unknown parameters format in AlgorithmParameters object: " + format); + } + + @Override + protected String engineToString() + { + return "EC AlgorithmParameters "; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java index c9ad4455..e69942a2 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java @@ -35,6 +35,7 @@ import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.util.Strings; public class BCECPrivateKey implements ECPrivateKey, org.bouncycastle.jce.interfaces.ECPrivateKey, PKCS12BagAttributeCarrier, ECPointEncoder @@ -210,38 +211,8 @@ public class BCECPrivateKey { X962Parameters params = X962Parameters.getInstance(info.getPrivateKeyAlgorithm().getParameters()); - if (params.isNamedCurve()) - { - ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters()); - X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); - EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed()); - - ecSpec = new ECNamedCurveSpec( - ECUtil.getCurveName(oid), - ellipticCurve, - new ECPoint( - ecP.getG().getAffineXCoord().toBigInteger(), - ecP.getG().getAffineYCoord().toBigInteger()), - ecP.getN(), - ecP.getH()); - } - else if (params.isImplicitlyCA()) - { - ecSpec = null; - } - else - { - X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); - EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed()); - - this.ecSpec = new ECParameterSpec( - ellipticCurve, - new ECPoint( - ecP.getG().getAffineXCoord().toBigInteger(), - ecP.getG().getAffineYCoord().toBigInteger()), - ecP.getN(), - ecP.getH().intValue()); - } + ECCurve curve = EC5Util.getCurve(configuration, params); + ecSpec = EC5Util.convertToSpec(params, curve); ASN1Encodable privKey = info.parsePrivateKey(); if (privKey instanceof ASN1Integer) @@ -418,7 +389,7 @@ public class BCECPrivateKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("EC Private Key").append(nl); buf.append(" S: ").append(this.d.toString(16)).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java index ac0ddf5b..c3f0dd02 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java @@ -34,8 +34,7 @@ import org.bouncycastle.jce.interfaces.ECPointEncoder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; -import org.bouncycastle.math.ec.custom.sec.SecP256K1Point; -import org.bouncycastle.math.ec.custom.sec.SecP256R1Point; +import org.bouncycastle.util.Strings; public class BCECPublicKey implements ECPublicKey, org.bouncycastle.jce.interfaces.ECPublicKey, ECPointEncoder @@ -202,46 +201,8 @@ public class BCECPublicKey private void populateFromPubKeyInfo(SubjectPublicKeyInfo info) { X962Parameters params = new X962Parameters((ASN1Primitive)info.getAlgorithm().getParameters()); - ECCurve curve; - EllipticCurve ellipticCurve; - - if (params.isNamedCurve()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); - X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); - - curve = ecP.getCurve(); - ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); - - ecSpec = new ECNamedCurveSpec( - ECUtil.getCurveName(oid), - ellipticCurve, - new ECPoint( - ecP.getG().getAffineXCoord().toBigInteger(), - ecP.getG().getAffineYCoord().toBigInteger()), - ecP.getN(), - ecP.getH()); - } - else if (params.isImplicitlyCA()) - { - ecSpec = null; - curve = configuration.getEcImplicitlyCa().getCurve(); - } - else - { - X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); - - curve = ecP.getCurve(); - ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); - - this.ecSpec = new ECParameterSpec( - ellipticCurve, - new ECPoint( - ecP.getG().getAffineXCoord().toBigInteger(), - ecP.getG().getAffineYCoord().toBigInteger()), - ecP.getN(), - ecP.getH().intValue()); - } + ECCurve curve = EC5Util.getCurve(configuration, params); + ecSpec = EC5Util.convertToSpec(params, curve); DERBitString bits = info.getPublicKeyData(); byte[] data = bits.getBytes(); @@ -267,6 +228,7 @@ public class BCECPublicKey } } } + X9ECPoint derQ = new X9ECPoint(curve, key); this.q = derQ.getPoint(); @@ -398,7 +360,7 @@ public class BCECPublicKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("EC Public Key").append(nl); buf.append(" X: ").append(this.q.getAffineXCoord().toBigInteger().toString(16)).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java new file mode 100644 index 00000000..dc92e0e4 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java @@ -0,0 +1,45 @@ +package org.bouncycastle.jcajce.provider.asymmetric.ec; + +import java.security.spec.ECGenParameterSpec; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; + +class ECUtils +{ + static X9ECParameters getDomainParametersFromGenSpec(ECGenParameterSpec genSpec) + { + return getDomainParametersFromName(genSpec.getName()); + } + + static X9ECParameters getDomainParametersFromName(String curveName) + { + X9ECParameters domainParameters; + try + { + if (curveName.charAt(0) >= '0' && curveName.charAt(0) <= '2') + { + ASN1ObjectIdentifier oidID = new ASN1ObjectIdentifier(curveName); + domainParameters = ECUtil.getNamedCurveByOid(oidID); + } + else + { + if (curveName.indexOf(' ') > 0) + { + curveName = curveName.substring(curveName.indexOf(' ') + 1); + domainParameters = ECUtil.getNamedCurveByName(curveName); + } + else + { + domainParameters = ECUtil.getNamedCurveByName(curveName); + } + } + } + catch (IllegalArgumentException ex) + { + domainParameters = ECUtil.getNamedCurveByName(curveName); + } + return domainParameters; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java index 754b4cae..004e2873 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java @@ -4,21 +4,11 @@ import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; -import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; -import java.util.Hashtable; -import javax.crypto.SecretKey; -import javax.crypto.ShortBufferException; -import javax.crypto.spec.SecretKeySpec; - -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; -import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; -import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x9.X9IntegerConverter; import org.bouncycastle.crypto.BasicAgreement; import org.bouncycastle.crypto.CipherParameters; @@ -27,11 +17,16 @@ import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; // BEGIN android-removed // import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement; // import org.bouncycastle.crypto.agreement.ECMQVBasicAgreement; -// import org.bouncycastle.crypto.agreement.kdf.DHKDFParameters; -// import org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator; +// import org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator; // END android-removed import org.bouncycastle.crypto.digests.SHA1Digest; -import org.bouncycastle.crypto.params.DESParameters; +import org.bouncycastle.crypto.digests.SHA224Digest; +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.digests.SHA384Digest; +import org.bouncycastle.crypto.digests.SHA512Digest; +// BEGIN android-removed +// import org.bouncycastle.crypto.generators.KDF2BytesGenerator; +// END android-removed import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; @@ -39,15 +34,18 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters; // import org.bouncycastle.crypto.params.MQVPrivateParameters; // import org.bouncycastle.crypto.params.MQVPublicParameters; // END android-removed +import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; +// BEGIN android-removed +// import org.bouncycastle.jcajce.spec.MQVParameterSpec; +// END android-removed +import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec; import org.bouncycastle.jce.interfaces.ECPrivateKey; import org.bouncycastle.jce.interfaces.ECPublicKey; // BEGIN android-removed // import org.bouncycastle.jce.interfaces.MQVPrivateKey; // import org.bouncycastle.jce.interfaces.MQVPublicKey; // END android-removed -import org.bouncycastle.util.Integers; -import org.bouncycastle.util.Strings; /** * Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363 @@ -56,65 +54,34 @@ import org.bouncycastle.util.Strings; * Also, MQV key agreement per SEC-1 */ public class KeyAgreementSpi - extends javax.crypto.KeyAgreementSpi + extends BaseAgreementSpi { private static final X9IntegerConverter converter = new X9IntegerConverter(); - private static final Hashtable algorithms = new Hashtable(); - private static final Hashtable oids = new Hashtable(); - private static final Hashtable des = new Hashtable(); - - static - { - Integer i64 = Integers.valueOf(64); - Integer i128 = Integers.valueOf(128); - Integer i192 = Integers.valueOf(192); - Integer i256 = Integers.valueOf(256); - - algorithms.put(NISTObjectIdentifiers.id_aes128_CBC.getId(), i128); - algorithms.put(NISTObjectIdentifiers.id_aes192_CBC.getId(), i192); - algorithms.put(NISTObjectIdentifiers.id_aes256_CBC.getId(), i256); - algorithms.put(NISTObjectIdentifiers.id_aes128_wrap.getId(), i128); - algorithms.put(NISTObjectIdentifiers.id_aes192_wrap.getId(), i192); - algorithms.put(NISTObjectIdentifiers.id_aes256_wrap.getId(), i256); - algorithms.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), i192); - algorithms.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), i192); - algorithms.put(OIWObjectIdentifiers.desCBC.getId(), i64); - - oids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC); - oids.put("AES", NISTObjectIdentifiers.id_aes256_CBC); - oids.put("DES", OIWObjectIdentifiers.desCBC); - - des.put("DES", "DES"); - des.put("DESEDE", "DES"); - des.put(OIWObjectIdentifiers.desCBC.getId(), "DES"); - des.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DES"); - des.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DES"); - } private String kaAlgorithm; - private BigInteger result; + private ECDomainParameters parameters; private BasicAgreement agreement; + // BEGIN android-removed - // private DerivationFunction kdf; + // private MQVParameterSpec mqvParameters; // END android-removed - private byte[] bigIntToBytes( - BigInteger r) - { - return converter.integerToBytes(r, converter.getByteLength(parameters.getCurve())); - } - protected KeyAgreementSpi( String kaAlgorithm, BasicAgreement agreement, DerivationFunction kdf) { + super(kaAlgorithm, kdf); + this.kaAlgorithm = kaAlgorithm; this.agreement = agreement; - // BEGIN android-removed - // this.kdf = kdf; - // END android-removed + } + + protected byte[] bigIntToBytes( + BigInteger r) + { + return converter.integerToBytes(r, converter.getByteLength(parameters.getCurve())); } protected Key engineDoPhase( @@ -138,19 +105,25 @@ public class KeyAgreementSpi // { // if (!(key instanceof MQVPublicKey)) // { - // throw new InvalidKeyException(kaAlgorithm + " key agreement requires " - // + getSimpleName(MQVPublicKey.class) + " for doPhase"); - // } + // ECPublicKeyParameters staticKey = (ECPublicKeyParameters) + // ECUtil.generatePublicKeyParameter((PublicKey)key); + // ECPublicKeyParameters ephemKey = (ECPublicKeyParameters) + // ECUtil.generatePublicKeyParameter(mqvParameters.getOtherPartyEphemeralKey()); // - // MQVPublicKey mqvPubKey = (MQVPublicKey)key; - // ECPublicKeyParameters staticKey = (ECPublicKeyParameters) - // ECUtil.generatePublicKeyParameter(mqvPubKey.getStaticKey()); - // ECPublicKeyParameters ephemKey = (ECPublicKeyParameters) - // ECUtil.generatePublicKeyParameter(mqvPubKey.getEphemeralKey()); + // pubKey = new MQVPublicParameters(staticKey, ephemKey); + // } + // else + // { + // MQVPublicKey mqvPubKey = (MQVPublicKey)key; + // ECPublicKeyParameters staticKey = (ECPublicKeyParameters) + // ECUtil.generatePublicKeyParameter(mqvPubKey.getStaticKey()); + // ECPublicKeyParameters ephemKey = (ECPublicKeyParameters) + // ECUtil.generatePublicKeyParameter(mqvPubKey.getEphemeralKey()); // - // pubKey = new MQVPublicParameters(staticKey, ephemKey); + // pubKey = new MQVPublicParameters(staticKey, ephemKey); // - // // TODO Validate that all the keys are using the same parameters? + // // TODO Validate that all the keys are using the same parameters? + // } // } // else // END android-removed @@ -179,102 +152,20 @@ public class KeyAgreementSpi return null; } - protected byte[] engineGenerateSecret() - throws IllegalStateException - { - // BEGIN android-removed - // if (kdf != null) - // { - // throw new UnsupportedOperationException( - // "KDF can only be used when algorithm is known"); - // } - // END android-removed - - return bigIntToBytes(result); - } - - protected int engineGenerateSecret( - byte[] sharedSecret, - int offset) - throws IllegalStateException, ShortBufferException - { - byte[] secret = engineGenerateSecret(); - - if (sharedSecret.length - offset < secret.length) - { - throw new ShortBufferException(kaAlgorithm + " key agreement: need " + secret.length + " bytes"); - } - - System.arraycopy(secret, 0, sharedSecret, offset, secret.length); - - return secret.length; - } - - protected SecretKey engineGenerateSecret( - String algorithm) - throws NoSuchAlgorithmException - { - byte[] secret = bigIntToBytes(result); - String algKey = Strings.toUpperCase(algorithm); - String oidAlgorithm = algorithm; - - if (oids.containsKey(algKey)) - { - oidAlgorithm = ((ASN1ObjectIdentifier)oids.get(algKey)).getId(); - } - - // BEGIN android-removed - // if (kdf != null) - // { - // if (!algorithms.containsKey(oidAlgorithm)) - // { - // throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm); - // } - // - // int keySize = ((Integer)algorithms.get(oidAlgorithm)).intValue(); - // - // DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(oidAlgorithm), keySize, secret); - // - // byte[] keyBytes = new byte[keySize / 8]; - // kdf.init(params); - // kdf.generateBytes(keyBytes, 0, keyBytes.length); - // secret = keyBytes; - // } - // else - // END android-removed - { - if (algorithms.containsKey(oidAlgorithm)) - { - Integer length = (Integer)algorithms.get(oidAlgorithm); - - byte[] key = new byte[length.intValue() / 8]; - - System.arraycopy(secret, 0, key, 0, key.length); - - secret = key; - } - } - - if (des.containsKey(oidAlgorithm)) - { - DESParameters.setOddParity(secret); - } - - return new SecretKeySpec(secret, algorithm); - } - protected void engineInit( Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { - if (params != null) + // BEGIN android-changed + if (params != null && !(params instanceof UserKeyingMaterialSpec)) + // END android-changed { throw new InvalidAlgorithmParameterException("No algorithm parameters supported"); } - initFromKey(key); + initFromKey(key, params); } protected void engineInit( @@ -282,32 +173,57 @@ public class KeyAgreementSpi SecureRandom random) throws InvalidKeyException { - initFromKey(key); + initFromKey(key, null); } - private void initFromKey(Key key) + private void initFromKey(Key key, AlgorithmParameterSpec parameterSpec) throws InvalidKeyException { // BEGIN android-removed // if (agreement instanceof ECMQVBasicAgreement) // { - // if (!(key instanceof MQVPrivateKey)) + // mqvParameters = null; + // if (!(key instanceof MQVPrivateKey) && !(parameterSpec instanceof MQVParameterSpec)) // { // throw new InvalidKeyException(kaAlgorithm + " key agreement requires " - // + getSimpleName(MQVPrivateKey.class) + " for initialisation"); + // + getSimpleName(MQVParameterSpec.class) + " for initialisation"); // } // - // MQVPrivateKey mqvPrivKey = (MQVPrivateKey)key; - // ECPrivateKeyParameters staticPrivKey = (ECPrivateKeyParameters) - // ECUtil.generatePrivateKeyParameter(mqvPrivKey.getStaticPrivateKey()); - // ECPrivateKeyParameters ephemPrivKey = (ECPrivateKeyParameters) - // ECUtil.generatePrivateKeyParameter(mqvPrivKey.getEphemeralPrivateKey()); + // ECPrivateKeyParameters staticPrivKey; + // ECPrivateKeyParameters ephemPrivKey; + // ECPublicKeyParameters ephemPubKey; + // if (key instanceof MQVPrivateKey) + // { + // MQVPrivateKey mqvPrivKey = (MQVPrivateKey)key; + // staticPrivKey = (ECPrivateKeyParameters) + // ECUtil.generatePrivateKeyParameter(mqvPrivKey.getStaticPrivateKey()); + // ephemPrivKey = (ECPrivateKeyParameters) + // ECUtil.generatePrivateKeyParameter(mqvPrivKey.getEphemeralPrivateKey()); // - // ECPublicKeyParameters ephemPubKey = null; - // if (mqvPrivKey.getEphemeralPublicKey() != null) + // ephemPubKey = null; + // if (mqvPrivKey.getEphemeralPublicKey() != null) + // { + // ephemPubKey = (ECPublicKeyParameters) + // ECUtil.generatePublicKeyParameter(mqvPrivKey.getEphemeralPublicKey()); + // } + // } + // else // { - // ephemPubKey = (ECPublicKeyParameters) - // ECUtil.generatePublicKeyParameter(mqvPrivKey.getEphemeralPublicKey()); + // MQVParameterSpec mqvParameterSpec = (MQVParameterSpec)parameterSpec; + // + // staticPrivKey = (ECPrivateKeyParameters) + // ECUtil.generatePrivateKeyParameter((PrivateKey)key); + // ephemPrivKey = (ECPrivateKeyParameters) + // ECUtil.generatePrivateKeyParameter(mqvParameterSpec.getEphemeralPrivateKey()); + // + // ephemPubKey = null; + // if (mqvParameterSpec.getEphemeralPublicKey() != null) + // { + // ephemPubKey = (ECPublicKeyParameters) + // ECUtil.generatePublicKeyParameter(mqvParameterSpec.getEphemeralPublicKey()); + // } + // mqvParameters = mqvParameterSpec; + // ukmParameters = mqvParameterSpec.getUserKeyingMaterial(); // } // // MQVPrivateParameters localParams = new MQVPrivateParameters(staticPrivKey, ephemPrivKey, ephemPubKey); @@ -328,7 +244,7 @@ public class KeyAgreementSpi ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)ECUtil.generatePrivateKeyParameter((PrivateKey)key); this.parameters = privKey.getParameters(); - + ukmParameters = (parameterSpec instanceof UserKeyingMaterialSpec) ? ((UserKeyingMaterialSpec)parameterSpec).getUserKeyingMaterial() : null; agreement.init(privKey); } } @@ -373,17 +289,223 @@ public class KeyAgreementSpi // { // public DHwithSHA1KDF() // { - // super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest())); + // super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest())); // } // } // - // public static class MQVwithSHA1KDF + // public static class DHwithSHA1KDFAndSharedInfo // extends KeyAgreementSpi // { - // public MQVwithSHA1KDF() + // public DHwithSHA1KDFAndSharedInfo() // { - // super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest())); + // super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest())); + // } + // } + // + // public static class CDHwithSHA1KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public CDHwithSHA1KDFAndSharedInfo() + // { + // super("ECCDHwithSHA1KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest())); + // } + // } + // + // public static class DHwithSHA224KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public DHwithSHA224KDFAndSharedInfo() + // { + // super("ECDHwithSHA224KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA224Digest())); + // } + // } + // + // public static class CDHwithSHA224KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public CDHwithSHA224KDFAndSharedInfo() + // { + // super("ECCDHwithSHA224KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA224Digest())); + // } + // } + // + // public static class DHwithSHA256KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public DHwithSHA256KDFAndSharedInfo() + // { + // super("ECDHwithSHA256KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA256Digest())); + // } + // } + // + // public static class CDHwithSHA256KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public CDHwithSHA256KDFAndSharedInfo() + // { + // super("ECCDHwithSHA256KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA256Digest())); + // } + // } + // + // public static class DHwithSHA384KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public DHwithSHA384KDFAndSharedInfo() + // { + // super("ECDHwithSHA384KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA384Digest())); + // } + // } + // + // public static class CDHwithSHA384KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public CDHwithSHA384KDFAndSharedInfo() + // { + // super("ECCDHwithSHA384KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA384Digest())); + // } + // } + // + // public static class DHwithSHA512KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public DHwithSHA512KDFAndSharedInfo() + // { + // super("ECDHwithSHA512KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA512Digest())); + // } + // } + // + // public static class CDHwithSHA512KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public CDHwithSHA512KDFAndSharedInfo() + // { + // super("ECCDHwithSHA512KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA512Digest())); + // } + // } + // + // public static class MQVwithSHA1KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public MQVwithSHA1KDFAndSharedInfo() + // { + // super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest())); + // } + // } + // + // public static class MQVwithSHA224KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public MQVwithSHA224KDFAndSharedInfo() + // { + // super("ECMQVwithSHA224KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA224Digest())); + // } + // } + // + // public static class MQVwithSHA256KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public MQVwithSHA256KDFAndSharedInfo() + // { + // super("ECMQVwithSHA256KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA256Digest())); + // } + // } + // + // public static class MQVwithSHA384KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public MQVwithSHA384KDFAndSharedInfo() + // { + // super("ECMQVwithSHA384KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA384Digest())); + // } + // } + // + // public static class MQVwithSHA512KDFAndSharedInfo + // extends KeyAgreementSpi + // { + // public MQVwithSHA512KDFAndSharedInfo() + // { + // super("ECMQVwithSHA512KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA512Digest())); + // } + // } + // + // public static class DHwithSHA1CKDF + // extends KeyAgreementSpi + // { + // public DHwithSHA1CKDF() + // { + // super("ECDHwithSHA1CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(new SHA1Digest())); + // } + // } + // + // public static class DHwithSHA256CKDF + // extends KeyAgreementSpi + // { + // public DHwithSHA256CKDF() + // { + // super("ECDHwithSHA256CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(new SHA256Digest())); + // } + // } + // + // public static class DHwithSHA384CKDF + // extends KeyAgreementSpi + // { + // public DHwithSHA384CKDF() + // { + // super("ECDHwithSHA384CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(new SHA384Digest())); + // } + // } + // + // public static class DHwithSHA512CKDF + // extends KeyAgreementSpi + // { + // public DHwithSHA512CKDF() + // { + // super("ECDHwithSHA512CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(new SHA512Digest())); + // } + // } + // + // public static class MQVwithSHA1CKDF + // extends KeyAgreementSpi + // { + // public MQVwithSHA1CKDF() + // { + // super("ECMQVwithSHA1CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA1Digest())); + // } + // } + // + // public static class MQVwithSHA224CKDF + // extends KeyAgreementSpi + // { + // public MQVwithSHA224CKDF() + // { + // super("ECMQVwithSHA224CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA224Digest())); + // } + // } + // + // public static class MQVwithSHA256CKDF + // extends KeyAgreementSpi + // { + // public MQVwithSHA256CKDF() + // { + // super("ECMQVwithSHA256CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA256Digest())); + // } + // } + // + // public static class MQVwithSHA384CKDF + // extends KeyAgreementSpi + // { + // public MQVwithSHA384CKDF() + // { + // super("ECMQVwithSHA384CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA384Digest())); + // } + // } + // + // public static class MQVwithSHA512CKDF + // extends KeyAgreementSpi + // { + // public MQVwithSHA512CKDF() + // { + // super("ECMQVwithSHA512CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA512Digest())); // } // } - // END android-removed } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java index d8585187..9a9c46be 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java @@ -212,7 +212,7 @@ public abstract class KeyPairGeneratorSpi { // NOTE: Don't bother with custom curves here as the curve will be converted to JCE type shortly - X9ECParameters p = ECNamedCurveTable.getByName(curveName); + X9ECParameters p = ECUtils.getDomainParametersFromName(curveName); if (p == null) { try diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java index baee6d52..de5a9aa5 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java @@ -90,7 +90,7 @@ public abstract class AlgorithmParametersSpi Class paramSpec) throws InvalidParameterSpecException { - if (paramSpec == OAEPParameterSpec.class && currentSpec != null) + if (paramSpec == OAEPParameterSpec.class || paramSpec == AlgorithmParameterSpec.class) { return currentSpec; } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateCrtKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateCrtKey.java index 9b70d74d..d81d1976 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateCrtKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateCrtKey.java @@ -12,6 +12,7 @@ import org.bouncycastle.asn1.pkcs.RSAPrivateKey; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.bouncycastle.util.Strings; /** * A provider representation for a RSA private key, with CRT factors included. @@ -224,7 +225,7 @@ public class BCRSAPrivateCrtKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("RSA Private CRT Key").append(nl); buf.append(" modulus: ").append(this.getModulus().toString(16)).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java index 6f5292ce..669cf2ba 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java @@ -15,6 +15,7 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.bouncycastle.util.Strings; public class BCRSAPublicKey implements RSAPublicKey @@ -134,7 +135,7 @@ public class BCRSAPublicKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("RSA Public Key").append(nl); buf.append(" modulus: ").append(this.getModulus().toString(16)).append(nl); @@ -153,11 +154,7 @@ public class BCRSAPublicKey { algorithmIdentifier = AlgorithmIdentifier.getInstance(in.readObject()); } - catch (OptionalDataException e) - { - algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER; - } - catch (EOFException e) + catch (Exception e) { algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER; } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java index aceb5ee0..81e50132 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java @@ -37,7 +37,6 @@ import org.bouncycastle.jcajce.provider.asymmetric.util.BaseCipherSpi; import org.bouncycastle.jcajce.provider.util.DigestFactory; import org.bouncycastle.jcajce.util.BCJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; -import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.Strings; public class CipherSpi diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java index 123ed415..9616a99b 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java @@ -25,6 +25,9 @@ import org.bouncycastle.asn1.x509.DigestInfo; import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; +// BEGIN android-added +import org.bouncycastle.crypto.digests.AndroidDigestFactory; +// END android-added // BEGIN android-removed // import org.bouncycastle.crypto.digests.MD2Digest; // import org.bouncycastle.crypto.digests.MD4Digest; @@ -38,10 +41,8 @@ import org.bouncycastle.crypto.Digest; // import org.bouncycastle.crypto.digests.SHA256Digest; // import org.bouncycastle.crypto.digests.SHA384Digest; // import org.bouncycastle.crypto.digests.SHA512Digest; +// import org.bouncycastle.crypto.digests.SHA512tDigest; // END android-removed -// BEGIN android-added -import org.bouncycastle.crypto.digests.AndroidDigestFactory; -// END android-added import org.bouncycastle.crypto.encodings.PKCS1Encoding; import org.bouncycastle.crypto.engines.RSABlindedEngine; import org.bouncycastle.util.Arrays; @@ -312,6 +313,24 @@ public class DigestSignatureSpi } // BEGIN android-removed + // static public class SHA512_224 + // extends DigestSignatureSpi + // { + // public SHA512_224() + // { + // super(NISTObjectIdentifiers.id_sha512_224, new SHA512tDigest(224), new PKCS1Encoding(new RSABlindedEngine())); + // } + // } + + // static public class SHA512_256 + // extends DigestSignatureSpi + // { + // public SHA512_256() + // { + // super(NISTObjectIdentifiers.id_sha512_256, new SHA512tDigest(256), new PKCS1Encoding(new RSABlindedEngine())); + // } + // } + // static public class MD2 // extends DigestSignatureSpi // { diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java index f779a66a..88f83a0c 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java @@ -43,7 +43,10 @@ public class KeyPairGeneratorSpi SecureRandom random) { param = new RSAKeyGenerationParameters(defaultPublicExponent, - random, strength, defaultTests); + // BEGIN android-changed + // Was: random, strength, defaultTests); + (random != null) ? random : new SecureRandom(), strength, defaultTests); + // END android-changed engine.init(param); } @@ -61,7 +64,11 @@ public class KeyPairGeneratorSpi param = new RSAKeyGenerationParameters( rsaParams.getPublicExponent(), - random, rsaParams.getKeysize(), defaultTests); + // BEGIN android-changed + // TODO(27063703): check whether this change is correct + // Was: random, rsaParams.getKeysize(), defaultTests); + (random != null) ? random : new SecureRandom(), rsaParams.getKeysize(), defaultTests); + // END android-changed engine.init(param); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java new file mode 100644 index 00000000..16e73481 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java @@ -0,0 +1,323 @@ +package org.bouncycastle.jcajce.provider.asymmetric.util; + +import java.math.BigInteger; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import javax.crypto.KeyAgreementSpi; +import javax.crypto.SecretKey; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +// BEGIN android-removed +// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +// import org.bouncycastle.asn1.gnu.GNUObjectIdentifiers; +// END android-removed +import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers; +import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.crypto.DerivationFunction; +// BEGIN android-removed +// import org.bouncycastle.crypto.agreement.kdf.DHKDFParameters; +// import org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator; +// END android-removed +import org.bouncycastle.crypto.params.DESParameters; +import org.bouncycastle.crypto.params.KDFParameters; +import org.bouncycastle.util.Integers; +import org.bouncycastle.util.Strings; + +public abstract class BaseAgreementSpi + extends KeyAgreementSpi +{ + private static final Map<String, ASN1ObjectIdentifier> defaultOids = new HashMap<String, ASN1ObjectIdentifier>(); + private static final Map<String, Integer> keySizes = new HashMap<String, Integer>(); + private static final Map<String, String> nameTable = new HashMap<String, String>(); + + private static final Hashtable oids = new Hashtable(); + private static final Hashtable des = new Hashtable(); + + static + { + Integer i64 = Integers.valueOf(64); + Integer i128 = Integers.valueOf(128); + Integer i192 = Integers.valueOf(192); + Integer i256 = Integers.valueOf(256); + + keySizes.put("DES", i64); + keySizes.put("DESEDE", i192); + keySizes.put("BLOWFISH", i128); + keySizes.put("AES", i256); + + keySizes.put(NISTObjectIdentifiers.id_aes128_ECB.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_ECB.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_ECB.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_CBC.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_CBC.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_CBC.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_CFB.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_CFB.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_CFB.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_OFB.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_OFB.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_OFB.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_wrap.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_wrap.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_wrap.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_CCM.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_CCM.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_CCM.getId(), i256); + keySizes.put(NISTObjectIdentifiers.id_aes128_GCM.getId(), i128); + keySizes.put(NISTObjectIdentifiers.id_aes192_GCM.getId(), i192); + keySizes.put(NISTObjectIdentifiers.id_aes256_GCM.getId(), i256); + keySizes.put(NTTObjectIdentifiers.id_camellia128_wrap.getId(), i128); + keySizes.put(NTTObjectIdentifiers.id_camellia192_wrap.getId(), i192); + keySizes.put(NTTObjectIdentifiers.id_camellia256_wrap.getId(), i256); + keySizes.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap.getId(), i128); + + keySizes.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), i192); + keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), i192); + keySizes.put(OIWObjectIdentifiers.desCBC.getId(), i64); + + keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA1.getId(), Integers.valueOf(160)); + keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA256.getId(), i256); + keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA384.getId(), Integers.valueOf(384)); + keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA512.getId(), Integers.valueOf(512)); + + defaultOids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC); + defaultOids.put("AES", NISTObjectIdentifiers.id_aes256_CBC); + defaultOids.put("CAMELLIA", NTTObjectIdentifiers.id_camellia256_cbc); + defaultOids.put("SEED", KISAObjectIdentifiers.id_seedCBC); + defaultOids.put("DES", OIWObjectIdentifiers.desCBC); + + nameTable.put(MiscObjectIdentifiers.cast5CBC.getId(), "CAST5"); + nameTable.put(MiscObjectIdentifiers.as_sys_sec_alg_ideaCBC.getId(), "IDEA"); + nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_ECB.getId(), "Blowfish"); + nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CBC.getId(), "Blowfish"); + nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CFB.getId(), "Blowfish"); + nameTable.put(MiscObjectIdentifiers.cryptlib_algorithm_blowfish_OFB.getId(), "Blowfish"); + nameTable.put(OIWObjectIdentifiers.desECB.getId(), "DES"); + nameTable.put(OIWObjectIdentifiers.desCBC.getId(), "DES"); + nameTable.put(OIWObjectIdentifiers.desCFB.getId(), "DES"); + nameTable.put(OIWObjectIdentifiers.desOFB.getId(), "DES"); + nameTable.put(OIWObjectIdentifiers.desEDE.getId(), "DESede"); + nameTable.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DESede"); + nameTable.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DESede"); + nameTable.put(PKCSObjectIdentifiers.id_alg_CMSRC2wrap.getId(), "RC2"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA1.getId(), "HmacSHA1"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA224.getId(), "HmacSHA224"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA256.getId(), "HmacSHA256"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA384.getId(), "HmacSHA384"); + nameTable.put(PKCSObjectIdentifiers.id_hmacWithSHA512.getId(), "HmacSHA512"); + nameTable.put(NTTObjectIdentifiers.id_camellia128_cbc.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia192_cbc.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia256_cbc.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia128_wrap.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia192_wrap.getId(), "Camellia"); + nameTable.put(NTTObjectIdentifiers.id_camellia256_wrap.getId(), "Camellia"); + nameTable.put(KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap.getId(), "SEED"); + nameTable.put(KISAObjectIdentifiers.id_seedCBC.getId(), "SEED"); + nameTable.put(KISAObjectIdentifiers.id_seedMAC.getId(), "SEED"); + // BEGIN android-removed + // nameTable.put(CryptoProObjectIdentifiers.gostR28147_gcfb.getId(), "GOST28147"); + // END android-removed + + nameTable.put(NISTObjectIdentifiers.id_aes128_wrap.getId(), "AES"); + nameTable.put(NISTObjectIdentifiers.id_aes128_CCM.getId(), "AES"); + nameTable.put(NISTObjectIdentifiers.id_aes128_CCM.getId(), "AES"); + + oids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC); + oids.put("AES", NISTObjectIdentifiers.id_aes256_CBC); + oids.put("DES", OIWObjectIdentifiers.desCBC); + + des.put("DES", "DES"); + des.put("DESEDE", "DES"); + des.put(OIWObjectIdentifiers.desCBC.getId(), "DES"); + des.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DES"); + des.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DES"); + } + + private final String kaAlgorithm; + private final DerivationFunction kdf; + + protected BigInteger result; + protected byte[] ukmParameters; + + public BaseAgreementSpi(String kaAlgorithm, DerivationFunction kdf) + { + this.kaAlgorithm = kaAlgorithm; + this.kdf = kdf; + } + + protected static String getAlgorithm(String algDetails) + { + if (algDetails.indexOf('[') > 0) + { + return algDetails.substring(0, algDetails.indexOf('[')); + } + + if (algDetails.startsWith(NISTObjectIdentifiers.aes.getId())) + { + return "AES"; + } + // BEGIN android-removed + // if (algDetails.startsWith(GNUObjectIdentifiers.Serpent.getId())) + // { + // return "Serpent"; + // } + // END android-removed + + String name = (String)nameTable.get(Strings.toUpperCase(algDetails)); + + if (name != null) + { + return name; + } + + return algDetails; + } + + protected static int getKeySize(String algDetails) + { + if (algDetails.indexOf('[') > 0) + { + return (Integer.parseInt(algDetails.substring(algDetails.indexOf('[') + 1, algDetails.indexOf(']'))) + 7) / 8; + } + + String algKey = Strings.toUpperCase(algDetails); + if (!keySizes.containsKey(algKey)) + { + return -1; + } + + return ((Integer)keySizes.get(algKey)).intValue(); + } + + protected static byte[] trimZeroes(byte[] secret) + { + if (secret[0] != 0) + { + return secret; + } + else + { + int ind = 0; + while (ind < secret.length && secret[ind] == 0) + { + ind++; + } + + byte[] rv = new byte[secret.length - ind]; + + System.arraycopy(secret, ind, rv, 0, rv.length); + + return rv; + } + } + + protected byte[] engineGenerateSecret() + throws IllegalStateException + { + if (kdf != null) + { + throw new UnsupportedOperationException( + "KDF can only be used when algorithm is known"); + } + + return bigIntToBytes(result); + } + + protected int engineGenerateSecret( + byte[] sharedSecret, + int offset) + throws IllegalStateException, ShortBufferException + { + byte[] secret = engineGenerateSecret(); + + if (sharedSecret.length - offset < secret.length) + { + throw new ShortBufferException(kaAlgorithm + " key agreement: need " + secret.length + " bytes"); + } + + System.arraycopy(secret, 0, sharedSecret, offset, secret.length); + + return secret.length; + } + + protected SecretKey engineGenerateSecret( + String algorithm) + throws NoSuchAlgorithmException + { + byte[] secret = bigIntToBytes(result); + String algKey = Strings.toUpperCase(algorithm); + String oidAlgorithm = algorithm; + + if (oids.containsKey(algKey)) + { + oidAlgorithm = ((ASN1ObjectIdentifier)oids.get(algKey)).getId(); + } + + int keySize = getKeySize(oidAlgorithm); + if (kdf != null) + { + if (keySize < 0) + { + throw new NoSuchAlgorithmException("unknown algorithm encountered: " + oidAlgorithm); + } + byte[] keyBytes = new byte[keySize / 8]; + + // BEGIN android-removed + // if (kdf instanceof DHKEKGenerator) + // { + // ASN1ObjectIdentifier oid; + // try + // { + // oid = new ASN1ObjectIdentifier(oidAlgorithm); + // } + // catch (IllegalArgumentException e) + // { + // throw new NoSuchAlgorithmException("no OID for algorithm: " + oidAlgorithm); + // } + // DHKDFParameters params = new DHKDFParameters(oid, keySize, secret, ukmParameters); + + // kdf.init(params); + // } + // else + // END android-removed + { + KDFParameters params = new KDFParameters(secret, ukmParameters); + + kdf.init(params); + } + + kdf.generateBytes(keyBytes, 0, keyBytes.length); + + secret = keyBytes; + } + else + { + if (keySize > 0) + { + byte[] keyBytes = new byte[keySize / 8]; + + System.arraycopy(secret, 0, keyBytes, 0, keyBytes.length); + + secret = keyBytes; + } + } + + if (des.containsKey(oidAlgorithm)) + { + DESParameters.setOddParity(secret); + } + + return new SecretKeySpec(secret, getAlgorithm(algorithm)); + } + + protected abstract byte[] bigIntToBytes(BigInteger result); +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java index d5b62fe8..0f25888a 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java @@ -11,13 +11,20 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.Map; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x9.ECNamedCurveTable; +import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.ec.CustomNamedCurves; +import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECAlgorithms; import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.field.FiniteField; +import org.bouncycastle.math.field.Polynomial; +import org.bouncycastle.math.field.PolynomialExtensionField; +import org.bouncycastle.util.Arrays; public class EC5Util { @@ -38,34 +45,111 @@ public class EC5Util } } - public static EllipticCurve convertCurve( - ECCurve curve, - byte[] seed) + public static ECCurve getCurve( + ProviderConfiguration configuration, + X962Parameters params) { - // TODO: the Sun EC implementation doesn't currently handle the seed properly - // so at the moment it's set to null. Should probably look at making this configurable - if (ECAlgorithms.isFpCurve(curve)) + ECCurve curve; + + if (params.isNamedCurve()) { - return new EllipticCurve(new ECFieldFp(curve.getField().getCharacteristic()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null); + ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters()); + X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); + + curve = ecP.getCurve(); + } + else if (params.isImplicitlyCA()) + { + curve = configuration.getEcImplicitlyCa().getCurve(); } else { - ECCurve.F2m curveF2m = (ECCurve.F2m)curve; - int ks[]; - - if (curveF2m.isTrinomial()) + X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); + + curve = ecP.getCurve(); + } + + return curve; + } + + public static ECParameterSpec convertToSpec( + X962Parameters params, ECCurve curve) + { + ECParameterSpec ecSpec; + EllipticCurve ellipticCurve; + + if (params.isNamedCurve()) + { + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); + X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); + + ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); + + ecSpec = new ECNamedCurveSpec( + ECUtil.getCurveName(oid), + ellipticCurve, + new ECPoint( + ecP.getG().getAffineXCoord().toBigInteger(), + ecP.getG().getAffineYCoord().toBigInteger()), + ecP.getN(), + ecP.getH()); + } + else if (params.isImplicitlyCA()) + { + ecSpec = null; + } + else + { + X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); + + ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); + + if (ecP.getH() != null) { - ks = new int[] { curveF2m.getK1() }; - - return new EllipticCurve(new ECFieldF2m(curveF2m.getM(), ks), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null); + ecSpec = new ECParameterSpec( + ellipticCurve, + new ECPoint( + ecP.getG().getAffineXCoord().toBigInteger(), + ecP.getG().getAffineYCoord().toBigInteger()), + ecP.getN(), + ecP.getH().intValue()); } else { - ks = new int[] { curveF2m.getK3(), curveF2m.getK2(), curveF2m.getK1() }; - - return new EllipticCurve(new ECFieldF2m(curveF2m.getM(), ks), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null); - } + ecSpec = new ECParameterSpec( + ellipticCurve, + new ECPoint( + ecP.getG().getAffineXCoord().toBigInteger(), + ecP.getG().getAffineYCoord().toBigInteger()), + ecP.getN(), 1); // TODO: not strictly correct... need to fix the test data... + } } + + return ecSpec; + } + + public static ECParameterSpec convertToSpec( + X9ECParameters domainParameters) + { + return new ECParameterSpec( + convertCurve(domainParameters.getCurve(), null), // JDK 1.5 has trouble with this if it's not null... + new ECPoint( + domainParameters.getG().getAffineXCoord().toBigInteger(), + domainParameters.getG().getAffineYCoord().toBigInteger()), + domainParameters.getN(), + domainParameters.getH().intValue()); + } + + public static EllipticCurve convertCurve( + ECCurve curve, + byte[] seed) + { + ECField field = convertField(curve.getField()); + BigInteger a = curve.getA().toBigInteger(), b = curve.getB().toBigInteger(); + + // TODO: the Sun EC implementation doesn't currently handle the seed properly + // so at the moment it's set to null. Should probably look at making this configurable + return new EllipticCurve(field, a, b, null); } public static ECCurve convertCurve( @@ -95,6 +179,21 @@ public class EC5Util } } + public static ECField convertField(FiniteField field) + { + if (ECAlgorithms.isFpField(field)) + { + return new ECFieldFp(field.getCharacteristic()); + } + else //if (ECAlgorithms.isF2mField(curveField)) + { + Polynomial poly = ((PolynomialExtensionField)field).getMinimalPolynomial(); + int[] exponents = poly.getExponentsPresent(); + int[] ks = Arrays.reverse(Arrays.copyOfRange(exponents, 1, exponents.length - 1)); + return new ECFieldF2m(poly.getDegree(), ks); + } + } + public static ECParameterSpec convertSpec( EllipticCurve ellipticCurve, org.bouncycastle.jce.spec.ECParameterSpec spec) @@ -149,6 +248,6 @@ public class EC5Util ECPoint point, boolean withCompression) { - return curve.createPoint(point.getAffineX(), point.getAffineY(), withCompression); + return curve.createPoint(point.getAffineX(), point.getAffineY()); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java index b8ef3985..561259ad 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java @@ -4,9 +4,11 @@ import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; +import java.util.Enumeration; import org.bouncycastle.asn1.ASN1ObjectIdentifier; // BEGIN android-removed +// import org.bouncycastle.asn1.anssi.ANSSINamedCurves; // import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; // END android-removed import org.bouncycastle.asn1.nist.NISTNamedCurves; @@ -16,8 +18,8 @@ import org.bouncycastle.asn1.sec.SECNamedCurves; // import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; // END android-removed import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X962NamedCurves; -import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; @@ -240,10 +242,40 @@ public class ECUtil } public static ASN1ObjectIdentifier getNamedCurveOid( - String name) + String curveName) + { + String name; + + if (curveName.indexOf(' ') > 0) + { + name = curveName.substring(curveName.indexOf(' ') + 1); + } + else + { + name = curveName; + } + + try + { + if (name.charAt(0) >= '0' && name.charAt(0) <= '2') + { + return new ASN1ObjectIdentifier(name); + } + else + { + return lookupOidByName(name); + } + } + catch (IllegalArgumentException ex) + { + return lookupOidByName(name); + } + } + + private static ASN1ObjectIdentifier lookupOidByName(String name) { ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name); - + if (oid == null) { oid = SECNamedCurves.getOID(name); @@ -260,12 +292,37 @@ public class ECUtil // { // oid = ECGOST3410NamedCurves.getOID(name); // } + // if (oid == null) + // { + // oid = ANSSINamedCurves.getOID(name); + // } // END android-removed } return oid; } - + + public static ASN1ObjectIdentifier getNamedCurveOid( + ECParameterSpec ecParameterSpec) + { + for (Enumeration names = ECNamedCurveTable.getNames(); names.hasMoreElements();) + { + String name = (String)names.nextElement(); + + X9ECParameters params = ECNamedCurveTable.getByName(name); + + if (params.getN().equals(ecParameterSpec.getN()) + && params.getH().equals(ecParameterSpec.getH()) + && params.getCurve().equals(ecParameterSpec.getCurve()) + && params.getG().equals(ecParameterSpec.getG())) + { + return org.bouncycastle.asn1.x9.ECNamedCurveTable.getOID(name); + } + } + + return null; + } + public static X9ECParameters getNamedCurveByOid( ASN1ObjectIdentifier oid) { @@ -293,6 +350,33 @@ public class ECUtil return params; } + public static X9ECParameters getNamedCurveByName( + String curveName) + { + X9ECParameters params = CustomNamedCurves.getByName(curveName); + + if (params == null) + { + params = X962NamedCurves.getByName(curveName); + if (params == null) + { + params = SECNamedCurves.getByName(curveName); + } + if (params == null) + { + params = NISTNamedCurves.getByName(curveName); + } + // BEGIN android-removed + // if (params == null) + // { + // params = TeleTrusTNamedCurves.getByName(curveName); + // } + // END android-removed + } + + return params; + } + public static String getCurveName( ASN1ObjectIdentifier oid) { diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java index 03a1fe83..2203ce79 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java @@ -24,6 +24,8 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.SignedData; import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.CertificateList; +import org.bouncycastle.jcajce.util.BCJcaJceHelper; +import org.bouncycastle.jcajce.util.JcaJceHelper; /** * class for dealing with X509 certificates. @@ -35,6 +37,8 @@ import org.bouncycastle.asn1.x509.CertificateList; public class CertificateFactory extends CertificateFactorySpi { + private final JcaJceHelper bcHelper = new BCJcaJceHelper(); + private static final PEMUtil PEM_CERT_PARSER = new PEMUtil("CERTIFICATE"); private static final PEMUtil PEM_CRL_PARSER = new PEMUtil("CRL"); @@ -64,7 +68,7 @@ public class CertificateFactory } } - return new X509CertificateObject( + return new X509CertificateObject(bcHelper, Certificate.getInstance(seq)); } @@ -79,7 +83,7 @@ public class CertificateFactory if (obj instanceof ASN1Sequence) { - return new X509CertificateObject( + return new X509CertificateObject(bcHelper, Certificate.getInstance(obj)); } } @@ -96,7 +100,7 @@ public class CertificateFactory if (seq != null) { - return new X509CertificateObject( + return new X509CertificateObject(bcHelper, Certificate.getInstance(seq)); } @@ -106,7 +110,7 @@ public class CertificateFactory protected CRL createCRL(CertificateList c) throws CRLException { - return new X509CRLObject(c); + return new X509CRLObject(bcHelper, c); } private CRL readPEMCRL( diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java index 0b53bd37..5a94c638 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java @@ -23,6 +23,7 @@ import org.bouncycastle.asn1.x509.Extensions; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.TBSCertList; +import org.bouncycastle.util.Strings; /** * The following extensions are listed in RFC 2459 as relevant to CRL Entries @@ -188,7 +189,7 @@ class X509CRLEntryObject extends X509CRLEntry } catch (Exception e) { - throw new RuntimeException("error encoding " + e.toString()); + throw new IllegalStateException("Exception encoding: " + e.toString()); } } @@ -258,7 +259,7 @@ class X509CRLEntryObject extends X509CRLEntry public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append(" userCertificate: ").append(this.getSerialNumber()).append(nl); buf.append(" revocationDate: ").append(this.getRevocationDate()).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java index cd877d04..dc8930b3 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java @@ -6,6 +6,7 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; +import java.security.Provider; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; @@ -40,8 +41,9 @@ import org.bouncycastle.asn1.x509.Extensions; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.IssuingDistributionPoint; import org.bouncycastle.asn1.x509.TBSCertList; +import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.jce.X509Principal; -import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; /** @@ -56,6 +58,7 @@ import org.bouncycastle.util.encoders.Hex; class X509CRLObject extends X509CRL { + private JcaJceHelper bcHelper; private CertificateList c; private String sigAlgName; private byte[] sigAlgParams; @@ -80,9 +83,11 @@ class X509CRLObject } protected X509CRLObject( + JcaJceHelper bcHelper, CertificateList c) throws CRLException { + this.bcHelper = bcHelper; this.c = c; try @@ -202,21 +207,45 @@ class X509CRLObject } public void verify(PublicKey key) - throws CRLException, NoSuchAlgorithmException, - InvalidKeyException, NoSuchProviderException, SignatureException + throws CRLException, NoSuchAlgorithmException, + InvalidKeyException, NoSuchProviderException, SignatureException { - verify(key, BouncyCastleProvider.PROVIDER_NAME); + Signature sig; + + try + { + sig = bcHelper.createSignature(getSigAlgName()); + } + catch (Exception e) + { + sig = Signature.getInstance(getSigAlgName()); + } + + doVerify(key, sig); } public void verify(PublicKey key, String sigProvider) throws CRLException, NoSuchAlgorithmException, - InvalidKeyException, NoSuchProviderException, SignatureException + InvalidKeyException, NoSuchProviderException, SignatureException { - if (!c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature())) + Signature sig; + + if (sigProvider != null) { - throw new CRLException("Signature algorithm on CertificateList does not match TBSCertList."); + sig = Signature.getInstance(getSigAlgName(), sigProvider); + } + else + { + sig = Signature.getInstance(getSigAlgName()); } + doVerify(key, sig); + } + + public void verify(PublicKey key, Provider sigProvider) + throws CRLException, NoSuchAlgorithmException, + InvalidKeyException, SignatureException + { Signature sig; if (sigProvider != null) @@ -228,6 +257,18 @@ class X509CRLObject sig = Signature.getInstance(getSigAlgName()); } + doVerify(key, sig); + } + + private void doVerify(PublicKey key, Signature sig) + throws CRLException, NoSuchAlgorithmException, + InvalidKeyException, SignatureException + { + if (!c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature())) + { + throw new CRLException("Signature algorithm on CertificateList does not match TBSCertList."); + } + sig.initVerify(key); sig.update(this.getTBSCertList()); @@ -354,7 +395,7 @@ class X509CRLObject public byte[] getSignature() { - return c.getSignature().getBytes(); + return c.getSignature().getOctets(); } public String getSigAlgName() @@ -389,7 +430,7 @@ class X509CRLObject public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append(" Version: ").append(this.getVersion()).append( nl); @@ -520,7 +561,7 @@ class X509CRLObject { if (!cert.getType().equals("X.509")) { - throw new RuntimeException("X.509 CRL used with non X.509 Cert"); + throw new IllegalArgumentException("X.509 CRL used with non X.509 Cert"); } Enumeration certs = c.getRevokedCertificateEnumeration(); @@ -561,7 +602,7 @@ class X509CRLObject } catch (CertificateEncodingException e) { - throw new RuntimeException("Cannot process certificate"); + throw new IllegalArgumentException("Cannot process certificate: " + e.getMessage()); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java index 3157ea67..51213d42 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java @@ -9,10 +9,10 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; +import java.security.Provider; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; -import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; @@ -30,6 +30,7 @@ import java.util.Set; import javax.security.auth.x500.X500Principal; +import org.bouncycastle.asn1.ASN1BitString; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1InputStream; @@ -59,17 +60,19 @@ import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.X509Name; // END android-added import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl; +import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.jce.X509Principal; import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Integers; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; class X509CertificateObject extends X509Certificate implements PKCS12BagAttributeCarrier { + private JcaJceHelper bcHelper; private org.bouncycastle.asn1.x509.Certificate c; private BasicConstraints basicConstraints; private boolean[] keyUsage; @@ -79,9 +82,11 @@ class X509CertificateObject private PKCS12BagAttributeCarrier attrCarrier = new PKCS12BagAttributeCarrierImpl(); public X509CertificateObject( + JcaJceHelper bcHelper, org.bouncycastle.asn1.x509.Certificate c) throws CertificateParsingException { + this.bcHelper = bcHelper; this.c = c; try @@ -103,7 +108,7 @@ class X509CertificateObject byte[] bytes = this.getExtensionBytes("2.5.29.15"); if (bytes != null) { - DERBitString bits = DERBitString.getInstance(ASN1Primitive.fromByteArray(bytes)); + ASN1BitString bits = DERBitString.getInstance(ASN1Primitive.fromByteArray(bytes)); bytes = bits.getBytes(); int length = (bytes.length * 8) - bits.getPadBits(); @@ -233,7 +238,7 @@ class X509CertificateObject public byte[] getSignature() { - return c.getSignature().getBytes(); + return c.getSignature().getOctets(); } /** @@ -566,38 +571,41 @@ class X509CertificateObject return true; } - if (!(o instanceof Certificate)) + if (o instanceof X509CertificateObject) { - return false; - } - - Certificate other = (Certificate)o; + X509CertificateObject other = (X509CertificateObject)o; - try - { - byte[] b1 = this.getEncoded(); - byte[] b2 = other.getEncoded(); + if (this.hashValueSet && other.hashValueSet) + { + if (this.hashValue != other.hashValue) + { + return false; + } + } - return Arrays.areEqual(b1, b2); - } - catch (CertificateEncodingException e) - { - return false; + return this.c.equals(other.c); } + + return super.equals(o); } - + public synchronized int hashCode() { if (!hashValueSet) { - hashValue = calculateHashCode(); + hashValue = super.hashCode(); hashValueSet = true; } return hashValue; } - - private int calculateHashCode() + + /** + * Returns the original hash code for Certificates pre-JDK 1.8. + * + * @return the pre-JDK 1.8 hashcode calculation. + */ + public int originalHashCode() { try { @@ -636,7 +644,7 @@ class X509CertificateObject public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append(" [0] Version: ").append(this.getVersion()).append(nl); buf.append(" SerialNumber: ").append(this.getSerialNumber()).append(nl); @@ -739,7 +747,7 @@ class X509CertificateObject try { - signature = Signature.getInstance(sigName, BouncyCastleProvider.PROVIDER_NAME); + signature = bcHelper.createSignature(sigName); } catch (Exception e) { @@ -758,7 +766,7 @@ class X509CertificateObject String sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm()); Signature signature; - if (sigProvider != null) + if (sigProvider != null) { signature = Signature.getInstance(sigName, sigProvider); } @@ -770,6 +778,27 @@ class X509CertificateObject checkSignature(key, signature); } + public final void verify( + PublicKey key, + Provider sigProvider) + throws CertificateException, NoSuchAlgorithmException, + InvalidKeyException, SignatureException + { + String sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm()); + Signature signature; + + if (sigProvider != null) + { + signature = Signature.getInstance(sigName, sigProvider); + } + else + { + signature = Signature.getInstance(sigName); + } + + checkSignature(key, signature); + } + private void checkSignature( PublicKey key, Signature signature) diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java index 123ff7de..5fb3ffc9 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java @@ -33,6 +33,8 @@ public interface ConfigurableProvider void addAlgorithm(String key, String value); + void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className); + boolean hasAlgorithm(String type, String name); void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java index c7502c77..1fdadc24 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java @@ -195,6 +195,8 @@ public class SHA1 provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1", PREFIX + "$PBKDF2WithHmacSHA1UTF8"); provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WithHmacSHA1AndUTF8", "PBKDF2WithHmacSHA1"); provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1And8BIT", PREFIX + "$PBKDF2WithHmacSHA18BIT"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2withASCII", "PBKDF2WithHmacSHA1And8BIT"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2with8BIT", "PBKDF2WithHmacSHA1And8BIT"); } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java index 53548f05..ed0fadce 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java @@ -32,8 +32,10 @@ import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; +import java.util.HashSet; import java.util.Hashtable; import java.util.Map; +import java.util.Set; import java.util.Vector; import javax.crypto.Cipher; @@ -89,8 +91,8 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.SHA1Digest; +import org.bouncycastle.jcajce.PKCS12Key; import org.bouncycastle.jcajce.PKCS12StoreParameter; -import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey; // BEGIN android-removed // import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec; // END android-removed @@ -216,8 +218,7 @@ public class PKCS12KeyStoreSpi { try { - SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( - (ASN1Sequence)ASN1Primitive.fromByteArray(pubKey.getEncoded())); + SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()); return new SubjectKeyIdentifier(getDigest(info)); } @@ -275,7 +276,8 @@ public class PKCS12KeyStoreSpi /** * this is not quite complete - we should follow up on the chain, a bit - * tricky if a certificate appears in more than one chain... + * tricky if a certificate appears in more than one chain... the store method + * now prunes out unused certificates from the chain map if they are present. */ public void engineDeleteEntry( String alias) @@ -450,14 +452,21 @@ public class PKCS12KeyStoreSpi } } - cs.addElement(c); - if (nextC != c) // self signed - end of the chain + if (cs.contains(c)) { - c = nextC; + c = null; // we've got a certificate chain loop time to stop } else { - c = null; + cs.addElement(c); + if (nextC != c) // self signed - end of the chain + { + c = nextC; + } + else + { + c = null; + } } } @@ -605,23 +614,15 @@ public class PKCS12KeyStoreSpi if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds)) { PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters()); - - PBEKeySpec pbeSpec = new PBEKeySpec(password); - PrivateKey out; - - SecretKeyFactory keyFact = helper.createSecretKeyFactory( - algorithm.getId()); PBEParameterSpec defParams = new PBEParameterSpec( pbeParams.getIV(), pbeParams.getIterations().intValue()); - SecretKey k = keyFact.generateSecret(pbeSpec); - - ((BCPBEKey)k).setTryWrongPKCS12Zero(wrongPKCS12Zero); - Cipher cipher = helper.createCipher(algorithm.getId()); - cipher.init(Cipher.UNWRAP_MODE, k, defParams); + PKCS12Key key = new PKCS12Key(password, wrongPKCS12Zero); + + cipher.init(Cipher.UNWRAP_MODE, key, defParams); // we pass "" as the key algorithm type as it is unknown at this point return (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY); @@ -692,13 +693,10 @@ public class PKCS12KeyStoreSpi try { - SecretKeyFactory keyFact = helper.createSecretKeyFactory(algorithm.getId()); PBEParameterSpec defParams = new PBEParameterSpec( pbeParams.getIV(), pbeParams.getIterations().intValue()); - BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec); - - key.setTryWrongPKCS12Zero(wrongPKCS12Zero); + PKCS12Key key = new PKCS12Key(password, wrongPKCS12Zero); Cipher cipher = helper.createCipher(algorithm.getId()); @@ -1281,7 +1279,6 @@ public class PKCS12KeyStoreSpi // ASN1EncodableVector keyS = new ASN1EncodableVector(); - Enumeration ks = keys.keys(); while (ks.hasMoreElements()) @@ -1531,6 +1528,8 @@ public class PKCS12KeyStoreSpi } } + Set usedSet = getUsedCertificateSet(); + cs = chainCerts.keys(); while (cs.hasMoreElements()) { @@ -1539,6 +1538,11 @@ public class PKCS12KeyStoreSpi CertId certId = (CertId)cs.nextElement(); Certificate cert = (Certificate)chainCerts.get(certId); + if (!usedSet.contains(cert)) + { + continue; + } + if (doneCerts.get(cert) != null) { continue; @@ -1657,6 +1661,34 @@ public class PKCS12KeyStoreSpi asn1Out.writeObject(pfx); } + private Set getUsedCertificateSet() + { + Set usedSet = new HashSet(); + + for (Enumeration en = keys.keys(); en.hasMoreElements();) + { + String alias = (String)en.nextElement(); + + Certificate[] certs = engineGetCertificateChain(alias); + + for (int i = 0; i != certs.length; i++) + { + usedSet.add(certs[i]); + } + } + + for (Enumeration en = certs.keys(); en.hasMoreElements();) + { + String alias = (String)en.nextElement(); + + Certificate cert = engineGetCertificate(alias); + + usedSet.add(cert); + } + + return usedSet; + } + private byte[] calculatePbeMac( ASN1ObjectIdentifier oid, byte[] salt, @@ -1666,15 +1698,12 @@ public class PKCS12KeyStoreSpi byte[] data) throws Exception { - SecretKeyFactory keyFact = helper.createSecretKeyFactory(oid.getId()); PBEParameterSpec defParams = new PBEParameterSpec(salt, itCount); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec); - key.setTryWrongPKCS12Zero(wrongPkcs12Zero); Mac mac = helper.createMac(oid.getId()); - mac.init(key, defParams); + mac.init(new PKCS12Key(password, wrongPkcs12Zero), defParams); mac.update(data); + return mac.doFinal(); } @@ -1776,7 +1805,7 @@ public class PKCS12KeyStoreSpi keySizes.put(new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"), Integers.valueOf(128)); - keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), Integers.valueOf(192)); + keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC, Integers.valueOf(192)); keySizes.put(NISTObjectIdentifiers.id_aes128_CBC, Integers.valueOf(128)); keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192)); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java index d476df8f..0328ac8b 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java @@ -1,8 +1,6 @@ package org.bouncycastle.jcajce.provider.symmetric; import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; // BEGIN android-added import java.security.NoSuchAlgorithmException; // END android-added @@ -14,9 +12,7 @@ import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; -// BEGIN android-removed -// import javax.crypto.spec.IvParameterSpec; -// END android-removed +import javax.crypto.spec.IvParameterSpec; // BEGIN android-added import javax.crypto.NoSuchPaddingException; @@ -60,7 +56,6 @@ import org.bouncycastle.jcajce.provider.symmetric.util.BaseWrapCipher; import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider; import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters; import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory; -import org.bouncycastle.util.Integers; public final class AES { @@ -136,7 +131,7 @@ public final class AES // { // public CCM() // { - // super(new CCMBlockCipher(new AESFastEngine())); + // super(new CCMBlockCipher(new AESFastEngine()), false, 16); // } // } // @@ -217,7 +212,67 @@ public final class AES super(new CBCBlockCipher(new AESFastEngine())); } } - + + /** + * PBEWithSHA1AES-CBC + */ + static public class PBEWithSHA1AESCBC128 + extends BaseBlockCipher + { + public PBEWithSHA1AESCBC128() + { + super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA1, 128, 16); + } + } + + static public class PBEWithSHA1AESCBC192 + extends BaseBlockCipher + { + public PBEWithSHA1AESCBC192() + { + super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA1, 192, 16); + } + } + + static public class PBEWithSHA1AESCBC256 + extends BaseBlockCipher + { + public PBEWithSHA1AESCBC256() + { + super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA1, 256, 16); + } + } + + /** + * PBEWithSHA256AES-CBC + */ + static public class PBEWithSHA256AESCBC128 + extends BaseBlockCipher + { + public PBEWithSHA256AESCBC128() + { + super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA256, 128, 16); + } + } + + static public class PBEWithSHA256AESCBC192 + extends BaseBlockCipher + { + public PBEWithSHA256AESCBC192() + { + super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA256, 192, 16); + } + } + + static public class PBEWithSHA256AESCBC256 + extends BaseBlockCipher + { + public PBEWithSHA256AESCBC256() + { + super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA256, 256, 16); + } + } + public static class KeyGen extends BaseKeyGenerator { @@ -504,19 +559,13 @@ public final class AES protected void engineInit(AlgorithmParameterSpec paramSpec) throws InvalidParameterSpecException { - if (gcmSpecClass != null) + if (GcmSpecUtil.isGcmSpec(paramSpec)) { - try - { - Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]); - Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]); - - gcmParams = new GCMParameters((byte[])iv.invoke(paramSpec, new Object[0]), ((Integer)tLen.invoke(paramSpec, new Object[0])).intValue() / 8); - } - catch (Exception e) - { - throw new InvalidParameterSpecException("Cannot process GCMParameterSpec."); - } + gcmParams = GcmSpecUtil.extractGcmParameters(paramSpec); + } + else + { + throw new InvalidParameterSpecException("AlgorithmParameterSpec class not recognized: " + paramSpec.getClass().getName()); } } @@ -562,25 +611,20 @@ public final class AES protected AlgorithmParameterSpec localEngineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { - if (gcmSpecClass != null) + if (paramSpec == AlgorithmParameterSpec.class || GcmSpecUtil.isGcmSpec(paramSpec)) { - try - { - Constructor constructor = gcmSpecClass.getConstructor(new Class[] { Integer.TYPE, byte[].class }); - - return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(gcmParams.getIcvLen() * 8), gcmParams.getNonce() }); - } - catch (NoSuchMethodException e) + if (GcmSpecUtil.gcmSpecExists()) { - throw new InvalidParameterSpecException("no constructor found!"); // should never happen - } - catch (Exception e) - { - throw new InvalidParameterSpecException("construction failed: " + e.getMessage()); // should never happen + return GcmSpecUtil.extractGcmSpec(gcmParams.toASN1Primitive()); } + return new IvParameterSpec(gcmParams.getNonce()); + } + if (paramSpec == IvParameterSpec.class) + { + return new IvParameterSpec(gcmParams.getNonce()); } - throw new InvalidParameterSpecException("unknown parameter spec: " + paramSpec.getName()); + throw new InvalidParameterSpecException("AlgorithmParameterSpec not recognized: " + paramSpec.getName()); } } @@ -589,19 +633,26 @@ public final class AES // extends BaseAlgorithmParameters // { // private CCMParameters ccmParams; - // + // // protected void engineInit(AlgorithmParameterSpec paramSpec) // throws InvalidParameterSpecException // { - // throw new InvalidParameterSpecException("No supported AlgorithmParameterSpec for AES parameter generation."); + // if (GcmSpecUtil.isGcmSpec(paramSpec)) + // { + // ccmParams = CCMParameters.getInstance(GcmSpecUtil.extractGcmParameters(paramSpec)); + // } + // else + // { + // throw new InvalidParameterSpecException("AlgorithmParameterSpec class not recognized: " + paramSpec.getClass().getName()); + // } // } - // + // // protected void engineInit(byte[] params) // throws IOException // { // ccmParams = CCMParameters.getInstance(params); // } - // + // // protected void engineInit(byte[] params, String format) // throws IOException // { @@ -609,16 +660,16 @@ public final class AES // { // throw new IOException("unknown format specified"); // } - // + // // ccmParams = CCMParameters.getInstance(params); // } - // + // // protected byte[] engineGetEncoded() // throws IOException // { // return ccmParams.getEncoded(); // } - // + // // protected byte[] engineGetEncoded(String format) // throws IOException // { @@ -626,37 +677,32 @@ public final class AES // { // throw new IOException("unknown format specified"); // } - // + // // return ccmParams.getEncoded(); // } - // + // // protected String engineToString() // { // return "CCM"; // } - // + // // protected AlgorithmParameterSpec localEngineGetParameterSpec(Class paramSpec) // throws InvalidParameterSpecException // { - // if (gcmSpecClass != null) + // if (paramSpec == AlgorithmParameterSpec.class || GcmSpecUtil.isGcmSpec(paramSpec)) // { - // try - // { - // Constructor constructor = gcmSpecClass.getConstructor(new Class[] { Integer.TYPE, byte[].class }); - // - // return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(ccmParams.getIcvLen() * 8), ccmParams.getNonce() }); - // } - // catch (NoSuchMethodException e) - // { - // throw new InvalidParameterSpecException("no constructor found!"); // should never happen - // } - // catch (Exception e) + // if (GcmSpecUtil.gcmSpecExists()) // { - // throw new InvalidParameterSpecException("construction failed: " + e.getMessage()); // should never happen + // return GcmSpecUtil.extractGcmSpec(ccmParams.toASN1Primitive()); // } + // return new IvParameterSpec(ccmParams.getNonce()); // } - // - // throw new InvalidParameterSpecException("unknown parameter spec: " + paramSpec.getName()); + // if (paramSpec == IvParameterSpec.class) + // { + // return new IvParameterSpec(ccmParams.getNonce()); + // } + // + // throw new InvalidParameterSpecException("AlgorithmParameterSpec not recognized: " + paramSpec.getName()); // } // } // END android-removed @@ -713,38 +759,39 @@ public final class AES provider.addAlgorithm("Alg.Alias.Cipher." + wrongAES192, "AES"); provider.addAlgorithm("Alg.Alias.Cipher." + wrongAES256, "AES"); // BEGIN android-removed - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes128_ECB, PREFIX + "$ECB"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes192_ECB, PREFIX + "$ECB"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes256_ECB, PREFIX + "$ECB"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes128_CBC, PREFIX + "$CBC"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes192_CBC, PREFIX + "$CBC"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes256_CBC, PREFIX + "$CBC"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes128_OFB, PREFIX + "$OFB"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes192_OFB, PREFIX + "$OFB"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes256_OFB, PREFIX + "$OFB"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes128_CFB, PREFIX + "$CFB"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes192_CFB, PREFIX + "$CFB"); - // provider.addAlgorithm("Cipher." + NISTObjectIdentifiers.id_aes256_CFB, PREFIX + "$CFB"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes128_ECB, PREFIX + "$ECB"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes192_ECB, PREFIX + "$ECB"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes256_ECB, PREFIX + "$ECB"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes128_CBC, PREFIX + "$CBC"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes192_CBC, PREFIX + "$CBC"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes256_CBC, PREFIX + "$CBC"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes128_OFB, PREFIX + "$OFB"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes192_OFB, PREFIX + "$OFB"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes256_OFB, PREFIX + "$OFB"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes128_CFB, PREFIX + "$CFB"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes192_CFB, PREFIX + "$CFB"); + // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes256_CFB, PREFIX + "$CFB"); // END android-removed provider.addAlgorithm("Cipher.AESWRAP", PREFIX + "$Wrap"); - provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_wrap, "AESWRAP"); - provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes192_wrap, "AESWRAP"); - provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_wrap, "AESWRAP"); + provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes128_wrap, "AESWRAP"); + provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes192_wrap, "AESWRAP"); + provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes256_wrap, "AESWRAP"); + provider.addAlgorithm("Alg.Alias.Cipher.AESKW", "AESWRAP"); // BEGIN android-removed // provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap"); // provider.addAlgorithm("Cipher.AESRFC5649WRAP", PREFIX + "$RFC5649Wrap"); - // + // // provider.addAlgorithm("AlgorithmParameterGenerator.CCM", PREFIX + "$AlgParamGenCCM"); // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes128_CCM, "CCM"); // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_CCM, "CCM"); // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_CCM, "CCM"); - // + // // provider.addAlgorithm("Cipher.CCM", PREFIX + "$CCM"); - // provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_CCM, "CCM"); - // provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes192_CCM, "CCM"); - // provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_CCM, "CCM"); - // + // provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes128_CCM, "CCM"); + // provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes192_CCM, "CCM"); + // provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes256_CCM, "CCM"); + // // provider.addAlgorithm("AlgorithmParameterGenerator.GCM", PREFIX + "$AlgParamGenGCM"); // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes128_GCM, "GCM"); // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_GCM, "GCM"); @@ -763,45 +810,45 @@ public final class AES // provider.addAlgorithm("KeyGenerator." + wrongAES128, PREFIX + "$KeyGen128"); // provider.addAlgorithm("KeyGenerator." + wrongAES192, PREFIX + "$KeyGen192"); // provider.addAlgorithm("KeyGenerator." + wrongAES256, PREFIX + "$KeyGen256"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_ECB, PREFIX + "$KeyGen128"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_CBC, PREFIX + "$KeyGen128"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_OFB, PREFIX + "$KeyGen128"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_CFB, PREFIX + "$KeyGen128"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_ECB, PREFIX + "$KeyGen192"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_CBC, PREFIX + "$KeyGen192"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_OFB, PREFIX + "$KeyGen192"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_CFB, PREFIX + "$KeyGen192"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_ECB, PREFIX + "$KeyGen256"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_CBC, PREFIX + "$KeyGen256"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_OFB, PREFIX + "$KeyGen256"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_CFB, PREFIX + "$KeyGen256"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes128_ECB, PREFIX + "$KeyGen128"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes128_CBC, PREFIX + "$KeyGen128"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes128_OFB, PREFIX + "$KeyGen128"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes128_CFB, PREFIX + "$KeyGen128"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes192_ECB, PREFIX + "$KeyGen192"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes192_CBC, PREFIX + "$KeyGen192"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes192_OFB, PREFIX + "$KeyGen192"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes192_CFB, PREFIX + "$KeyGen192"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes256_ECB, PREFIX + "$KeyGen256"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes256_CBC, PREFIX + "$KeyGen256"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes256_OFB, PREFIX + "$KeyGen256"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes256_CFB, PREFIX + "$KeyGen256"); // provider.addAlgorithm("KeyGenerator.AESWRAP", PREFIX + "$KeyGen"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_wrap, PREFIX + "$KeyGen128"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_wrap, PREFIX + "$KeyGen192"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_wrap, PREFIX + "$KeyGen256"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_GCM, PREFIX + "$KeyGen128"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_GCM, PREFIX + "$KeyGen192"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_GCM, PREFIX + "$KeyGen256"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_CCM, PREFIX + "$KeyGen128"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_CCM, PREFIX + "$KeyGen192"); - // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_CCM, PREFIX + "$KeyGen256"); - // + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes128_wrap, PREFIX + "$KeyGen128"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes192_wrap, PREFIX + "$KeyGen192"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes256_wrap, PREFIX + "$KeyGen256"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes128_GCM, PREFIX + "$KeyGen128"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes192_GCM, PREFIX + "$KeyGen192"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes256_GCM, PREFIX + "$KeyGen256"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes128_CCM, PREFIX + "$KeyGen128"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes192_CCM, PREFIX + "$KeyGen192"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes256_CCM, PREFIX + "$KeyGen256"); + // // provider.addAlgorithm("Mac.AESCMAC", PREFIX + "$AESCMAC"); // END android-removed - provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.getId(), "PBEWITHSHAAND128BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.getId(), "PBEWITHSHAAND192BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc.getId(), "PBEWITHSHAAND256BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc.getId(), "PBEWITHSHA256AND128BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.getId(), "PBEWITHSHA256AND192BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.getId(), "PBEWITHSHA256AND256BITAES-CBC-BC"); - - provider.addAlgorithm("Cipher.PBEWITHSHAAND128BITAES-CBC-BC", PREFIX + "$PBEWithAESCBC"); - provider.addAlgorithm("Cipher.PBEWITHSHAAND192BITAES-CBC-BC", PREFIX + "$PBEWithAESCBC"); - provider.addAlgorithm("Cipher.PBEWITHSHAAND256BITAES-CBC-BC", PREFIX + "$PBEWithAESCBC"); - provider.addAlgorithm("Cipher.PBEWITHSHA256AND128BITAES-CBC-BC", PREFIX + "$PBEWithAESCBC"); - provider.addAlgorithm("Cipher.PBEWITHSHA256AND192BITAES-CBC-BC", PREFIX + "$PBEWithAESCBC"); - provider.addAlgorithm("Cipher.PBEWITHSHA256AND256BITAES-CBC-BC", PREFIX + "$PBEWithAESCBC"); + provider.addAlgorithm("Alg.Alias.Cipher", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc, "PBEWITHSHAAND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc, "PBEWITHSHAAND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc, "PBEWITHSHAAND256BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher", BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc, "PBEWITHSHA256AND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher", BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc, "PBEWITHSHA256AND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher", BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc, "PBEWITHSHA256AND256BITAES-CBC-BC"); + + provider.addAlgorithm("Cipher.PBEWITHSHAAND128BITAES-CBC-BC", PREFIX + "$PBEWithSHA1AESCBC128"); + provider.addAlgorithm("Cipher.PBEWITHSHAAND192BITAES-CBC-BC", PREFIX + "$PBEWithSHA1AESCBC192"); + provider.addAlgorithm("Cipher.PBEWITHSHAAND256BITAES-CBC-BC", PREFIX + "$PBEWithSHA1AESCBC256"); + provider.addAlgorithm("Cipher.PBEWITHSHA256AND128BITAES-CBC-BC", PREFIX + "$PBEWithSHA256AESCBC128"); + provider.addAlgorithm("Cipher.PBEWITHSHA256AND192BITAES-CBC-BC", PREFIX + "$PBEWithSHA256AESCBC192"); + provider.addAlgorithm("Cipher.PBEWITHSHA256AND256BITAES-CBC-BC", PREFIX + "$PBEWithSHA256AESCBC256"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND128BITAES-CBC-BC","PBEWITHSHAAND128BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND192BITAES-CBC-BC","PBEWITHSHAAND192BITAES-CBC-BC"); @@ -809,10 +856,25 @@ public final class AES provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-1AND128BITAES-CBC-BC","PBEWITHSHAAND128BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-1AND192BITAES-CBC-BC","PBEWITHSHAAND192BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-1AND256BITAES-CBC-BC","PBEWITHSHAAND256BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHAAND128BITAES-BC","PBEWITHSHAAND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHAAND192BITAES-BC", "PBEWITHSHAAND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHAAND256BITAES-BC", "PBEWITHSHAAND256BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND128BITAES-BC","PBEWITHSHAAND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND192BITAES-BC","PBEWITHSHAAND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND256BITAES-BC","PBEWITHSHAAND256BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-1AND128BITAES-BC","PBEWITHSHAAND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-1AND192BITAES-BC","PBEWITHSHAAND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-1AND256BITAES-BC","PBEWITHSHAAND256BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-256AND128BITAES-CBC-BC","PBEWITHSHA256AND128BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-256AND192BITAES-CBC-BC","PBEWITHSHA256AND192BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-256AND256BITAES-CBC-BC","PBEWITHSHA256AND256BITAES-CBC-BC"); - + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA256AND128BITAES-BC","PBEWITHSHA256AND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA256AND192BITAES-BC","PBEWITHSHA256AND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA256AND256BITAES-BC","PBEWITHSHA256AND256BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-256AND128BITAES-BC","PBEWITHSHA256AND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-256AND192BITAES-BC","PBEWITHSHA256AND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA-256AND256BITAES-BC","PBEWITHSHA256AND256BITAES-CBC-BC"); + provider.addAlgorithm("Cipher.PBEWITHMD5AND128BITAES-CBC-OPENSSL", PREFIX + "$PBEWithAESCBC"); provider.addAlgorithm("Cipher.PBEWITHMD5AND192BITAES-CBC-OPENSSL", PREFIX + "$PBEWithAESCBC"); provider.addAlgorithm("Cipher.PBEWITHMD5AND256BITAES-CBC-OPENSSL", PREFIX + "$PBEWithAESCBC"); @@ -836,12 +898,15 @@ public final class AES provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA-256AND128BITAES-CBC-BC","PBEWITHSHA256AND128BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA-256AND192BITAES-CBC-BC","PBEWITHSHA256AND192BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA-256AND256BITAES-CBC-BC","PBEWITHSHA256AND256BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.getId(), "PBEWITHSHAAND128BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.getId(), "PBEWITHSHAAND192BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc.getId(), "PBEWITHSHAAND256BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc.getId(), "PBEWITHSHA256AND128BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.getId(), "PBEWITHSHA256AND192BITAES-CBC-BC"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.getId(), "PBEWITHSHA256AND256BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA-256AND128BITAES-BC","PBEWITHSHA256AND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA-256AND192BITAES-BC","PBEWITHSHA256AND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA-256AND256BITAES-BC","PBEWITHSHA256AND256BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc, "PBEWITHSHAAND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc, "PBEWITHSHAAND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc, "PBEWITHSHAAND256BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc, "PBEWITHSHA256AND128BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc, "PBEWITHSHA256AND192BITAES-CBC-BC"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc, "PBEWITHSHA256AND256BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND128BITAES-CBC-BC", "PKCS12PBE"); provider.addAlgorithm("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND192BITAES-CBC-BC", "PKCS12PBE"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/ARC4.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/ARC4.java index 9de8ef0c..c780d12c 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/ARC4.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/ARC4.java @@ -68,7 +68,7 @@ public final class ARC4 { public PBEWithSHAAnd128Bit() { - super(new RC4Engine(), 0); + super(new RC4Engine(), 0, 128, SHA1); } } @@ -80,7 +80,7 @@ public final class ARC4 { public PBEWithSHAAnd40Bit() { - super(new RC4Engine(), 0); + super(new RC4Engine(), 0, 40, SHA1); } } @@ -96,7 +96,7 @@ public final class ARC4 public void configure(ConfigurableProvider provider) { provider.addAlgorithm("Cipher.ARC4", PREFIX + "$Base"); - provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.rc4, "ARC4"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.rc4, "ARC4"); provider.addAlgorithm("Alg.Alias.Cipher.ARCFOUR", "ARC4"); provider.addAlgorithm("Alg.Alias.Cipher.RC4", "ARC4"); provider.addAlgorithm("KeyGenerator.ARC4", PREFIX + "$KeyGen"); @@ -113,14 +113,14 @@ public final class ARC4 provider.addAlgorithm("Cipher.PBEWITHSHAAND128BITRC4", PREFIX + "$PBEWithSHAAnd128Bit"); provider.addAlgorithm("Cipher.PBEWITHSHAAND40BITRC4", PREFIX + "$PBEWithSHAAnd40Bit"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC4, "PBEWITHSHAAND128BITRC4"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC4, "PBEWITHSHAAND40BITRC4"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC4, "PBEWITHSHAAND128BITRC4"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC4, "PBEWITHSHAAND40BITRC4"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND128BITRC4", "PBEWITHSHAAND128BITRC4"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND40BITRC4", "PBEWITHSHAAND40BITRC4"); - provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC4, "PBEWITHSHAAND128BITRC4"); - provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC4, "PBEWITHSHAAND40BITRC4"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC4, "PBEWITHSHAAND128BITRC4"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC4, "PBEWITHSHAAND40BITRC4"); } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java index 0e374876..c0a09499 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java @@ -1,11 +1,18 @@ package org.bouncycastle.jcajce.provider.symmetric; +import org.bouncycastle.asn1.misc.MiscObjectIdentifiers; import org.bouncycastle.crypto.CipherKeyGenerator; import org.bouncycastle.crypto.engines.BlowfishEngine; +// BEGIN android-removed +// import org.bouncycastle.crypto.macs.CMac; +// END android-removed import org.bouncycastle.crypto.modes.CBCBlockCipher; import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher; import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator; +// BEGIN android-removed +// import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac; +// END android-removed import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters; import org.bouncycastle.jcajce.provider.util.AlgorithmProvider; @@ -33,6 +40,17 @@ public final class Blowfish } } + // BEGIN android-removed + // public static class CMAC + // extends BaseMac + // { + // public CMAC() + // { + // super(new CMac(new BlowfishEngine())); + // } + // } + // END android-removed + public static class KeyGen extends BaseKeyGenerator { @@ -62,15 +80,17 @@ public final class Blowfish public void configure(ConfigurableProvider provider) { - + // BEGIN android-removed + // provider.addAlgorithm("Mac.BLOWFISHCMAC", PREFIX + "$CMAC"); + // END android-removed provider.addAlgorithm("Cipher.BLOWFISH", PREFIX + "$ECB"); // BEGIN android-removed - // provider.addAlgorithm("Cipher.1.3.6.1.4.1.3029.1.2", PREFIX + "$CBC"); + // provider.addAlgorithm("Cipher", MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CBC, PREFIX + "$CBC"); // END android-removed provider.addAlgorithm("KeyGenerator.BLOWFISH", PREFIX + "$KeyGen"); - provider.addAlgorithm("Alg.Alias.KeyGenerator.1.3.6.1.4.1.3029.1.2", "BLOWFISH"); + provider.addAlgorithm("Alg.Alias.KeyGenerator", MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CBC, "BLOWFISH"); provider.addAlgorithm("AlgorithmParameters.BLOWFISH", PREFIX + "$AlgParams"); - provider.addAlgorithm("Alg.Alias.AlgorithmParameters.1.3.6.1.4.1.3029.1.2", "BLOWFISH"); + provider.addAlgorithm("Alg.Alias.AlgorithmParameters", MiscObjectIdentifiers.cryptlib_algorithm_blowfish_CBC, "BLOWFISH"); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java index b4c7c06e..5a4f8cda 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java @@ -405,7 +405,7 @@ public final class DES // { // public PBEWithMD2() // { - // super(new CBCBlockCipher(new DESEngine())); + // super(new CBCBlockCipher(new DESEngine()), PKCS5S1, MD2, 64, 8); // } // } // END android-removed @@ -418,7 +418,7 @@ public final class DES { public PBEWithMD5() { - super(new CBCBlockCipher(new DESEngine())); + super(new CBCBlockCipher(new DESEngine()), PKCS5S1, MD5, 64, 8); } } @@ -430,7 +430,7 @@ public final class DES { public PBEWithSHA1() { - super(new CBCBlockCipher(new DESEngine())); + super(new CBCBlockCipher(new DESEngine()), PKCS5S1, SHA1, 64, 8); } } @@ -449,7 +449,7 @@ public final class DES provider.addAlgorithm("Cipher.DES", PREFIX + "$ECB"); // BEGIN android-removed - // provider.addAlgorithm("Cipher." + OIWObjectIdentifiers.desCBC, PREFIX + "$CBC"); + // provider.addAlgorithm("Cipher", OIWObjectIdentifiers.desCBC, PREFIX + "$CBC"); // // addAlias(provider, OIWObjectIdentifiers.desCBC, "DES"); // @@ -486,7 +486,7 @@ public final class DES // END android-removed provider.addAlgorithm("AlgorithmParameters.DES", PACKAGE + ".util.IvAlgorithmParameters"); - provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + OIWObjectIdentifiers.desCBC, "DES"); + provider.addAlgorithm("Alg.Alias.AlgorithmParameters", OIWObjectIdentifiers.desCBC, "DES"); // BEGIN android-removed // provider.addAlgorithm("AlgorithmParameterGenerator.DES", PREFIX + "$AlgParamGen"); @@ -498,13 +498,19 @@ public final class DES provider.addAlgorithm("Cipher.PBEWITHSHA1ANDDES", PREFIX + "$PBEWithSHA1"); // BEGIN android-removed - // provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC, "PBEWITHMD2ANDDES"); + // provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC, "PBEWITHMD2ANDDES"); // END android-removed - provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, "PBEWITHMD5ANDDES"); - provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, "PBEWITHSHA1ANDDES"); - + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, "PBEWITHMD5ANDDES"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, "PBEWITHSHA1ANDDES"); + + // BEGIN android-removed + // provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHMD2ANDDES-CBC", "PBEWITHMD2ANDDES"); + // BEGIN android-removed + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHMD5ANDDES-CBC", "PBEWITHMD5ANDDES"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1ANDDES-CBC", "PBEWITHSHA1ANDDES"); + // BEGIN android-removed - // provider.addAlgorithm("SecretKeyFactory.PBEWITHMD2ANDDES", PREFIX + "$PBEWithMD2KeyFactory"); + // provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHMD2ANDDES-CBC", "PBEWITHMD2ANDDES"); // END android-removed provider.addAlgorithm("SecretKeyFactory.PBEWITHMD5ANDDES", PREFIX + "$PBEWithMD5KeyFactory"); provider.addAlgorithm("SecretKeyFactory.PBEWITHSHA1ANDDES", PREFIX + "$PBEWithSHA1KeyFactory"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java index 7b3addd7..64d8972a 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java @@ -105,7 +105,7 @@ public final class DESede super(new CBCBlockCipherMac(new DESedeEngine(), 64, new ISO7816d4Padding())); } } - + public static class CBCMAC extends BaseMac { @@ -125,7 +125,7 @@ public final class DESede // } // } // END android-removed - + public static class Wrap extends BaseWrapCipher { @@ -134,7 +134,7 @@ public final class DESede super(new DESedeWrapEngine()); } } - + // BEGIN android-removed // public static class RFC3211 // extends BaseWrapCipher @@ -218,7 +218,7 @@ public final class DESede { public PBEWithSHAAndDES3Key() { - super(new CBCBlockCipher(new DESedeEngine())); + super(new CBCBlockCipher(new DESedeEngine()), PKCS12, SHA1, 192, 8); } } @@ -230,7 +230,7 @@ public final class DESede { public PBEWithSHAAndDES2Key() { - super(new CBCBlockCipher(new DESedeEngine())); + super(new CBCBlockCipher(new DESedeEngine()), PKCS12, SHA1, 128, 8); } } @@ -381,7 +381,7 @@ public final class DESede { provider.addAlgorithm("Cipher.DESEDE", PREFIX + "$ECB"); // BEGIN android-removed - // provider.addAlgorithm("Cipher." + PKCSObjectIdentifiers.des_EDE3_CBC, PREFIX + "$CBC"); + // provider.addAlgorithm("Cipher", PKCSObjectIdentifiers.des_EDE3_CBC, PREFIX + "$CBC"); // END android-removed provider.addAlgorithm("Cipher.DESEDEWRAP", PREFIX + "$Wrap"); // BEGIN android-changed @@ -389,6 +389,7 @@ public final class DESede // END android-changed // BEGIN android-removed // provider.addAlgorithm("Cipher.DESEDERFC3211WRAP", PREFIX + "$RFC3211"); + // provider.addAlgorithm("Alg.Alias.Cipher.DESEDERFC3217WRAP", "DESEDEWRAP"); // END android-removed provider.addAlgorithm("Alg.Alias.Cipher.TDEA", "DESEDE"); @@ -411,11 +412,16 @@ public final class DESede // BEGIN android-removed // provider.addAlgorithm("Cipher.BROKENPBEWITHSHAAND2-KEYTRIPLEDES-CBC", PREFIX + "$BrokePBEWithSHAAndDES2Key"); // END android-removed - provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC, "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"); - provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithSHAAnd2_KeyTripleDES_CBC, "PBEWITHSHAAND2-KEYTRIPLEDES-CBC"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC, "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithSHAAnd2_KeyTripleDES_CBC, "PBEWITHSHAAND2-KEYTRIPLEDES-CBC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1ANDDESEDE", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND3-KEYTRIPLEDES-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND2-KEYTRIPLEDES-CBC", "PBEWITHSHAAND2-KEYTRIPLEDES-CBC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHAAND3-KEYDESEDE-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHAAND2-KEYDESEDE-CBC", "PBEWITHSHAAND2-KEYTRIPLEDES-CBC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND3-KEYDESEDE-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND2-KEYDESEDE-CBC", "PBEWITHSHAAND2-KEYTRIPLEDES-CBC"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1ANDDESEDE-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"); } provider.addAlgorithm("KeyGenerator.DESEDE", PREFIX + "$KeyGenerator"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java new file mode 100644 index 00000000..5ccc8ff0 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java @@ -0,0 +1,78 @@ +package org.bouncycastle.jcajce.provider.symmetric; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; + +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.cms.GCMParameters; +import org.bouncycastle.util.Integers; + +class GcmSpecUtil +{ + static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec"); + + static boolean gcmSpecExists() + { + return gcmSpecClass != null; + } + + static boolean isGcmSpec(AlgorithmParameterSpec paramSpec) + { + return gcmSpecClass != null && gcmSpecClass.isInstance(paramSpec); + } + + static boolean isGcmSpec(Class paramSpecClass) + { + return gcmSpecClass == paramSpecClass; + } + + static AlgorithmParameterSpec extractGcmSpec(ASN1Primitive spec) + throws InvalidParameterSpecException + { + try + { + GCMParameters gcmParams = GCMParameters.getInstance(spec); + Constructor constructor = gcmSpecClass.getConstructor(new Class[]{Integer.TYPE, byte[].class}); + + return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(gcmParams.getIcvLen() * 8), gcmParams.getNonce() }); + } + catch (NoSuchMethodException e) + { + throw new InvalidParameterSpecException("No constructor found!"); // should never happen + } + catch (Exception e) + { + throw new InvalidParameterSpecException("Construction failed: " + e.getMessage()); // should never happen + } + } + + static GCMParameters extractGcmParameters(AlgorithmParameterSpec paramSpec) + throws InvalidParameterSpecException + { + try + { + Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]); + Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]); + + return new GCMParameters((byte[])iv.invoke(paramSpec, new Object[0]), ((Integer)tLen.invoke(paramSpec, new Object[0])).intValue() / 8); + } + catch (Exception e) + { + throw new InvalidParameterSpecException("Cannot process GCMParameterSpec"); + } + } + + private static Class lookup(String className) + { + try + { + return GcmSpecUtil.class.getClassLoader().loadClass(className); + } + catch (Exception e) + { + return null; + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java index 4056aa79..343fa0c7 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java @@ -144,7 +144,7 @@ public final class RC2 { public PBEWithMD5AndRC2() { - super(new CBCBlockCipher(new RC2Engine())); + super(new CBCBlockCipher(new RC2Engine()), PKCS5S1, MD5, 64, 8); } } @@ -156,7 +156,7 @@ public final class RC2 { public PBEWithSHA1AndRC2() { - super(new CBCBlockCipher(new RC2Engine())); + super(new CBCBlockCipher(new RC2Engine()), PKCS5S1, SHA1, 64, 8); } } @@ -168,7 +168,7 @@ public final class RC2 { public PBEWithSHAAnd128BitRC2() { - super(new CBCBlockCipher(new RC2Engine())); + super(new CBCBlockCipher(new RC2Engine()), PKCS12, SHA1, 128, 8); } } @@ -180,7 +180,7 @@ public final class RC2 { public PBEWithSHAAnd40BitRC2() { - super(new CBCBlockCipher(new RC2Engine())); + super(new CBCBlockCipher(new RC2Engine()), PKCS12, SHA1, 40, 8); } } @@ -465,7 +465,6 @@ public final class RC2 public void configure(ConfigurableProvider provider) { - // BEGIN android-removed // provider.addAlgorithm("AlgorithmParameterGenerator.RC2", PREFIX + "$AlgParamGen"); // provider.addAlgorithm("AlgorithmParameterGenerator.1.2.840.113549.3.2", PREFIX + "$AlgParamGen"); @@ -478,8 +477,8 @@ public final class RC2 // // provider.addAlgorithm("Cipher.RC2", PREFIX + "$ECB"); // provider.addAlgorithm("Cipher.RC2WRAP", PREFIX + "$Wrap"); - // provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.id_alg_CMSRC2wrap, "RC2WRAP"); - // provider.addAlgorithm("Cipher.1.2.840.113549.3.2", PREFIX + "$CBC"); + // provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.id_alg_CMSRC2wrap, "RC2WRAP"); + // provider.addAlgorithm("Cipher", PKCSObjectIdentifiers.RC2_CBC, PREFIX + "$CBC"); // // provider.addAlgorithm("Mac.RC2MAC", PREFIX + "$CBCMAC"); // provider.addAlgorithm("Alg.Alias.Mac.RC2", "RC2MAC"); @@ -494,12 +493,12 @@ public final class RC2 provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA1ANDRC2-CBC", "PBEWITHSHA1ANDRC2"); // BEGIN android-removed - // provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD2AndRC2_CBC, "PBEWITHMD2ANDRC2"); + // provider.addAlgorithm("Alg.Alias.SecretKeyFactory", PKCSObjectIdentifiers.pbeWithMD2AndRC2_CBC, "PBEWITHMD2ANDRC2"); // END android-removed - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC, "PBEWITHMD5ANDRC2"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC, "PBEWITHMD5ANDRC2"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithSHA1AndRC2_CBC, "PBEWITHSHA1ANDRC2"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory", PKCSObjectIdentifiers.pbeWithSHA1AndRC2_CBC, "PBEWITHSHA1ANDRC2"); provider.addAlgorithm("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.5", "PBEWITHSHAAND128BITRC2-CBC"); provider.addAlgorithm("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.6", "PBEWITHSHAAND40BITRC2-CBC"); @@ -511,28 +510,31 @@ public final class RC2 provider.addAlgorithm("SecretKeyFactory.PBEWITHSHAAND128BITRC2-CBC", PREFIX + "$PBEWithSHAAnd128BitKeyFactory"); provider.addAlgorithm("SecretKeyFactory.PBEWITHSHAAND40BITRC2-CBC", PREFIX + "$PBEWithSHAAnd40BitKeyFactory"); - + // BEGIN android-removed - // provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithMD2AndRC2_CBC, "PBEWITHMD2ANDRC2"); + // provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithMD2AndRC2_CBC, "PBEWITHMD2ANDRC2"); // END android-removed - provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC, "PBEWITHMD5ANDRC2"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC, "PBEWITHMD5ANDRC2"); - provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithSHA1AndRC2_CBC, "PBEWITHSHA1ANDRC2"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithSHA1AndRC2_CBC, "PBEWITHSHA1ANDRC2"); provider.addAlgorithm("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.5", "PKCS12PBE"); provider.addAlgorithm("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.6", "PKCS12PBE"); provider.addAlgorithm("Alg.Alias.AlgorithmParameters.PBEWithSHAAnd3KeyTripleDES", "PKCS12PBE"); - provider.addAlgorithm("Alg.Alias.Cipher.1.2.840.113549.1.12.1.5", "PBEWITHSHAAND128BITRC2-CBC"); - provider.addAlgorithm("Alg.Alias.Cipher.1.2.840.113549.1.12.1.6", "PBEWITHSHAAND40BITRC2-CBC"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC2_CBC, "PBEWITHSHAAND128BITRC2-CBC"); + provider.addAlgorithm("Alg.Alias.Cipher", PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC2_CBC, "PBEWITHSHAAND40BITRC2-CBC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND128BITRC2-CBC", "PBEWITHSHAAND128BITRC2-CBC"); provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1AND40BITRC2-CBC", "PBEWITHSHAAND40BITRC2-CBC"); provider.addAlgorithm("Cipher.PBEWITHSHA1ANDRC2", PREFIX + "$PBEWithSHA1AndRC2"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHAANDRC2-CBC", "PBEWITHSHA1ANDRC2"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1ANDRC2-CBC", "PBEWITHSHA1ANDRC2"); provider.addAlgorithm("Cipher.PBEWITHSHAAND128BITRC2-CBC", PREFIX + "$PBEWithSHAAnd128BitRC2"); provider.addAlgorithm("Cipher.PBEWITHSHAAND40BITRC2-CBC", PREFIX + "$PBEWithSHAAnd40BitRC2"); provider.addAlgorithm("Cipher.PBEWITHMD5ANDRC2", PREFIX + "$PBEWithMD5AndRC2"); + provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHMD5ANDRC2-CBC", "PBEWITHMD5ANDRC2"); provider.addAlgorithm("Alg.Alias.AlgorithmParameters.PBEWITHSHA1ANDRC2", "PKCS12PBE"); provider.addAlgorithm("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDRC2", "PKCS12PBE"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java index fc34865f..7ac79e7e 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java @@ -7,6 +7,19 @@ abstract class SymmetricAlgorithmProvider extends AlgorithmProvider { // BEGIN android-removed + // protected void addCMacAlgorithm( + // ConfigurableProvider provider, + // String algorithm, + // String algorithmClassName, + // String keyGeneratorClassName) + // { + // provider.addAlgorithm("Mac." + algorithm + "-CMAC", algorithmClassName); + // provider.addAlgorithm("Alg.Alias.Mac." + algorithm + "CMAC", algorithm + "-CMAC"); + // + // provider.addAlgorithm("KeyGenerator." + algorithm + "-CMAC", keyGeneratorClassName); + // provider.addAlgorithm("Alg.Alias.KeyGenerator." + algorithm + "CMAC", algorithm + "-CMAC"); + // } + // // protected void addGMacAlgorithm( // ConfigurableProvider provider, // String algorithm, diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java index e2b2efd8..c666ac14 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java @@ -102,7 +102,7 @@ public final class Twofish { public PBEWithSHA() { - super(new CBCBlockCipher(new TwofishEngine())); + super(new CBCBlockCipher(new TwofishEngine()), PKCS12, SHA1, 256, 16); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java index 0e933b71..da2b4d56 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java @@ -18,6 +18,7 @@ import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; +import javax.crypto.interfaces.PBEKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEParameterSpec; // BEGIN android-removed @@ -69,10 +70,15 @@ import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.crypto.params.RC2Parameters; // BEGIN android-removed // import org.bouncycastle.crypto.params.RC5Parameters; +// import org.bouncycastle.jcajce.PBKDF1Key; +// import org.bouncycastle.jcajce.PBKDF1KeyWithParameters; +// END android-removed +import org.bouncycastle.jcajce.PKCS12Key; +import org.bouncycastle.jcajce.PKCS12KeyWithParameters; +// BEGIN android-removed // import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec; // import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec; // END android-removed -import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.Strings; public class BaseBlockCipher @@ -90,12 +96,12 @@ public class BaseBlockCipher // RC2ParameterSpec.class, // RC5ParameterSpec.class, // END android-removed + gcmSpecClass, IvParameterSpec.class, PBEParameterSpec.class, // BEGIN android-removed - // GOST28147ParameterSpec.class, + // GOST28147ParameterSpec.class // END android-removed - gcmSpecClass }; private BlockCipher baseEngine; @@ -104,10 +110,14 @@ public class BaseBlockCipher private ParametersWithIV ivParam; private AEADParameters aeadParams; + private int keySizeInBits; + private int scheme = -1; + private int digest; + private int ivLength = 0; private boolean padded; - + private boolean fixedIv = true; private PBEParameterSpec pbeSpec = null; private String pbeAlgorithm = null; @@ -136,6 +146,23 @@ public class BaseBlockCipher } protected BaseBlockCipher( + BlockCipher engine, + int scheme, + int digest, + int keySizeInBits, + int ivLength) + { + baseEngine = engine; + + this.scheme = scheme; + this.digest = digest; + this.keySizeInBits = keySizeInBits; + this.ivLength = ivLength; + + cipher = new BufferedGenericBlockCipher(engine); + } + + protected BaseBlockCipher( BlockCipherProvider provider) { baseEngine = provider.get(); @@ -153,6 +180,17 @@ public class BaseBlockCipher } protected BaseBlockCipher( + AEADBlockCipher engine, + boolean fixedIv, + int ivLength) + { + this.baseEngine = engine.getUnderlyingCipher(); + this.fixedIv = fixedIv; + this.ivLength = ivLength; + this.cipher = new AEADGenericBlockCipher(engine); + } + + protected BaseBlockCipher( org.bouncycastle.crypto.BlockCipher engine, int ivLength) { @@ -239,7 +277,7 @@ public class BaseBlockCipher try { engineParams = createParametersInstance("GCM"); - engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize()).getEncoded()); + engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize() / 8).getEncoded()); } catch (Exception e) { @@ -322,6 +360,7 @@ public class BaseBlockCipher // { // throw new IllegalArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)"); // } + // fixedIv = false; // cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( // new SICBlockCipher(baseEngine))); // } @@ -329,6 +368,7 @@ public class BaseBlockCipher else if (modeName.startsWith("CTR")) { ivLength = baseEngine.getBlockSize(); + fixedIv = false; cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( new SICBlockCipher(baseEngine))); } @@ -478,7 +518,81 @@ public class BaseBlockCipher // // a note on iv's - if ivLength is zero the IV gets ignored (we don't use it). // - if (key instanceof BCPBEKey) + if (scheme == PKCS12 || key instanceof PKCS12Key) + { + SecretKey k; + try + { + k = (SecretKey)key; + } + catch (Exception e) + { + throw new InvalidKeyException("PKCS12 requires a SecretKey/PBEKey"); + } + + if (params instanceof PBEParameterSpec) + { + pbeSpec = (PBEParameterSpec)params; + } + + if (k instanceof PBEKey && pbeSpec == null) + { + // BEGIN android-added + if (((PBEKey)k).getSalt() == null) { + // TODO(27061541): check whether this is the correct fix + throw new InvalidAlgorithmParameterException("Parameters for the algorithm are null " + + "and the PBEKey has null salt"); + } + // END android-added + pbeSpec = new PBEParameterSpec(((PBEKey)k).getSalt(), ((PBEKey)k).getIterationCount()); + } + + if (pbeSpec == null && !(k instanceof PBEKey)) + { + throw new InvalidKeyException("Algorithm requires a PBE key"); + } + if (key instanceof BCPBEKey) + { + if (((BCPBEKey)key).getParam() != null) + { + param = ((BCPBEKey)key).getParam(); + } + else + { + param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS12, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); + } + } + else + { + param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS12, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); + } + if (param instanceof ParametersWithIV) + { + ivParam = (ParametersWithIV)param; + } + } + // BEGIN android-removed + // else if (key instanceof PBKDF1Key) + // { + // PBKDF1Key k = (PBKDF1Key)key; + + // if (params instanceof PBEParameterSpec) + // { + // pbeSpec = (PBEParameterSpec)params; + // } + // if (k instanceof PBKDF1KeyWithParameters && pbeSpec == null) + // { + // pbeSpec = new PBEParameterSpec(((PBKDF1KeyWithParameters)k).getSalt(), ((PBKDF1KeyWithParameters)k).getIterationCount()); + // } + + // param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS5S1, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); + // if (param instanceof ParametersWithIV) + // { + // ivParam = (ParametersWithIV)param; + // } + // } + // END android-removed + else if (key instanceof BCPBEKey) { BCPBEKey k = (BCPBEKey)key; @@ -493,27 +607,7 @@ public class BaseBlockCipher if (k.getParam() != null) { - param = k.getParam(); - if (params instanceof IvParameterSpec) - { - IvParameterSpec iv = (IvParameterSpec)params; - - param = new ParametersWithIV(param, iv.getIV()); - } - // BEGIN android-removed - // else if (params instanceof GOST28147ParameterSpec) - // { - // // need to pick up IV and SBox. - // GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; - // - // param = new ParametersWithSBox(param, gost28147Param.getSbox()); - // - // if (gost28147Param.getIV() != null && ivLength != 0) - // { - // param = new ParametersWithIV(param, gost28147Param.getIV()); - // } - // } - // END android-removed + param = adjustParameters(params, k.getParam()); } else if (params instanceof PBEParameterSpec) { @@ -530,33 +624,59 @@ public class BaseBlockCipher ivParam = (ParametersWithIV)param; } } - else if (params == null) + else if (key instanceof PBEKey) { + PBEKey k = (PBEKey)key; + pbeSpec = (PBEParameterSpec)params; + if (k instanceof PKCS12KeyWithParameters && pbeSpec == null) + { + pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount()); + } + + param = PBE.Util.makePBEParameters(k.getEncoded(), scheme, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); + if (param instanceof ParametersWithIV) + { + ivParam = (ParametersWithIV)param; + } + } + // BEGIN android-changed + // Was: else if (!(key instanceof RepeatedSecretKeySpec)) + else + // END android-changed + { + if (scheme == PKCS5S1 || scheme == PKCS5S1_UTF8 || scheme == PKCS5S2 || scheme == PKCS5S2_UTF8) + { + throw new InvalidKeyException("Algorithm requires a PBE key"); + } param = new KeyParameter(key.getEncoded()); } - else if (params instanceof IvParameterSpec) + // BEGIN android-removed + // else + // { + // param = null; + // } + // END android-removed + + if (params instanceof IvParameterSpec) { if (ivLength != 0) { IvParameterSpec p = (IvParameterSpec)params; - if (p.getIV().length != ivLength && !isAEADModeName(modeName)) + if (p.getIV().length != ivLength && !(cipher instanceof AEADGenericBlockCipher) && fixedIv) { throw new InvalidAlgorithmParameterException("IV must be " + ivLength + " bytes long."); } - // BEGIN android-removed - // if (key instanceof RepeatedSecretKeySpec) - // { - // param = new ParametersWithIV(null, p.getIV()); - // ivParam = (ParametersWithIV)param; - // } - // else - // END android-removed + if (param instanceof ParametersWithIV) + { + param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), p.getIV()); + } + else { - param = new ParametersWithIV(new KeyParameter(key.getEncoded()), p.getIV()); - ivParam = (ParametersWithIV)param; + param = new ParametersWithIV(param, p.getIV()); } + ivParam = (ParametersWithIV)param; } else { @@ -564,8 +684,6 @@ public class BaseBlockCipher { throw new InvalidAlgorithmParameterException("ECB mode does not use an IV"); } - - param = new KeyParameter(key.getEncoded()); } } // BEGIN android-removed @@ -578,7 +696,14 @@ public class BaseBlockCipher // // if (gost28147Param.getIV() != null && ivLength != 0) // { - // param = new ParametersWithIV(param, gost28147Param.getIV()); + // if (param instanceof ParametersWithIV) + // { + // param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), gost28147Param.getIV()); + // } + // else + // { + // param = new ParametersWithIV(param, gost28147Param.getIV()); + // } // ivParam = (ParametersWithIV)param; // } // } @@ -590,7 +715,14 @@ public class BaseBlockCipher // // if (rc2Param.getIV() != null && ivLength != 0) // { - // param = new ParametersWithIV(param, rc2Param.getIV()); + // if (param instanceof ParametersWithIV) + // { + // param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), rc2Param.getIV()); + // } + // else + // { + // param = new ParametersWithIV(param, rc2Param.getIV()); + // } // ivParam = (ParametersWithIV)param; // } // } @@ -622,7 +754,14 @@ public class BaseBlockCipher // } // if ((rc5Param.getIV() != null) && (ivLength != 0)) // { - // param = new ParametersWithIV(param, rc5Param.getIV()); + // if (param instanceof ParametersWithIV) + // { + // param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), rc5Param.getIV()); + // } + // else + // { + // param = new ParametersWithIV(param, rc5Param.getIV()); + // } // ivParam = (ParametersWithIV)param; // } // } @@ -639,23 +778,23 @@ public class BaseBlockCipher Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]); Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]); - // BEGIN android-removed - // if (key instanceof RepeatedSecretKeySpec) - // { - // param = aeadParams = new AEADParameters(null, ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0])); - // } - // else - // END android-removed + KeyParameter keyParam; + if (param instanceof ParametersWithIV) + { + keyParam = (KeyParameter)((ParametersWithIV)param).getParameters(); + } + else { - param = aeadParams = new AEADParameters(new KeyParameter(key.getEncoded()), ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0])); + keyParam = (KeyParameter)param; } + param = aeadParams = new AEADParameters(keyParam, ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0])); } catch (Exception e) { throw new InvalidAlgorithmParameterException("Cannot process GCMParameterSpec."); } } - else + else if (params != null && !(params instanceof PBEParameterSpec)) { throw new InvalidAlgorithmParameterException("unknown parameter type."); } @@ -704,12 +843,75 @@ public class BaseBlockCipher throw new InvalidParameterException("unknown opmode " + opmode + " passed"); } } - catch (Exception e) + catch (final Exception e) { - throw new InvalidKeyException(e.getMessage()); + throw new InvalidKeyException(e.getMessage()) + { + public Throwable getCause() + { + return e; + } + }; } } + private CipherParameters adjustParameters(AlgorithmParameterSpec params, CipherParameters param) + { + CipherParameters key; + + if (param instanceof ParametersWithIV) + { + key = ((ParametersWithIV)param).getParameters(); + if (params instanceof IvParameterSpec) + { + IvParameterSpec iv = (IvParameterSpec)params; + + ivParam = new ParametersWithIV(key, iv.getIV()); + param = ivParam; + } + // BEGIN android-removed + // else if (params instanceof GOST28147ParameterSpec) + // { + // // need to pick up IV and SBox. + // GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; + // + // param = new ParametersWithSBox(param, gost28147Param.getSbox()); + // + // if (gost28147Param.getIV() != null && ivLength != 0) + // { + // ivParam = new ParametersWithIV(key, gost28147Param.getIV()); + // param = ivParam; + // } + // } + // END android-removed + } + else + { + if (params instanceof IvParameterSpec) + { + IvParameterSpec iv = (IvParameterSpec)params; + + ivParam = new ParametersWithIV(param, iv.getIV()); + param = ivParam; + } + // BEGIN android-removed + // else if (params instanceof GOST28147ParameterSpec) + // { + // // need to pick up IV and SBox. + // GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; + // + // param = new ParametersWithSBox(param, gost28147Param.getSbox()); + // + // if (gost28147Param.getIV() != null && ivLength != 0) + // { + // param = new ParametersWithIV(param, gost28147Param.getIV()); + // } + // } + // END android-removed + } + return param; + } + protected void engineInit( int opmode, Key key, @@ -820,13 +1022,19 @@ public class BaseBlockCipher int outputOffset) throws ShortBufferException { + if (outputOffset + cipher.getUpdateOutputSize(inputLen) > output.length) + { + throw new ShortBufferException("output buffer too short for input."); + } + try { return cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); } catch (DataLengthException e) { - throw new ShortBufferException(e.getMessage()); + // should never occur + throw new IllegalStateException(e.toString()); } } @@ -873,10 +1081,15 @@ public class BaseBlockCipher int outputOffset) throws IllegalBlockSizeException, BadPaddingException, ShortBufferException { - try + int len = 0; + + if (outputOffset + engineGetOutputSize(inputLen) > output.length) { - int len = 0; + throw new ShortBufferException("output buffer too short for input."); + } + try + { if (inputLen != 0) { len = cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); @@ -886,7 +1099,7 @@ public class BaseBlockCipher } catch (OutputLengthException e) { - throw new ShortBufferException(e.getMessage()); + throw new IllegalBlockSizeException(e.getMessage()); } catch (DataLengthException e) { diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java index d014972e..f6076170 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java @@ -9,6 +9,8 @@ import java.util.Iterator; import java.util.Map; import javax.crypto.MacSpi; +import javax.crypto.SecretKey; +import javax.crypto.interfaces.PBEKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEParameterSpec; @@ -18,6 +20,9 @@ import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; // BEGIN android-removed // import org.bouncycastle.crypto.params.SkeinParameters; +// END android-removed +import org.bouncycastle.jcajce.PKCS12Key; +// BEGIN android-removed // import org.bouncycastle.jcajce.spec.SkeinParameterSpec; // END android-removed @@ -26,7 +31,7 @@ public class BaseMac { private Mac macEngine; - private int pbeType = PKCS12; + private int scheme = PKCS12; private int pbeHash = SHA1; private int keySize = 160; @@ -38,12 +43,12 @@ public class BaseMac protected BaseMac( Mac macEngine, - int pbeType, + int scheme, int pbeHash, int keySize) { this.macEngine = macEngine; - this.pbeType = pbeType; + this.scheme = scheme; this.pbeHash = pbeHash; this.keySize = keySize; } @@ -60,7 +65,54 @@ public class BaseMac throw new InvalidKeyException("key is null"); } - if (key instanceof BCPBEKey) + if (key instanceof PKCS12Key) + { + SecretKey k; + PBEParameterSpec pbeSpec; + + try + { + k = (SecretKey)key; + } + catch (Exception e) + { + throw new InvalidKeyException("PKCS12 requires a SecretKey/PBEKey"); + } + + try + { + pbeSpec = (PBEParameterSpec)params; + } + catch (Exception e) + { + throw new InvalidAlgorithmParameterException("PKCS12 requires a PBEParameterSpec"); + } + + if (k instanceof PBEKey && pbeSpec == null) + { + pbeSpec = new PBEParameterSpec(((PBEKey)k).getSalt(), ((PBEKey)k).getIterationCount()); + } + + int digest = SHA1; + int keySize = 160; + // BEGIN android-removed + // if (macEngine.getAlgorithmName().startsWith("GOST")) + // { + // digest = GOST3411; + // keySize = 256; + // } + // BEGIN android-changed + // Was: else if (macEngine.getAlgorithmName().startsWith("SHA256")) + if (macEngine.getAlgorithmName().startsWith("SHA256")) + // END android-changed + { + digest = SHA256; + keySize = 256; + } + // TODO: add correct handling for other digests + param = PBE.Util.makePBEMacParameters(k, PKCS12, digest, keySize, pbeSpec); + } + else if (key instanceof BCPBEKey) { BCPBEKey k = (BCPBEKey)key; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java index fba61b8d..ea3ac5b0 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java @@ -5,7 +5,6 @@ import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.Key; -import java.security.Provider; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; @@ -25,7 +24,8 @@ import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.StreamCipher; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; -import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jcajce.PKCS12Key; +import org.bouncycastle.jcajce.PKCS12KeyWithParameters; public class BaseStreamCipher extends BaseWrapCipher @@ -45,6 +45,8 @@ public class BaseStreamCipher }; private StreamCipher cipher; + private int keySizeInBits; + private int digest; private ParametersWithIV ivParam; private int ivLength = 0; @@ -56,8 +58,19 @@ public class BaseStreamCipher StreamCipher engine, int ivLength) { + this(engine, ivLength, -1, -1); + } + + protected BaseStreamCipher( + StreamCipher engine, + int ivLength, + int keySizeInBits, + int digest) + { cipher = engine; this.ivLength = ivLength; + this.keySizeInBits = keySizeInBits; + this.digest = digest; } protected int engineGetBlockSize() @@ -152,7 +165,18 @@ public class BaseStreamCipher throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption."); } - if (key instanceof BCPBEKey) + if (key instanceof PKCS12Key) + { + PKCS12Key k = (PKCS12Key)key; + pbeSpec = (PBEParameterSpec)params; + if (k instanceof PKCS12KeyWithParameters && pbeSpec == null) + { + pbeSpec = new PBEParameterSpec(((PKCS12KeyWithParameters)k).getSalt(), ((PKCS12KeyWithParameters)k).getIterationCount()); + } + + param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS12, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); + } + else if (key instanceof BCPBEKey) { BCPBEKey k = (BCPBEKey)key; @@ -187,6 +211,10 @@ public class BaseStreamCipher } else if (params == null) { + if (digest > 0) + { + throw new InvalidKeyException("Algorithm requires a PBE key"); + } param = new KeyParameter(key.getEncoded()); } else if (params instanceof IvParameterSpec) @@ -314,15 +342,21 @@ public class BaseStreamCipher int outputOffset) throws ShortBufferException { + if (outputOffset + inputLen > output.length) + { + throw new ShortBufferException("output buffer too short for input."); + } + try { - cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); + cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); - return inputLen; + return inputLen; } catch (DataLengthException e) { - throw new ShortBufferException(e.getMessage()); + // should never happen + throw new IllegalStateException(e.getMessage()); } } @@ -350,8 +384,14 @@ public class BaseStreamCipher int inputOffset, int inputLen, byte[] output, - int outputOffset) + int outputOffset) + throws ShortBufferException { + if (outputOffset + inputLen > output.length) + { + throw new ShortBufferException("output buffer too short for input."); + } + if (inputLen != 0) { cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java index a26d9807..ece0d146 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java @@ -8,9 +8,7 @@ import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; -import java.security.Provider; import java.security.SecureRandom; -import java.security.Security; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; @@ -40,6 +38,7 @@ import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.jcajce.util.BCJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.Arrays; public abstract class BaseWrapCipher extends CipherSpi @@ -97,7 +96,7 @@ public abstract class BaseWrapCipher protected byte[] engineGetIV() { - return (byte[])iv.clone(); + return Arrays.clone(iv); } protected int engineGetKeySize( diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java index c39a2d3d..8fead80a 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java @@ -1,7 +1,9 @@ package org.bouncycastle.jcajce.provider.symmetric.util; +import java.security.InvalidAlgorithmParameterException; import java.security.spec.AlgorithmParameterSpec; +import javax.crypto.SecretKey; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; @@ -176,6 +178,70 @@ public interface PBE } /** + * construct a key and iv (if necessary) suitable for use with a + * Cipher. + */ + public static CipherParameters makePBEParameters( + byte[] pbeKey, + int scheme, + int digest, + int keySize, + int ivSize, + AlgorithmParameterSpec spec, + String targetAlgorithm) + throws InvalidAlgorithmParameterException + { + if ((spec == null) || !(spec instanceof PBEParameterSpec)) + { + throw new InvalidAlgorithmParameterException("Need a PBEParameter spec with a PBE key."); + } + + PBEParameterSpec pbeParam = (PBEParameterSpec)spec; + PBEParametersGenerator generator = makePBEGenerator(scheme, digest); + byte[] key = pbeKey; + CipherParameters param; + +// if (pbeKey.shouldTryWrongPKCS12()) +// { +// key = new byte[2]; +// } + + generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount()); + + if (ivSize != 0) + { + param = generator.generateDerivedParameters(keySize, ivSize); + } + else + { + param = generator.generateDerivedParameters(keySize); + } + + if (targetAlgorithm.startsWith("DES")) + { + if (param instanceof ParametersWithIV) + { + KeyParameter kParam = (KeyParameter)((ParametersWithIV)param).getParameters(); + + DESParameters.setOddParity(kParam.getKey()); + } + else + { + KeyParameter kParam = (KeyParameter)param; + + DESParameters.setOddParity(kParam.getKey()); + } + } + + for (int i = 0; i != key.length; i++) + { + key[i] = 0; + } + + return param; + } + + /** * construct a key and iv (if necessary) suitable for use with a * Cipher. */ @@ -252,11 +318,6 @@ public interface PBE PBEParametersGenerator generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest()); byte[] key = pbeKey.getEncoded(); CipherParameters param; - - if (pbeKey.shouldTryWrongPKCS12()) - { - key = new byte[2]; - } generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount()); @@ -269,7 +330,36 @@ public interface PBE return param; } - + + /** + * generate a PBE based key suitable for a MAC algorithm, the + * key size is chosen according the MAC size, or the hashing algorithm, + * whichever is greater. + */ + public static CipherParameters makePBEMacParameters( + PBEKeySpec keySpec, + int type, + int hash, + int keySize) + { + PBEParametersGenerator generator = makePBEGenerator(type, hash); + byte[] key; + CipherParameters param; + + key = convertPassword(type, keySpec); + + generator.init(key, keySpec.getSalt(), keySpec.getIterationCount()); + + param = generator.generateDerivedMacParameters(keySize); + + for (int i = 0; i != key.length; i++) + { + key[i] = 0; + } + + return param; + } + /** * construct a key and iv (if necessary) suitable for use with a * Cipher. @@ -306,31 +396,30 @@ public interface PBE return param; } - /** * generate a PBE based key suitable for a MAC algorithm, the * key size is chosen according the MAC size, or the hashing algorithm, * whichever is greater. */ public static CipherParameters makePBEMacParameters( - PBEKeySpec keySpec, + SecretKey key, int type, int hash, - int keySize) + int keySize, + PBEParameterSpec pbeSpec) { PBEParametersGenerator generator = makePBEGenerator(type, hash); - byte[] key; CipherParameters param; - key = convertPassword(type, keySpec); + byte[] keyBytes = key.getEncoded(); - generator.init(key, keySpec.getSalt(), keySpec.getIterationCount()); + generator.init(key.getEncoded(), pbeSpec.getSalt(), pbeSpec.getIterationCount()); param = generator.generateDerivedMacParameters(keySize); - for (int i = 0; i != key.length; i++) + for (int i = 0; i != keyBytes.length; i++) { - key[i] = 0; + keyBytes[i] = 0; } return param; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/DigestFactory.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/DigestFactory.java index 19ca6b1d..ce8bb363 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/DigestFactory.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/DigestFactory.java @@ -17,6 +17,7 @@ import org.bouncycastle.crypto.Digest; // import org.bouncycastle.crypto.digests.SHA256Digest; // import org.bouncycastle.crypto.digests.SHA384Digest; // import org.bouncycastle.crypto.digests.SHA512Digest; +// import org.bouncycastle.crypto.digests.SHA512tDigest; // END android-removed // BEGIN android-added import org.bouncycastle.crypto.digests.AndroidDigestFactory; @@ -31,7 +32,11 @@ public class DigestFactory private static Set sha256 = new HashSet(); private static Set sha384 = new HashSet(); private static Set sha512 = new HashSet(); - + // BEGIN android-removed + // private static Set sha512_224 = new HashSet(); + // private static Set sha512_256 = new HashSet(); + // END android-removed + private static Map oids = new HashMap(); static @@ -59,6 +64,16 @@ public class DigestFactory sha512.add("SHA-512"); sha512.add(NISTObjectIdentifiers.id_sha512.getId()); + // BEGIN android-removed + // sha512_224.add("SHA512(224)"); + // sha512_224.add("SHA-512(224)"); + // sha512_224.add(NISTObjectIdentifiers.id_sha512_224.getId()); + + // sha512_256.add("SHA512(256)"); + // sha512_256.add("SHA-512(256)"); + // sha512_256.add(NISTObjectIdentifiers.id_sha512_256.getId()); + // END android-removed + oids.put("MD5", PKCSObjectIdentifiers.md5); oids.put(PKCSObjectIdentifiers.md5.getId(), PKCSObjectIdentifiers.md5); @@ -80,7 +95,15 @@ public class DigestFactory oids.put("SHA512", NISTObjectIdentifiers.id_sha512); oids.put("SHA-512", NISTObjectIdentifiers.id_sha512); - oids.put(NISTObjectIdentifiers.id_sha512.getId(), NISTObjectIdentifiers.id_sha512); + oids.put(NISTObjectIdentifiers.id_sha512.getId(), NISTObjectIdentifiers.id_sha512); + + oids.put("SHA512(224)", NISTObjectIdentifiers.id_sha512_224); + oids.put("SHA-512(224)", NISTObjectIdentifiers.id_sha512_224); + oids.put(NISTObjectIdentifiers.id_sha512_224.getId(), NISTObjectIdentifiers.id_sha512_224); + + oids.put("SHA512(256)", NISTObjectIdentifiers.id_sha512_256); + oids.put("SHA-512(256)", NISTObjectIdentifiers.id_sha512_256); + oids.put(NISTObjectIdentifiers.id_sha512_256.getId(), NISTObjectIdentifiers.id_sha512_256); } public static Digest getDigest( @@ -124,7 +147,17 @@ public class DigestFactory return AndroidDigestFactory.getSHA512(); // END android-changed } - + // BEGIN android-removed + // if (sha512_224.contains(digestName)) + // { + // return new SHA512tDigest(224); + // } + // if (sha512_256.contains(digestName)) + // { + // return new SHA512tDigest(256); + // } + // END android-removed + return null; } @@ -137,6 +170,10 @@ public class DigestFactory || (sha256.contains(digest1) && sha256.contains(digest2)) || (sha384.contains(digest1) && sha384.contains(digest2)) || (sha512.contains(digest1) && sha512.contains(digest2)) + // BEGIN android-removed + // || (sha512_224.contains(digest1) && sha512_224.contains(digest2)) + // || (sha512_256.contains(digest1) && sha512_256.contains(digest2)) + // END android-removed || (md5.contains(digest1) && md5.contains(digest2)); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java index 09a9bd0b..df0c1454 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java @@ -18,7 +18,7 @@ public class PBKDF2KeySpec * @param password password to use as the seed of the PBE key generator. * @param salt salt to use in the generator, * @param iterationCount iteration count to use in the generator. - * @param keySize size of the key to be generated. + * @param keySize size of the key to be generated (in bits). * @param prf identifier and parameters for the PRF algorithm to use. */ public PBKDF2KeySpec(char[] password, byte[] salt, int iterationCount, int keySize, AlgorithmIdentifier prf) diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java new file mode 100644 index 00000000..d8135310 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/UserKeyingMaterialSpec.java @@ -0,0 +1,21 @@ +package org.bouncycastle.jcajce.spec; + +import java.security.spec.AlgorithmParameterSpec; + +import org.bouncycastle.util.Arrays; + +public class UserKeyingMaterialSpec + implements AlgorithmParameterSpec +{ + private final byte[] userKeyingMaterial; + + public UserKeyingMaterialSpec(byte[] userKeyingMaterial) + { + this.userKeyingMaterial = Arrays.clone(userKeyingMaterial); + } + + public byte[] getUserKeyingMaterial() + { + return Arrays.clone(userKeyingMaterial); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java new file mode 100644 index 00000000..4a1a92a5 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java @@ -0,0 +1,68 @@ +/***************************************************************/ +/****** DO NOT EDIT THIS CLASS bc-java SOURCE FILE ******/ +/***************************************************************/ +package org.bouncycastle.jcajce.util; + +import java.io.IOException; +import java.security.AlgorithmParameters; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Primitive; + +/** + * General JCA/JCE utility methods. + */ +public class AlgorithmParametersUtils +{ + + + private AlgorithmParametersUtils() + { + + } + + /** + * Extract an ASN.1 encodable from an AlgorithmParameters object. + * + * @param params the object to get the encoding used to create the return value. + * @return an ASN.1 object representing the primitives making up the params parameter. + * @throws IOException if an encoding cannot be extracted. + */ + public static ASN1Encodable extractParameters(AlgorithmParameters params) + throws IOException + { + // we try ASN.1 explicitly first just in case and then role back to the default. + ASN1Encodable asn1Params; + try + { + asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1")); + } + catch (Exception ex) + { + asn1Params = ASN1Primitive.fromByteArray(params.getEncoded()); + } + + return asn1Params; + } + + /** + * Load an AlgorithmParameters object with the passed in ASN.1 encodable - if possible. + * + * @param params the AlgorithmParameters object to be initialised. + * @param sParams the ASN.1 encodable to initialise params with. + * @throws IOException if the parameters cannot be initialised. + */ + public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams) + throws IOException + { + // we try ASN.1 explicitly first just in case and then role back to the default. + try + { + params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1"); + } + catch (Exception ex) + { + params.init(sParams.toASN1Primitive().getEncoded()); + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceUtils.java index a082d897..51486012 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceUtils.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceUtils.java @@ -32,6 +32,7 @@ public class JcaJceUtils * @param params the object to get the encoding used to create the return value. * @return an ASN.1 object representing the primitives making up the params parameter. * @throws IOException if an encoding cannot be extracted. + * @deprecated use AlgorithmParametersUtils.extractParameters(AlgorithmParameters params) */ public static ASN1Encodable extractParameters(AlgorithmParameters params) throws IOException @@ -56,6 +57,7 @@ public class JcaJceUtils * @param params the AlgorithmParameters object to be initialised. * @param sParams the ASN.1 encodable to initialise params with. * @throws IOException if the parameters cannot be initialised. + * @deprecated use AlgorithmParametersUtils.loadParameters(AlgorithmParameters params, ASN1Encodable sParams) */ public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams) throws IOException @@ -76,6 +78,7 @@ public class JcaJceUtils * * @param digestAlgOID the OID of the digest algorithm of interest. * @return a string representing the standard name - the OID as a string if none available. + * @deprecated use MessageDigestUtils,getDigestName() */ public static String getDigestAlgName( ASN1ObjectIdentifier digestAlgOID) diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java new file mode 100644 index 00000000..80ce603f --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java @@ -0,0 +1,63 @@ +package org.bouncycastle.jcajce.util; + +import java.util.HashMap; +import java.util.Map; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +// BEGIN android-removed +// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +// import org.bouncycastle.asn1.gnu.GNUObjectIdentifiers; +// import org.bouncycastle.asn1.iso.ISOIECObjectIdentifiers; +// END android-removed +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +// BEGIN android-removed +// import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; +// END android-removed + +public class MessageDigestUtils +{ + private static Map<ASN1ObjectIdentifier, String> digestOidMap = new HashMap<ASN1ObjectIdentifier, String>(); + + static + { + // BEGIN android-removed + // digestOidMap.put(PKCSObjectIdentifiers.md2, "MD2"); + // digestOidMap.put(PKCSObjectIdentifiers.md4, "MD4"); + // END android-removed + digestOidMap.put(PKCSObjectIdentifiers.md5, "MD5"); + digestOidMap.put(OIWObjectIdentifiers.idSHA1, "SHA-1"); + digestOidMap.put(NISTObjectIdentifiers.id_sha224, "SHA-224"); + digestOidMap.put(NISTObjectIdentifiers.id_sha256, "SHA-256"); + digestOidMap.put(NISTObjectIdentifiers.id_sha384, "SHA-384"); + digestOidMap.put(NISTObjectIdentifiers.id_sha512, "SHA-512"); + // BEGIN android-removed + // digestOidMap.put(TeleTrusTObjectIdentifiers.ripemd128, "RIPEMD-128"); + // digestOidMap.put(TeleTrusTObjectIdentifiers.ripemd160, "RIPEMD-160"); + // digestOidMap.put(TeleTrusTObjectIdentifiers.ripemd256, "RIPEMD-128"); + // digestOidMap.put(ISOIECObjectIdentifiers.ripemd128, "RIPEMD-128"); + // digestOidMap.put(ISOIECObjectIdentifiers.ripemd160, "RIPEMD-160"); + // digestOidMap.put(CryptoProObjectIdentifiers.gostR3411, "GOST3411"); + // digestOidMap.put(GNUObjectIdentifiers.Tiger_192, "Tiger"); + // digestOidMap.put(ISOIECObjectIdentifiers.whirlpool, "Whirlpool"); + // END android-removed + } + + /** + * Attempt to find a standard JCA name for the digest represented by the passed in OID. + * + * @param digestAlgOID the OID of the digest algorithm of interest. + * @return a string representing the standard name - the OID as a string if none available. + */ + public static String getDigestName(ASN1ObjectIdentifier digestAlgOID) + { + String name = (String)digestOidMap.get(digestAlgOID); // for pre 1.5 JDK + if (name != null) + { + return name; + } + + return digestAlgOID.getId(); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java b/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java index 36706950..0c41c882 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java @@ -363,7 +363,7 @@ public class PKCS10CertificationRequest try { ASN1Sequence seq = (ASN1Sequence)ASN1Primitive.fromByteArray(key.getEncoded()); - this.reqInfo = new CertificationRequestInfo(subject, new SubjectPublicKeyInfo(seq), attributes); + this.reqInfo = new CertificationRequestInfo(subject, SubjectPublicKeyInfo.getInstance(seq), attributes); } catch (IOException e) { @@ -414,7 +414,7 @@ public class PKCS10CertificationRequest try { - X509EncodedKeySpec xspec = new X509EncodedKeySpec(new DERBitString(subjectPKInfo).getBytes()); + X509EncodedKeySpec xspec = new X509EncodedKeySpec(new DERBitString(subjectPKInfo).getOctets()); AlgorithmIdentifier keyAlg = subjectPKInfo.getAlgorithm(); try { @@ -432,9 +432,9 @@ public class PKCS10CertificationRequest // // try an alternate // - if (keyAlgorithms.get(keyAlg.getObjectId()) != null) + if (keyAlgorithms.get(keyAlg.getAlgorithm()) != null) { - String keyAlgorithm = (String)keyAlgorithms.get(keyAlg.getObjectId()); + String keyAlgorithm = (String)keyAlgorithms.get(keyAlg.getAlgorithm()); if (provider == null) { @@ -507,9 +507,9 @@ public class PKCS10CertificationRequest // // try an alternate // - if (oids.get(sigAlgId.getObjectId()) != null) + if (oids.get(sigAlgId.getAlgorithm()) != null) { - String signatureAlgorithm = (String)oids.get(sigAlgId.getObjectId()); + String signatureAlgorithm = (String)oids.get(sigAlgId.getAlgorithm()); if (provider == null) { @@ -539,7 +539,7 @@ public class PKCS10CertificationRequest throw new SignatureException("exception encoding TBS cert request - " + e); } - return sig.verify(sigBits.getBytes()); + return sig.verify(sigBits.getOctets()); } /** @@ -596,14 +596,14 @@ public class PKCS10CertificationRequest if (params != null && !DERNull.INSTANCE.equals(params)) { - if (sigAlgId.getObjectId().equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) + if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) { RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params); - return getDigestAlgName(rsaParams.getHashAlgorithm().getObjectId()) + "withRSAandMGF1"; + return getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "withRSAandMGF1"; } } - return sigAlgId.getObjectId().getId(); + return sigAlgId.getAlgorithm().getId(); } private static String getDigestAlgName( diff --git a/bcprov/src/main/java/org/bouncycastle/jce/netscape/NetscapeCertRequest.java b/bcprov/src/main/java/org/bouncycastle/jce/netscape/NetscapeCertRequest.java index 39dd35ad..f8a1a6fd 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/netscape/NetscapeCertRequest.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/netscape/NetscapeCertRequest.java @@ -86,9 +86,8 @@ public class NetscapeCertRequest + spkac.size()); } - sigAlg = new AlgorithmIdentifier((ASN1Sequence)spkac - .getObjectAt(1)); - sigBits = ((DERBitString)spkac.getObjectAt(2)).getBytes(); + sigAlg = AlgorithmIdentifier.getInstance(spkac.getObjectAt(1)); + sigBits = ((DERBitString)spkac.getObjectAt(2)).getOctets(); // // PublicKeyAndChallenge ::= SEQUENCE { @@ -110,14 +109,13 @@ public class NetscapeCertRequest //could potentially alter the bytes content = new DERBitString(pkac); - SubjectPublicKeyInfo pubkeyinfo = new SubjectPublicKeyInfo( - (ASN1Sequence)pkac.getObjectAt(0)); + SubjectPublicKeyInfo pubkeyinfo = SubjectPublicKeyInfo.getInstance(pkac.getObjectAt(0)); X509EncodedKeySpec xspec = new X509EncodedKeySpec(new DERBitString( pubkeyinfo).getBytes()); - keyAlg = pubkeyinfo.getAlgorithmId(); - pubkey = KeyFactory.getInstance(keyAlg.getObjectId().getId(), "BC") + keyAlg = pubkeyinfo.getAlgorithm(); + pubkey = KeyFactory.getInstance(keyAlg.getAlgorithm().getId(), "BC") .generatePublic(xspec); } @@ -205,7 +203,7 @@ public class NetscapeCertRequest // Verify the signature .. shows the response was generated // by someone who knew the associated private key // - Signature sig = Signature.getInstance(sigAlg.getObjectId().getId(), + Signature sig = Signature.getInstance(sigAlg.getAlgorithm().getId(), "BC"); sig.initVerify(pubkey); sig.update(content.getBytes()); diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java index 82c6a5a8..00f23e8d 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java @@ -44,7 +44,7 @@ import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; public final class BouncyCastleProvider extends Provider implements ConfigurableProvider { - private static String info = "BouncyCastle Security Provider v1.52"; + private static String info = "BouncyCastle Security Provider v1.54"; public static final String PROVIDER_NAME = "BC"; @@ -74,8 +74,8 @@ public final class BouncyCastleProvider extends Provider // BEGIN android-removed // "AES", "ARC4", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede", // "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA", "Noekeon", "RC2", "RC5", - // "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "TEA", "Twofish", "Threefish", - // "VMPC", "VMPCKSA3", "XTEA", "XSalsa20" + // "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "SM4", "TEA", "Twofish", "Threefish", + // "VMPC", "VMPCKSA3", "XTEA", "XSalsa20", "OpenSSLPBKDF" // END android-removed // BEGIN android-added "AES", "ARC4", "Blowfish", "DES", "DESede", "RC2", "Twofish", @@ -116,7 +116,8 @@ public final class BouncyCastleProvider extends Provider private static final String[] DIGESTS = { // BEGIN android-removed - // "GOST3411", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "Skein", "SM3", "Tiger", "Whirlpool" + // "GOST3411", "Keccak", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224", + // "SHA256", "SHA384", "SHA512", "SHA3", "Skein", "SM3", "Tiger", "Whirlpool", "Blake2b" // END android-removed // BEGIN android-added "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", @@ -139,7 +140,7 @@ public final class BouncyCastleProvider extends Provider */ public BouncyCastleProvider() { - super(PROVIDER_NAME, 1.52, info); + super(PROVIDER_NAME, 1.54, info); AccessController.doPrivileged(new PrivilegedAction() { @@ -276,6 +277,12 @@ public final class BouncyCastleProvider extends Provider put(key, value); } + public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className) + { + addAlgorithm(type + "." + oid, className); + addAlgorithm(type + ".OID." + oid, className); + } + public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter) { keyInfoConverters.put(oid, keyInfoConverter); diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java index f53f3ac7..b6a9d6a5 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java @@ -35,6 +35,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; + import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1Encodable; @@ -720,14 +721,7 @@ class CertPathValidatorUtilities for (int j = 0; j < genNames.length; j++) { - // BEGIN android-removed - // PKIXCRLStore store = namedCRLStoreMap.get(genNames[i]); - // END android-removed - // BEGIN android-added - // Seems like a bug, unless there should be a guarantee that j < i, - // However, it's breaking the tests. PKIXCRLStore store = namedCRLStoreMap.get(genNames[j]); - // END android-added if (store != null) { stores.add(store); @@ -900,25 +894,16 @@ class CertPathValidatorUtilities { return; } - // BEGIN android-removed - // X500Name certIssuer = X500Name.getInstance(crl_entry.getCertificateIssuer().getEncoded()); - // END android-removed - // BEGIN android-added - // The original code throws null pointer exception for OpenSSLX509CRL, - // which uses the implementation for getCertificateIssuer() in X509CRL, method - // whose reference implementation has the following JavaDoc: "If the certificate - // issuer is also the CRL issuer, this method returns null." - X500Name certIssuer = null; - X500Principal certificateIssuerPrincipal = crl_entry.getCertificateIssuer(); - if (certificateIssuerPrincipal != null) { - certIssuer = X500Name.getInstance(certificateIssuerPrincipal.getEncoded()); - } - // END android-added - - if (certIssuer == null) + X500Principal certificateIssuer = crl_entry.getCertificateIssuer(); + X500Name certIssuer; + if (certificateIssuer == null) { certIssuer = PrincipalUtils.getIssuerPrincipal(crl); } + else + { + certIssuer = X500Name.getInstance(certificateIssuer.getEncoded()); + } if (! PrincipalUtils.getEncodedIssuerPrincipal(cert).equals(certIssuer)) { diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java index f5af73a8..20ca6f27 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java @@ -39,6 +39,7 @@ import org.bouncycastle.jce.interfaces.ECPointEncoder; import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.util.Strings; public class JCEECPrivateKey implements ECPrivateKey, org.bouncycastle.jce.interfaces.ECPrivateKey, PKCS12BagAttributeCarrier, ECPointEncoder @@ -432,7 +433,7 @@ public class JCEECPrivateKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("EC Private Key").append(nl); buf.append(" S: ").append(this.d.toString(16)).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java index 10dfb48e..94fb7289 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java @@ -46,6 +46,7 @@ import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.custom.sec.SecP256K1Point; import org.bouncycastle.math.ec.custom.sec.SecP256R1Point; +import org.bouncycastle.util.Strings; public class JCEECPublicKey implements ECPublicKey, org.bouncycastle.jce.interfaces.ECPublicKey, ECPointEncoder @@ -191,7 +192,8 @@ public class JCEECPublicKey private void populateFromPubKeyInfo(SubjectPublicKeyInfo info) { - // if (info.getAlgorithmId().getObjectId().equals(CryptoProObjectIdentifiers.gostR3410_2001)) + // BEGIN android-removed + // if (info.getAlgorithmId().getAlgorithm().equals(CryptoProObjectIdentifiers.gostR3410_2001)) // { // DERBitString bits = info.getPublicKeyData(); // ASN1OctetString key; @@ -478,7 +480,7 @@ public class JCEECPublicKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("EC Public Key").append(nl); buf.append(" X: ").append(this.q.getAffineXCoord().toBigInteger().toString(16)).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCERSAPrivateCrtKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCERSAPrivateCrtKey.java index f9bb5dd3..40f007f3 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCERSAPrivateCrtKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCERSAPrivateCrtKey.java @@ -12,6 +12,7 @@ import org.bouncycastle.asn1.pkcs.RSAPrivateKey; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.bouncycastle.util.Strings; /** * A provider representation for a RSA private key, with CRT factors included. @@ -224,7 +225,7 @@ public class JCERSAPrivateCrtKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("RSA Private CRT Key").append(nl); buf.append(" modulus: ").append(this.getModulus().toString(16)).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCERSAPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCERSAPublicKey.java index a09295d5..adf0e3e8 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCERSAPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCERSAPublicKey.java @@ -5,14 +5,13 @@ import java.math.BigInteger; import java.security.interfaces.RSAPublicKey; import java.security.spec.RSAPublicKeySpec; -import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; +import org.bouncycastle.util.Strings; public class JCERSAPublicKey implements RSAPublicKey @@ -48,7 +47,7 @@ public class JCERSAPublicKey { try { - RSAPublicKeyStructure pubKey = new RSAPublicKeyStructure((ASN1Sequence)info.parsePublicKey()); + org.bouncycastle.asn1.pkcs.RSAPublicKey pubKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(info.parsePublicKey()); this.modulus = pubKey.getModulus(); this.publicExponent = pubKey.getPublicExponent(); @@ -91,7 +90,7 @@ public class JCERSAPublicKey public byte[] getEncoded() { - return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPublicKeyStructure(getModulus(), getPublicExponent())); + return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new org.bouncycastle.asn1.pkcs.RSAPublicKey(getModulus(), getPublicExponent())); } public int hashCode() @@ -120,7 +119,7 @@ public class JCERSAPublicKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("RSA Public Key").append(nl); buf.append(" modulus: ").append(this.getModulus().toString(16)).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPublicKey.java index 80bbf3c5..95a1ad74 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPublicKey.java @@ -18,6 +18,7 @@ import org.bouncycastle.asn1.x509.DSAParameter; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.DSAPublicKeyParameters; +import org.bouncycastle.util.Strings; public class JDKDSAPublicKey implements DSAPublicKey @@ -126,7 +127,7 @@ public class JDKDSAPublicKey public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append("DSA Public Key").append(nl); buf.append(" y: ").append(this.getY().toString(16)).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java index b7133951..dfe9cef5 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java @@ -44,16 +44,6 @@ public class PKIXCertPathBuilderSpi public CertPathBuilderResult engineBuild(CertPathParameters params) throws CertPathBuilderException, InvalidAlgorithmParameterException { - if (!(params instanceof PKIXBuilderParameters) - && !(params instanceof ExtendedPKIXBuilderParameters) - && !(params instanceof PKIXExtendedBuilderParameters)) - { - throw new InvalidAlgorithmParameterException( - "Parameters must be an instance of " - + PKIXBuilderParameters.class.getName() + " or " - + PKIXExtendedBuilderParameters.class.getName() + "."); - } - PKIXExtendedBuilderParameters paramsPKIX; if (params instanceof PKIXBuilderParameters) { @@ -81,10 +71,17 @@ public class PKIXCertPathBuilderSpi paramsPKIX = paramsBldrPKIXBldr.build(); } - else + else if (params instanceof PKIXExtendedBuilderParameters) { paramsPKIX = (PKIXExtendedBuilderParameters)params; } + else + { + throw new InvalidAlgorithmParameterException( + "Parameters must be an instance of " + + PKIXBuilderParameters.class.getName() + " or " + + PKIXExtendedBuilderParameters.class.getName() + "."); + } Collection targets; Iterator targetIter; diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java index 3fdedad0..5d49d889 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java @@ -25,6 +25,7 @@ import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters; import org.bouncycastle.jcajce.PKIXExtendedParameters; import org.bouncycastle.jcajce.util.BCJcaJceHelper; @@ -56,12 +57,6 @@ public class PKIXCertPathValidatorSpi throws CertPathValidatorException, InvalidAlgorithmParameterException { - if (!(params instanceof CertPathParameters)) - { - throw new InvalidAlgorithmParameterException("Parameters must be a " + PKIXParameters.class.getName() - + " instance."); - } - PKIXExtendedParameters paramsPKIX; if (params instanceof PKIXParameters) { @@ -81,18 +76,14 @@ public class PKIXCertPathValidatorSpi { paramsPKIX = ((PKIXExtendedBuilderParameters)params).getBaseParameters(); } - // BEGIN android-changed - // else else if (params instanceof PKIXExtendedParameters) - // END android-changed { paramsPKIX = (PKIXExtendedParameters)params; } - // BEGIN android-added - else { - throw new InvalidAlgorithmParameterException("Expecting PKIX algorithm parameters"); + else + { + throw new InvalidAlgorithmParameterException("Parameters must be a " + PKIXParameters.class.getName() + " instance."); } - // END android-added if (paramsPKIX.getTrustAnchors() == null) { @@ -112,7 +103,7 @@ public class PKIXCertPathValidatorSpi if (certs.isEmpty()) { - throw new CertPathValidatorException("Certification path is empty.", null, certPath, 0); + throw new CertPathValidatorException("Certification path is empty.", null, certPath, -1); } // BEGIN android-added { @@ -476,6 +467,7 @@ public class PKIXCertPathValidatorSpi criticalExtensions.remove(RFC3280CertPathUtilities.SUBJECT_ALTERNATIVE_NAME); criticalExtensions.remove(RFC3280CertPathUtilities.NAME_CONSTRAINTS); criticalExtensions.remove(RFC3280CertPathUtilities.CRL_DISTRIBUTION_POINTS); + criticalExtensions.remove(Extension.extendedKeyUsage.getId()); } else { diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java index 7e76a897..d5e23382 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java @@ -24,6 +24,7 @@ import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.TBSCertList; import org.bouncycastle.asn1.x509.X509Extension; +import org.bouncycastle.util.Strings; /** * The following extensions are listed in RFC 2459 as relevant to CRL Entries @@ -259,7 +260,7 @@ public class X509CRLEntryObject extends X509CRLEntry public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append(" userCertificate: ").append(this.getSerialNumber()).append(nl); buf.append(" revocationDate: ").append(this.getRevocationDate()).append(nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java index c9ee77c8..b6885ace 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java @@ -6,6 +6,7 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; +import java.security.Provider; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; @@ -41,6 +42,7 @@ import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.IssuingDistributionPoint; import org.bouncycastle.asn1.x509.TBSCertList; import org.bouncycastle.jce.X509Principal; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; /** @@ -201,21 +203,45 @@ public class X509CRLObject } public void verify(PublicKey key) - throws CRLException, NoSuchAlgorithmException, - InvalidKeyException, NoSuchProviderException, SignatureException + throws CRLException, NoSuchAlgorithmException, + InvalidKeyException, NoSuchProviderException, SignatureException { - verify(key, BouncyCastleProvider.PROVIDER_NAME); + Signature sig; + + try + { + sig = Signature.getInstance(getSigAlgName(), BouncyCastleProvider.PROVIDER_NAME); + } + catch (Exception e) + { + sig = Signature.getInstance(getSigAlgName()); + } + + doVerify(key, sig); } public void verify(PublicKey key, String sigProvider) throws CRLException, NoSuchAlgorithmException, - InvalidKeyException, NoSuchProviderException, SignatureException + InvalidKeyException, NoSuchProviderException, SignatureException { - if (!c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature())) + Signature sig; + + if (sigProvider != null) { - throw new CRLException("Signature algorithm on CertificateList does not match TBSCertList."); + sig = Signature.getInstance(getSigAlgName(), sigProvider); + } + else + { + sig = Signature.getInstance(getSigAlgName()); } + doVerify(key, sig); + } + + public void verify(PublicKey key, Provider sigProvider) + throws CRLException, NoSuchAlgorithmException, + InvalidKeyException, SignatureException + { Signature sig; if (sigProvider != null) @@ -227,6 +253,18 @@ public class X509CRLObject sig = Signature.getInstance(getSigAlgName()); } + doVerify(key, sig); + } + + private void doVerify(PublicKey key, Signature sig) + throws CRLException, NoSuchAlgorithmException, + InvalidKeyException, SignatureException + { + if (!c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature())) + { + throw new CRLException("Signature algorithm on CertificateList does not match TBSCertList."); + } + sig.initVerify(key); sig.update(this.getTBSCertList()); @@ -353,7 +391,7 @@ public class X509CRLObject public byte[] getSignature() { - return c.getSignature().getBytes(); + return c.getSignature().getOctets(); } public String getSigAlgName() @@ -388,7 +426,7 @@ public class X509CRLObject public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append(" Version: ").append(this.getVersion()).append( nl); diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CertificateObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CertificateObject.java index 0ae61d23..09703f4c 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CertificateObject.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CertificateObject.java @@ -32,6 +32,7 @@ import java.util.Set; import javax.security.auth.x500.X500Principal; +import org.bouncycastle.asn1.ASN1BitString; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1InputStream; @@ -65,6 +66,7 @@ import org.bouncycastle.jce.X509Principal; import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Integers; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; public class X509CertificateObject @@ -104,7 +106,7 @@ public class X509CertificateObject byte[] bytes = this.getExtensionBytes("2.5.29.15"); if (bytes != null) { - DERBitString bits = DERBitString.getInstance(ASN1Primitive.fromByteArray(bytes)); + ASN1BitString bits = DERBitString.getInstance(ASN1Primitive.fromByteArray(bytes)); bytes = bits.getBytes(); int length = (bytes.length * 8) - bits.getPadBits(); @@ -234,7 +236,7 @@ public class X509CertificateObject public byte[] getSignature() { - return c.getSignature().getBytes(); + return c.getSignature().getOctets(); } /** @@ -664,7 +666,7 @@ public class X509CertificateObject public String toString() { StringBuffer buf = new StringBuffer(); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); buf.append(" [0] Version: ").append(this.getVersion()).append(nl); buf.append(" SerialNumber: ").append(this.getSerialNumber()).append(nl); @@ -783,12 +785,42 @@ public class X509CertificateObject throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { - String sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm()); - Signature signature = Signature.getInstance(sigName, sigProvider); + String sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm()); + Signature signature; + + if (sigProvider != null) + { + signature = Signature.getInstance(sigName, sigProvider); + } + else + { + signature = Signature.getInstance(sigName); + } checkSignature(key, signature); } + public final void verify( + PublicKey key, + Provider sigProvider) + throws CertificateException, NoSuchAlgorithmException, + InvalidKeyException, SignatureException + { + String sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm()); + Signature signature; + + if (sigProvider != null) + { + signature = Signature.getInstance(sigName, sigProvider); + } + else + { + signature = Signature.getInstance(sigName); + } + + checkSignature(key, signature); + } + private void checkSignature( PublicKey key, Signature signature) diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java index c1b5ccc6..36aa595e 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java @@ -1,6 +1,7 @@ package org.bouncycastle.jce.spec; import java.math.BigInteger; +import java.security.spec.ECField; import java.security.spec.ECFieldF2m; import java.security.spec.ECFieldFp; import java.security.spec.ECPoint; @@ -8,6 +9,10 @@ import java.security.spec.EllipticCurve; import org.bouncycastle.math.ec.ECAlgorithms; import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.field.FiniteField; +import org.bouncycastle.math.field.Polynomial; +import org.bouncycastle.math.field.PolynomialExtensionField; +import org.bouncycastle.util.Arrays; /** * specification signifying that the curve parameters can also be @@ -22,29 +27,24 @@ public class ECNamedCurveSpec ECCurve curve, byte[] seed) { - if (ECAlgorithms.isFpCurve(curve)) + ECField field = convertField(curve.getField()); + BigInteger a = curve.getA().toBigInteger(), b = curve.getB().toBigInteger(); + return new EllipticCurve(field, a, b, seed); + } + + private static ECField convertField(FiniteField field) + { + if (ECAlgorithms.isFpField(field)) { - return new EllipticCurve(new ECFieldFp(curve.getField().getCharacteristic()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), seed); + return new ECFieldFp(field.getCharacteristic()); } - else + else //if (ECAlgorithms.isF2mField(curveField)) { - ECCurve.F2m curveF2m = (ECCurve.F2m)curve; - int ks[]; - - if (curveF2m.isTrinomial()) - { - ks = new int[] { curveF2m.getK1() }; - - return new EllipticCurve(new ECFieldF2m(curveF2m.getM(), ks), curve.getA().toBigInteger(), curve.getB().toBigInteger(), seed); - } - else - { - ks = new int[] { curveF2m.getK3(), curveF2m.getK2(), curveF2m.getK1() }; - - return new EllipticCurve(new ECFieldF2m(curveF2m.getM(), ks), curve.getA().toBigInteger(), curve.getB().toBigInteger(), seed); - } + Polynomial poly = ((PolynomialExtensionField)field).getMinimalPolynomial(); + int[] exponents = poly.getExponentsPresent(); + int[] ks = Arrays.reverse(Arrays.copyOfRange(exponents, 1, exponents.length - 1)); + return new ECFieldF2m(poly.getDegree(), ks); } - } private static ECPoint convertPoint( diff --git a/bcprov/src/main/java/org/bouncycastle/math/Primes.java b/bcprov/src/main/java/org/bouncycastle/math/Primes.java new file mode 100644 index 00000000..dc4c017c --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/math/Primes.java @@ -0,0 +1,674 @@ +package org.bouncycastle.math; + +import java.math.BigInteger; +import java.security.SecureRandom; + +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.BigIntegers; + +/** + * Utility methods for generating primes and testing for primality. + */ +public abstract class Primes +{ + public static final int SMALL_FACTOR_LIMIT = 211; + + private static final BigInteger ONE = BigInteger.valueOf(1); + private static final BigInteger TWO = BigInteger.valueOf(2); + private static final BigInteger THREE = BigInteger.valueOf(3); + + /** + * Used to return the output from the + * {@linkplain Primes#enhancedMRProbablePrimeTest(BigInteger, SecureRandom, int) Enhanced + * Miller-Rabin Probabilistic Primality Test} + */ + public static class MROutput + { + private static MROutput probablyPrime() + { + return new MROutput(false, null); + } + + private static MROutput provablyCompositeWithFactor(BigInteger factor) + { + return new MROutput(true, factor); + } + + private static MROutput provablyCompositeNotPrimePower() + { + return new MROutput(true, null); + } + + private boolean provablyComposite; + private BigInteger factor; + + private MROutput(boolean provablyComposite, BigInteger factor) + { + this.provablyComposite = provablyComposite; + this.factor = factor; + } + + public BigInteger getFactor() + { + return factor; + } + + public boolean isProvablyComposite() + { + return provablyComposite; + } + + public boolean isNotPrimePower() + { + return provablyComposite && factor == null; + } + } + + /** + * Used to return the output from the + * {@linkplain Primes#generateSTRandomPrime(Digest, int, byte[]) Shawe-Taylor Random_Prime + * Routine} + */ + public static class STOutput + { + private BigInteger prime; + private byte[] primeSeed; + private int primeGenCounter; + + private STOutput(BigInteger prime, byte[] primeSeed, int primeGenCounter) + { + this.prime = prime; + this.primeSeed = primeSeed; + this.primeGenCounter = primeGenCounter; + } + + public BigInteger getPrime() + { + return prime; + } + + public byte[] getPrimeSeed() + { + return primeSeed; + } + + public int getPrimeGenCounter() + { + return primeGenCounter; + } + } + + /** + * FIPS 186-4 C.6 Shawe-Taylor Random_Prime Routine + * + * Construct a provable prime number using a hash function. + * + * @param hash + * the {@link Digest} instance to use (as "Hash()"). Cannot be null. + * @param length + * the length (in bits) of the prime to be generated. Must be at least 2. + * @param inputSeed + * the seed to be used for the generation of the requested prime. Cannot be null or + * empty. + * @return an {@link STOutput} instance containing the requested prime. + */ + public static STOutput generateSTRandomPrime(Digest hash, int length, byte[] inputSeed) + { + if (hash == null) + { + throw new IllegalArgumentException("'hash' cannot be null"); + } + if (length < 2) + { + throw new IllegalArgumentException("'length' must be >= 2"); + } + if (inputSeed == null || inputSeed.length == 0) + { + throw new IllegalArgumentException("'inputSeed' cannot be null or empty"); + } + + return implSTRandomPrime(hash, length, Arrays.clone(inputSeed)); + } + + /** + * FIPS 186-4 C.3.2 Enhanced Miller-Rabin Probabilistic Primality Test + * + * Run several iterations of the Miller-Rabin algorithm with randomly-chosen bases. This is an + * alternative to {@link #isMRProbablePrime(BigInteger, SecureRandom, int)} that provides more + * information about a composite candidate, which may be useful when generating or validating + * RSA moduli. + * + * @param candidate + * the {@link BigInteger} instance to test for primality. + * @param random + * the source of randomness to use to choose bases. + * @param iterations + * the number of randomly-chosen bases to perform the test for. + * @return an {@link MROutput} instance that can be further queried for details. + */ + public static MROutput enhancedMRProbablePrimeTest(BigInteger candidate, SecureRandom random, int iterations) + { + checkCandidate(candidate, "candidate"); + + if (random == null) + { + throw new IllegalArgumentException("'random' cannot be null"); + } + if (iterations < 1) + { + throw new IllegalArgumentException("'iterations' must be > 0"); + } + + if (candidate.bitLength() == 2) + { + return MROutput.probablyPrime(); + } + if (!candidate.testBit(0)) + { + return MROutput.provablyCompositeWithFactor(TWO); + } + + BigInteger w = candidate; + BigInteger wSubOne = candidate.subtract(ONE); + BigInteger wSubTwo = candidate.subtract(TWO); + + int a = wSubOne.getLowestSetBit(); + BigInteger m = wSubOne.shiftRight(a); + + for (int i = 0; i < iterations; ++i) + { + BigInteger b = BigIntegers.createRandomInRange(TWO, wSubTwo, random); + BigInteger g = b.gcd(w); + + if (g.compareTo(ONE) > 0) + { + return MROutput.provablyCompositeWithFactor(g); + } + + BigInteger z = b.modPow(m, w); + + if (z.equals(ONE) || z.equals(wSubOne)) + { + continue; + } + + boolean primeToBase = false; + + BigInteger x = z; + for (int j = 1; j < a; ++j) + { + z = z.modPow(TWO, w); + + if (z.equals(wSubOne)) + { + primeToBase = true; + break; + } + + if (z.equals(ONE)) + { + break; + } + + x = z; + } + + if (!primeToBase) + { + if (!z.equals(ONE)) + { + x = z; + z = z.modPow(TWO, w); + + if (!z.equals(ONE)) + { + x = z; + } + } + + g = x.subtract(ONE).gcd(w); + + if (g.compareTo(ONE) > 0) + { + return MROutput.provablyCompositeWithFactor(g); + } + + return MROutput.provablyCompositeNotPrimePower(); + } + } + + return MROutput.probablyPrime(); + } + + /** + * A fast check for small divisors, up to some implementation-specific limit. + * + * @param candidate + * the {@link BigInteger} instance to test for division by small factors. + * + * @return <code>true</code> if the candidate is found to have any small factors, + * <code>false</code> otherwise. + */ + public static boolean hasAnySmallFactors(BigInteger candidate) + { + checkCandidate(candidate, "candidate"); + + return implHasAnySmallFactors(candidate); + } + + /** + * FIPS 186-4 C.3.1 Miller-Rabin Probabilistic Primality Test + * + * Run several iterations of the Miller-Rabin algorithm with randomly-chosen bases. + * + * @param candidate + * the {@link BigInteger} instance to test for primality. + * @param random + * the source of randomness to use to choose bases. + * @param iterations + * the number of randomly-chosen bases to perform the test for. + * @return <code>false</code> if any witness to compositeness is found amongst the chosen bases + * (so <code>candidate</code> is definitely NOT prime), or else <code>true</code> + * (indicating primality with some probability dependent on the number of iterations + * that were performed). + */ + public static boolean isMRProbablePrime(BigInteger candidate, SecureRandom random, int iterations) + { + checkCandidate(candidate, "candidate"); + + if (random == null) + { + throw new IllegalArgumentException("'random' cannot be null"); + } + if (iterations < 1) + { + throw new IllegalArgumentException("'iterations' must be > 0"); + } + + if (candidate.bitLength() == 2) + { + return true; + } + if (!candidate.testBit(0)) + { + return false; + } + + BigInteger w = candidate; + BigInteger wSubOne = candidate.subtract(ONE); + BigInteger wSubTwo = candidate.subtract(TWO); + + int a = wSubOne.getLowestSetBit(); + BigInteger m = wSubOne.shiftRight(a); + + for (int i = 0; i < iterations; ++i) + { + BigInteger b = BigIntegers.createRandomInRange(TWO, wSubTwo, random); + + if (!implMRProbablePrimeToBase(w, wSubOne, m, a, b)) + { + return false; + } + } + + return true; + } + + /** + * FIPS 186-4 C.3.1 Miller-Rabin Probabilistic Primality Test (to a fixed base). + * + * Run a single iteration of the Miller-Rabin algorithm against the specified base. + * + * @param candidate + * the {@link BigInteger} instance to test for primality. + * @param base + * the base value to use for this iteration. + * @return <code>false</code> if the specified base is a witness to compositeness (so + * <code>candidate</code> is definitely NOT prime), or else <code>true</code>. + */ + public static boolean isMRProbablePrimeToBase(BigInteger candidate, BigInteger base) + { + checkCandidate(candidate, "candidate"); + checkCandidate(base, "base"); + + if (base.compareTo(candidate.subtract(ONE)) >= 0) + { + throw new IllegalArgumentException("'base' must be < ('candidate' - 1)"); + } + + if (candidate.bitLength() == 2) + { + return true; + } + + BigInteger w = candidate; + BigInteger wSubOne = candidate.subtract(ONE); + + int a = wSubOne.getLowestSetBit(); + BigInteger m = wSubOne.shiftRight(a); + + return implMRProbablePrimeToBase(w, wSubOne, m, a, base); + } + + private static void checkCandidate(BigInteger n, String name) + { + if (n == null || n.signum() < 1 || n.bitLength() < 2) + { + throw new IllegalArgumentException("'" + name + "' must be non-null and >= 2"); + } + } + + private static boolean implHasAnySmallFactors(BigInteger x) + { + /* + * Bundle trial divisors into ~32-bit moduli then use fast tests on the ~32-bit remainders. + */ + int m = 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23; + int r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 2) == 0 || (r % 3) == 0 || (r % 5) == 0 || (r % 7) == 0 || (r % 11) == 0 || (r % 13) == 0 + || (r % 17) == 0 || (r % 19) == 0 || (r % 23) == 0) + { + return true; + } + + m = 29 * 31 * 37 * 41 * 43; + r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 29) == 0 || (r % 31) == 0 || (r % 37) == 0 || (r % 41) == 0 || (r % 43) == 0) + { + return true; + } + + m = 47 * 53 * 59 * 61 * 67; + r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 47) == 0 || (r % 53) == 0 || (r % 59) == 0 || (r % 61) == 0 || (r % 67) == 0) + { + return true; + } + + m = 71 * 73 * 79 * 83; + r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 71) == 0 || (r % 73) == 0 || (r % 79) == 0 || (r % 83) == 0) + { + return true; + } + + m = 89 * 97 * 101 * 103; + r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 89) == 0 || (r % 97) == 0 || (r % 101) == 0 || (r % 103) == 0) + { + return true; + } + + m = 107 * 109 * 113 * 127; + r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 107) == 0 || (r % 109) == 0 || (r % 113) == 0 || (r % 127) == 0) + { + return true; + } + + m = 131 * 137 * 139 * 149; + r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 131) == 0 || (r % 137) == 0 || (r % 139) == 0 || (r % 149) == 0) + { + return true; + } + + m = 151 * 157 * 163 * 167; + r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 151) == 0 || (r % 157) == 0 || (r % 163) == 0 || (r % 167) == 0) + { + return true; + } + + m = 173 * 179 * 181 * 191; + r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 173) == 0 || (r % 179) == 0 || (r % 181) == 0 || (r % 191) == 0) + { + return true; + } + + m = 193 * 197 * 199 * 211; + r = x.mod(BigInteger.valueOf(m)).intValue(); + if ((r % 193) == 0 || (r % 197) == 0 || (r % 199) == 0 || (r % 211) == 0) + { + return true; + } + + /* + * NOTE: Unit tests depend on SMALL_FACTOR_LIMIT matching the + * highest small factor tested here. + */ + return false; + } + + private static boolean implMRProbablePrimeToBase(BigInteger w, BigInteger wSubOne, BigInteger m, int a, BigInteger b) + { + BigInteger z = b.modPow(m, w); + + if (z.equals(ONE) || z.equals(wSubOne)) + { + return true; + } + + boolean result = false; + + for (int j = 1; j < a; ++j) + { + z = z.modPow(TWO, w); + + if (z.equals(wSubOne)) + { + result = true; + break; + } + + if (z.equals(ONE)) + { + return false; + } + } + + return result; + } + + private static STOutput implSTRandomPrime(Digest d, int length, byte[] primeSeed) + { + int dLen = d.getDigestSize(); + + if (length < 33) + { + int primeGenCounter = 0; + + byte[] c0 = new byte[dLen]; + byte[] c1 = new byte[dLen]; + + for (;;) + { + hash(d, primeSeed, c0, 0); + inc(primeSeed, 1); + + hash(d, primeSeed, c1, 0); + inc(primeSeed, 1); + + int c = extract32(c0) ^ extract32(c1); + c &= (-1 >>> (32 - length)); + c |= (1 << (length - 1)) | 1; + + ++primeGenCounter; + + long c64 = c & 0xFFFFFFFFL; + if (isPrime32(c64)) + { + return new STOutput(BigInteger.valueOf(c64), primeSeed, primeGenCounter); + } + + if (primeGenCounter > (4 * length)) + { + throw new IllegalStateException("Too many iterations in Shawe-Taylor Random_Prime Routine"); + } + } + } + + STOutput rec = implSTRandomPrime(d, (length + 3) / 2, primeSeed); + + BigInteger c0 = rec.getPrime(); + primeSeed = rec.getPrimeSeed(); + int primeGenCounter = rec.getPrimeGenCounter(); + + int outlen = 8 * dLen; + int iterations = (length - 1) / outlen; + + int oldCounter = primeGenCounter; + + BigInteger x = hashGen(d, primeSeed, iterations + 1); + x = x.mod(ONE.shiftLeft(length - 1)).setBit(length - 1); + + BigInteger c0x2 = c0.shiftLeft(1); + BigInteger tx2 = x.subtract(ONE).divide(c0x2).add(ONE).shiftLeft(1); + int dt = 0; + + BigInteger c = tx2.multiply(c0).add(ONE); + + /* + * TODO Since the candidate primes are generated by constant steps ('c0x2'), sieving could + * be used here in place of the 'hasAnySmallFactors' approach. + */ + for (;;) + { + if (c.bitLength() > length) + { + tx2 = ONE.shiftLeft(length - 1).subtract(ONE).divide(c0x2).add(ONE).shiftLeft(1); + c = tx2.multiply(c0).add(ONE); + } + + ++primeGenCounter; + + /* + * This is an optimization of the original algorithm, using trial division to screen out + * many non-primes quickly. + * + * NOTE: 'primeSeed' is still incremented as if we performed the full check! + */ + if (!implHasAnySmallFactors(c)) + { + BigInteger a = hashGen(d, primeSeed, iterations + 1); + a = a.mod(c.subtract(THREE)).add(TWO); + + tx2 = tx2.add(BigInteger.valueOf(dt)); + dt = 0; + + BigInteger z = a.modPow(tx2, c); + + if (c.gcd(z.subtract(ONE)).equals(ONE) && z.modPow(c0, c).equals(ONE)) + { + return new STOutput(c, primeSeed, primeGenCounter); + } + } + else + { + inc(primeSeed, iterations + 1); + } + + if (primeGenCounter >= ((4 * length) + oldCounter)) + { + throw new IllegalStateException("Too many iterations in Shawe-Taylor Random_Prime Routine"); + } + + dt += 2; + c = c.add(c0x2); + } + } + + private static int extract32(byte[] bs) + { + int result = 0; + + int count = Math.min(4, bs.length); + for (int i = 0; i < count; ++i) + { + int b = bs[bs.length - (i + 1)] & 0xFF; + result |= (b << (8 * i)); + } + + return result; + } + + private static void hash(Digest d, byte[] input, byte[] output, int outPos) + { + d.update(input, 0, input.length); + d.doFinal(output, outPos); + } + + private static BigInteger hashGen(Digest d, byte[] seed, int count) + { + int dLen = d.getDigestSize(); + int pos = count * dLen; + byte[] buf = new byte[pos]; + for (int i = 0; i < count; ++i) + { + pos -= dLen; + hash(d, seed, buf, pos); + inc(seed, 1); + } + return new BigInteger(1, buf); + } + + private static void inc(byte[] seed, int c) + { + int pos = seed.length; + while (c > 0 && --pos >= 0) + { + c += (seed[pos] & 0xFF); + seed[pos] = (byte)c; + c >>>= 8; + } + } + + private static boolean isPrime32(long x) + { + if (x >>> 32 != 0L) + { + throw new IllegalArgumentException("Size limit exceeded"); + } + + /* + * Use wheel factorization with 2, 3, 5 to select trial divisors. + */ + + if (x <= 5L) + { + return x == 2L || x == 3L || x == 5L; + } + + if ((x & 1L) == 0L || (x % 3L) == 0L || (x % 5L) == 0L) + { + return false; + } + + long[] ds = new long[]{ 1L, 7L, 11L, 13L, 17L, 19L, 23L, 29L }; + long base = 0L; + for (int pos = 1;; pos = 0) + { + /* + * Trial division by wheel-selected divisors + */ + while (pos < ds.length) + { + long d = base + ds[pos]; + if (x % d == 0L) + { + return x < 30L; + } + ++pos; + } + + base += 30L; + + if (base * base >= x) + { + return true; + } + } + } +}
\ No newline at end of file diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java index 7165bab3..f8bf1eb5 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java @@ -11,14 +11,23 @@ public class ECAlgorithms { public static boolean isF2mCurve(ECCurve c) { - FiniteField field = c.getField(); + return isF2mField(c.getField()); + } + + public static boolean isF2mField(FiniteField field) + { return field.getDimension() > 1 && field.getCharacteristic().equals(ECConstants.TWO) && field instanceof PolynomialExtensionField; } public static boolean isFpCurve(ECCurve c) { - return c.getField().getDimension() == 1; + return isFpField(c.getField()); + } + + public static boolean isFpField(FiniteField field) + { + return field.getDimension() == 1; } public static ECPoint sumOfMultiplies(ECPoint[] ps, BigInteger[] ks) @@ -65,9 +74,9 @@ public class ECAlgorithms Q = importPoint(cp, Q); // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick - if (cp instanceof ECCurve.F2m) + if (cp instanceof ECCurve.AbstractF2m) { - ECCurve.F2m f2mCurve = (ECCurve.F2m)cp; + ECCurve.AbstractF2m f2mCurve = (ECCurve.AbstractF2m)cp; if (f2mCurve.isKoblitz()) { return validatePoint(P.multiply(a).add(Q.multiply(b))); diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECConstants.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECConstants.java index 864f746d..53e60f73 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECConstants.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECConstants.java @@ -9,4 +9,5 @@ public interface ECConstants public static final BigInteger TWO = BigInteger.valueOf(2); public static final BigInteger THREE = BigInteger.valueOf(3); public static final BigInteger FOUR = BigInteger.valueOf(4); + public static final BigInteger EIGHT = BigInteger.valueOf(8); } diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java index 0dc68535..7f3197bc 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java @@ -75,9 +75,13 @@ public abstract class ECCurve throw new IllegalStateException("implementation returned current curve"); } - c.coord = coord; - c.endomorphism = endomorphism; - c.multiplier = multiplier; + // NOTE: Synchronization added to keep FindBugsâ„¢ happy + synchronized (c) + { + c.coord = coord; + c.endomorphism = endomorphism; + c.multiplier = multiplier; + } return c; } @@ -100,7 +104,9 @@ public abstract class ECCurve public abstract ECFieldElement fromBigInteger(BigInteger x); - public Config configure() + public abstract boolean isValidFieldElement(BigInteger x); + + public synchronized Config configure() { return new Config(this.coord, this.endomorphism, this.multiplier); } @@ -497,10 +503,15 @@ public abstract class ECCurve super(FiniteFields.getPrimeField(q)); } + public boolean isValidFieldElement(BigInteger x) + { + return x != null && x.signum() >= 0 && x.compareTo(this.getField().getCharacteristic()) < 0; + } + protected ECPoint decompressPoint(int yTilde, BigInteger X1) { ECFieldElement x = this.fromBigInteger(X1); - ECFieldElement rhs = x.square().add(a).multiply(x).add(b); + ECFieldElement rhs = x.square().add(this.a).multiply(x).add(this.b); ECFieldElement y = rhs.sqrt(); /* @@ -526,7 +537,7 @@ public abstract class ECCurve */ public static class Fp extends AbstractFp { - private static final int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED; + private static final int FP_DEFAULT_COORDS = ECCurve.COORD_JACOBIAN_MODIFIED; BigInteger q, r; ECPoint.Fp infinity; @@ -573,17 +584,17 @@ public abstract class ECCurve protected ECCurve cloneCurve() { - return new Fp(q, r, a, b, order, cofactor); + return new Fp(this.q, this.r, this.a, this.b, this.order, this.cofactor); } public boolean supportsCoordinateSystem(int coord) { switch (coord) { - case COORD_AFFINE: - case COORD_HOMOGENEOUS: - case COORD_JACOBIAN: - case COORD_JACOBIAN_MODIFIED: + case ECCurve.COORD_AFFINE: + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_JACOBIAN: + case ECCurve.COORD_JACOBIAN_MODIFIED: return true; default: return false; @@ -617,13 +628,13 @@ public abstract class ECCurve public ECPoint importPoint(ECPoint p) { - if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity()) + if (this != p.getCurve() && this.getCoordinateSystem() == ECCurve.COORD_JACOBIAN && !p.isInfinity()) { switch (p.getCurve().getCoordinateSystem()) { - case COORD_JACOBIAN: - case COORD_JACOBIAN_CHUDNOVSKY: - case COORD_JACOBIAN_MODIFIED: + case ECCurve.COORD_JACOBIAN: + case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: + case ECCurve.COORD_JACOBIAN_MODIFIED: return new ECPoint.Fp(this, fromBigInteger(p.x.toBigInteger()), fromBigInteger(p.y.toBigInteger()), @@ -645,6 +656,18 @@ public abstract class ECCurve public static abstract class AbstractF2m extends ECCurve { + public static BigInteger inverse(int m, int[] ks, BigInteger x) + { + return new LongArray(x).modInverse(m, ks).toBigInteger(); + } + + /** + * The auxiliary values <code>s<sub>0</sub></code> and + * <code>s<sub>1</sub></code> used for partial modular reduction for + * Koblitz curves. + */ + private BigInteger[] si = null; + private static FiniteField buildField(int m, int k1, int k2, int k3) { if (k1 == 0) @@ -679,6 +702,173 @@ public abstract class ECCurve { super(buildField(m, k1, k2, k3)); } + + public boolean isValidFieldElement(BigInteger x) + { + return x != null && x.signum() >= 0 && x.bitLength() <= this.getFieldSize(); + } + + public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) + { + ECFieldElement X = this.fromBigInteger(x), Y = this.fromBigInteger(y); + + int coord = this.getCoordinateSystem(); + + switch (coord) + { + case ECCurve.COORD_LAMBDA_AFFINE: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + if (X.isZero()) + { + if (!Y.square().equals(this.getB())) + { + throw new IllegalArgumentException(); + } + } + /* + * NOTE: A division could be avoided using a projective result, except at present + * callers will expect that the result is already normalized. + */ +// else if (coord == COORD_LAMBDA_PROJECTIVE) +// { +// ECFieldElement Z = X; +// X = X.square(); +// Y = Y.add(X); +// return createRawPoint(X, Y, new ECFieldElement[]{ Z }, withCompression); +// } + else + { + // Y becomes Lambda (X + Y/X) here + Y = Y.divide(X).add(X); + } + break; + } + default: + { + break; + } + } + + return this.createRawPoint(X, Y, withCompression); + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected ECPoint decompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = this.fromBigInteger(X1), y = null; + if (x.isZero()) + { + y = this.getB().sqrt(); + } + else + { + ECFieldElement beta = x.square().invert().multiply(this.getB()).add(this.getA()).add(x); + ECFieldElement z = solveQuadraticEquation(beta); + if (z != null) + { + if (z.testBitZero() != (yTilde == 1)) + { + z = z.addOne(); + } + + switch (this.getCoordinateSystem()) + { + case ECCurve.COORD_LAMBDA_AFFINE: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + y = z.add(x); + break; + } + default: + { + y = z.multiply(x); + break; + } + } + } + } + + if (y == null) + { + throw new IllegalArgumentException("Invalid point compression"); + } + + return this.createRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 + * D.1.6) The other solution is <code>z + 1</code>. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for <code>z<sup>2</sup> + z = beta</code> or + * <code>null</code> if no solution exists. + */ + private ECFieldElement solveQuadraticEquation(ECFieldElement beta) + { + if (beta.isZero()) + { + return beta; + } + + ECFieldElement gamma, z, zeroElement = this.fromBigInteger(ECConstants.ZERO); + + int m = this.getFieldSize(); + Random rand = new Random(); + do + { + ECFieldElement t = this.fromBigInteger(new BigInteger(m, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < m; i++) + { + ECFieldElement w2 = w.square(); + z = z.square().add(w2.multiply(t)); + w = w2.add(beta); + } + if (!w.isZero()) + { + return null; + } + gamma = z.square().add(z); + } + while (gamma.isZero()); + + return z; + } + + /** + * @return the auxiliary values <code>s<sub>0</sub></code> and + * <code>s<sub>1</sub></code> used for partial modular reduction for + * Koblitz curves. + */ + synchronized BigInteger[] getSi() + { + if (si == null) + { + si = Tnaf.getSi(this); + } + return si; + } + + /** + * Returns true if this is a Koblitz curve (ABC curve). + * @return true if this is a Koblitz curve (ABC curve), false otherwise + */ + public boolean isKoblitz() + { + return this.order != null && this.cofactor != null && this.b.isOne() && (this.a.isZero() || this.a.isOne()); + } } /** @@ -687,7 +877,7 @@ public abstract class ECCurve */ public static class F2m extends AbstractF2m { - private static final int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + private static final int F2M_DEFAULT_COORDS = ECCurve.COORD_LAMBDA_PROJECTIVE; /** * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. @@ -726,19 +916,6 @@ public abstract class ECCurve private ECPoint.F2m infinity; // can't be final - JDK 1.1 /** - * The parameter <code>μ</code> of the elliptic curve if this is - * a Koblitz curve. - */ - private byte mu = 0; - - /** - * The auxiliary values <code>s<sub>0</sub></code> and - * <code>s<sub>1</sub></code> used for partial modular reduction for - * Koblitz curves. - */ - private BigInteger[] si = null; - - /** * Constructor for Trinomial Polynomial Basis (TPB). * @param m The exponent <code>m</code> of * <code>F<sub>2<sup>m</sup></sub></code>. @@ -887,16 +1064,16 @@ public abstract class ECCurve protected ECCurve cloneCurve() { - return new F2m(m, k1, k2, k3, a, b, order, cofactor); + return new F2m(this.m, this.k1, this.k2, this.k3, this.a, this.b, this.order, this.cofactor); } public boolean supportsCoordinateSystem(int coord) { switch (coord) { - case COORD_AFFINE: - case COORD_HOMOGENEOUS: - case COORD_LAMBDA_PROJECTIVE: + case ECCurve.COORD_AFFINE: + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_LAMBDA_PROJECTIVE: return true; default: return false; @@ -923,38 +1100,6 @@ public abstract class ECCurve return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x); } - public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) - { - ECFieldElement X = fromBigInteger(x), Y = fromBigInteger(y); - - switch (this.getCoordinateSystem()) - { - case COORD_LAMBDA_AFFINE: - case COORD_LAMBDA_PROJECTIVE: - { - if (X.isZero()) - { - if (!Y.square().equals(this.getB())) - { - throw new IllegalArgumentException(); - } - } - else - { - // Y becomes Lambda (X + Y/X) here - Y = Y.divide(X).add(X); - } - break; - } - default: - { - break; - } - } - - return createRawPoint(X, Y, withCompression); - } - protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) { return new ECPoint.F2m(this, x, y, withCompression); @@ -970,140 +1115,6 @@ public abstract class ECCurve return infinity; } - /** - * Returns true if this is a Koblitz curve (ABC curve). - * @return true if this is a Koblitz curve (ABC curve), false otherwise - */ - public boolean isKoblitz() - { - return order != null && cofactor != null && b.isOne() && (a.isZero() || a.isOne()); - } - - /** - * Returns the parameter <code>μ</code> of the elliptic curve. - * @return <code>μ</code> of the elliptic curve. - * @throws IllegalArgumentException if the given ECCurve is not a - * Koblitz curve. - */ - synchronized byte getMu() - { - if (mu == 0) - { - mu = Tnaf.getMu(this); - } - return mu; - } - - /** - * @return the auxiliary values <code>s<sub>0</sub></code> and - * <code>s<sub>1</sub></code> used for partial modular reduction for - * Koblitz curves. - */ - synchronized BigInteger[] getSi() - { - if (si == null) - { - si = Tnaf.getSi(this); - } - return si; - } - - /** - * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). - * - * @param yTilde - * ~yp, an indication bit for the decompression of yp. - * @param X1 - * The field element xp. - * @return the decompressed point. - */ - protected ECPoint decompressPoint(int yTilde, BigInteger X1) - { - ECFieldElement x = fromBigInteger(X1), y = null; - if (x.isZero()) - { - y = b.sqrt(); - } - else - { - ECFieldElement beta = x.square().invert().multiply(b).add(a).add(x); - ECFieldElement z = solveQuadraticEquation(beta); - if (z != null) - { - if (z.testBitZero() != (yTilde == 1)) - { - z = z.addOne(); - } - - switch (this.getCoordinateSystem()) - { - case COORD_LAMBDA_AFFINE: - case COORD_LAMBDA_PROJECTIVE: - { - y = z.add(x); - break; - } - default: - { - y = z.multiply(x); - break; - } - } - } - } - - if (y == null) - { - throw new IllegalArgumentException("Invalid point compression"); - } - - return this.createRawPoint(x, y, true); - } - - /** - * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 - * D.1.6) The other solution is <code>z + 1</code>. - * - * @param beta - * The value to solve the quadratic equation for. - * @return the solution for <code>z<sup>2</sup> + z = beta</code> or - * <code>null</code> if no solution exists. - */ - private ECFieldElement solveQuadraticEquation(ECFieldElement beta) - { - if (beta.isZero()) - { - return beta; - } - - ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO); - - ECFieldElement z = null; - ECFieldElement gamma = null; - - Random rand = new Random(); - do - { - ECFieldElement t = fromBigInteger(new BigInteger(m, rand)); - z = zeroElement; - ECFieldElement w = beta; - for (int i = 1; i <= m - 1; i++) - { - ECFieldElement w2 = w.square(); - z = z.square().add(w2.multiply(t)); - w = w2.add(beta); - } - if (!w.isZero()) - { - return null; - } - gamma = z.square().add(z); - } - while (gamma.isZero()); - - return z; - } - public int getM() { return m; @@ -1139,7 +1150,7 @@ public abstract class ECCurve */ public BigInteger getN() { - return order; + return this.order; } /** @@ -1147,7 +1158,7 @@ public abstract class ECCurve */ public BigInteger getH() { - return cofactor; + return this.cofactor; } } } diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java index 59438826..18409c09 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java @@ -59,6 +59,16 @@ public abstract class ECFieldElement return square().add(x.multiply(y)); } + public ECFieldElement squarePow(int pow) + { + ECFieldElement r = this; + for (int i = 0; i < pow; ++i) + { + r = r.square(); + } + return r; + } + public boolean testBitZero() { return toBigInteger().testBit(0); @@ -548,6 +558,11 @@ public abstract class ECFieldElement int k3, BigInteger x) { + if (x == null || x.signum() < 0 || x.bitLength() > m) + { + throw new IllegalArgumentException("x value invalid in F2m field element"); + } + if ((k2 == 0) && (k3 == 0)) { this.representation = TPB; @@ -766,6 +781,11 @@ public abstract class ECFieldElement return new F2m(m, ks, aa); } + public ECFieldElement squarePow(int pow) + { + return pow < 1 ? this : new F2m(m, ks, x.modSquareN(pow, m, ks)); + } + public ECFieldElement invert() { return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks)); @@ -773,14 +793,7 @@ public abstract class ECFieldElement public ECFieldElement sqrt() { - LongArray x1 = this.x; - if (x1.isOne() || x1.isZero()) - { - return this; - } - - LongArray x2 = x1.modSquareN(m - 1, m, ks); - return new ECFieldElement.F2m(m, ks, x2); + return (x.isZero() || x.isOne()) ? this : squarePow(m - 1); } /** diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java index 4db27e04..0ea5026c 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java @@ -181,19 +181,19 @@ public abstract class ECPoint int zsLen = zs.length; if (zsLen == 0) { - return zs; + return EMPTY_ZS; } ECFieldElement[] copy = new ECFieldElement[zsLen]; System.arraycopy(zs, 0, copy, 0, zsLen); return copy; } - protected final ECFieldElement getRawXCoord() + public final ECFieldElement getRawXCoord() { return x; } - protected final ECFieldElement getRawYCoord() + public final ECFieldElement getRawYCoord() { return y; } @@ -1175,6 +1175,8 @@ public abstract class ECPoint { switch (coord) { + case ECCurve.COORD_AFFINE: + break; case ECCurve.COORD_HOMOGENEOUS: ECFieldElement Z1Sq = Z1.square(); X1 = X1.multiply(Z1); @@ -1187,6 +1189,8 @@ public abstract class ECPoint case ECCurve.COORD_JACOBIAN_MODIFIED: W1 = getJacobianModifiedW(); break; + default: + throw new IllegalStateException("unsupported coordinate system"); } } @@ -1418,6 +1422,153 @@ public abstract class ECPoint ECFieldElement rhs = X.add(A).multiply(X.square()).add(B); return lhs.equals(rhs); } + + public ECPoint scaleX(ECFieldElement scale) + { + if (this.isInfinity()) + { + return this; + } + + int coord = this.getCurveCoordinateSystem(); + + switch (coord) + { + case ECCurve.COORD_LAMBDA_AFFINE: + { + // Y is actually Lambda (X + Y/X) here + ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK + + ECFieldElement X2 = X.multiply(scale); + ECFieldElement L2 = L.add(X).divide(scale).add(X2); + + return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK + } + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + // Y is actually Lambda (X + Y/X) here + ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(), Z = this.getRawZCoords()[0]; // earlier JDK + + // We scale the Z coordinate also, to avoid an inversion + ECFieldElement X2 = X.multiply(scale.square()); + ECFieldElement L2 = L.add(X).add(X2); + ECFieldElement Z2 = Z.multiply(scale); + + return this.getCurve().createRawPoint(X2, L2, new ECFieldElement[]{ Z2 }, this.withCompression); // earlier JDK + } + default: + { + return super.scaleX(scale); + } + } + } + + public ECPoint scaleY(ECFieldElement scale) + { + if (this.isInfinity()) + { + return this; + } + + int coord = this.getCurveCoordinateSystem(); + + switch (coord) + { + case ECCurve.COORD_LAMBDA_AFFINE: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK + + // Y is actually Lambda (X + Y/X) here + ECFieldElement L2 = L.add(X).multiply(scale).add(X); + + return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK + } + default: + { + return super.scaleY(scale); + } + } + } + + public ECPoint subtract(ECPoint b) + { + if (b.isInfinity()) + { + return this; + } + + // Add -b + return this.add(b.negate()); + } + + public ECPoint.AbstractF2m tau() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + int coord = curve.getCoordinateSystem(); + + ECFieldElement X1 = this.x; + + switch (coord) + { + case ECCurve.COORD_AFFINE: + case ECCurve.COORD_LAMBDA_AFFINE: + { + ECFieldElement Y1 = this.y; + return (ECPoint.AbstractF2m)curve.createRawPoint(X1.square(), Y1.square(), this.withCompression); + } + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + ECFieldElement Y1 = this.y, Z1 = this.zs[0]; + return (ECPoint.AbstractF2m)curve.createRawPoint(X1.square(), Y1.square(), + new ECFieldElement[]{ Z1.square() }, this.withCompression); + } + default: + { + throw new IllegalStateException("unsupported coordinate system"); + } + } + } + + public ECPoint.AbstractF2m tauPow(int pow) + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + int coord = curve.getCoordinateSystem(); + + ECFieldElement X1 = this.x; + + switch (coord) + { + case ECCurve.COORD_AFFINE: + case ECCurve.COORD_LAMBDA_AFFINE: + { + ECFieldElement Y1 = this.y; + return (ECPoint.AbstractF2m)curve.createRawPoint(X1.squarePow(pow), Y1.squarePow(pow), this.withCompression); + } + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + ECFieldElement Y1 = this.y, Z1 = this.zs[0]; + return (ECPoint.AbstractF2m)curve.createRawPoint(X1.squarePow(pow), Y1.squarePow(pow), + new ECFieldElement[]{ Z1.squarePow(pow) }, this.withCompression); + } + default: + { + throw new IllegalStateException("unsupported coordinate system"); + } + } + } } /** @@ -1520,74 +1671,6 @@ public abstract class ECPoint } } - public ECPoint scaleX(ECFieldElement scale) - { - if (this.isInfinity()) - { - return this; - } - - int coord = this.getCurveCoordinateSystem(); - - switch (coord) - { - case ECCurve.COORD_LAMBDA_AFFINE: - { - // Y is actually Lambda (X + Y/X) here - ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK - - ECFieldElement X2 = X.multiply(scale); - ECFieldElement L2 = L.add(X).divide(scale).add(X2); - - return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK - } - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - // Y is actually Lambda (X + Y/X) here - ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(), Z = this.getRawZCoords()[0]; // earlier JDK - - // We scale the Z coordinate also, to avoid an inversion - ECFieldElement X2 = X.multiply(scale.square()); - ECFieldElement L2 = L.add(X).add(X2); - ECFieldElement Z2 = Z.multiply(scale); - - return this.getCurve().createRawPoint(X2, L2, new ECFieldElement[]{ Z2 }, this.withCompression); // earlier JDK - } - default: - { - return super.scaleX(scale); - } - } - } - - public ECPoint scaleY(ECFieldElement scale) - { - if (this.isInfinity()) - { - return this; - } - - int coord = this.getCurveCoordinateSystem(); - - switch (coord) - { - case ECCurve.COORD_LAMBDA_AFFINE: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK - - // Y is actually Lambda (X + Y/X) here - ECFieldElement L2 = L.add(X).multiply(scale).add(X); - - return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK - } - default: - { - return super.scaleY(scale); - } - } - } - protected boolean getCompressionYTilde() { ECFieldElement X = this.getRawXCoord(); @@ -1613,45 +1696,8 @@ public abstract class ECPoint } } - /** - * Check, if two <code>ECPoint</code>s can be added or subtracted. - * @param a The first <code>ECPoint</code> to check. - * @param b The second <code>ECPoint</code> to check. - * @throws IllegalArgumentException if <code>a</code> and <code>b</code> - * cannot be added. - */ - private static void checkPoints(ECPoint a, ECPoint b) - { - // Check, if points are on the same curve - if (a.curve != b.curve) - { - throw new IllegalArgumentException("Only points on the same " - + "curve can be added or subtracted"); - } - -// ECFieldElement.F2m.checkFieldElements(a.x, b.x); - } - - /* (non-Javadoc) - * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint) - */ public ECPoint add(ECPoint b) { - checkPoints(this, b); - return addSimple((ECPoint.F2m)b); - } - - /** - * Adds another <code>ECPoints.F2m</code> to <code>this</code> without - * checking if both points are on the same curve. Used by multiplication - * algorithms, because there all points are a multiple of the same point - * and hence the checks can be omitted. - * @param b The other <code>ECPoints.F2m</code> to add to - * <code>this</code>. - * @return <code>this + b</code> - */ - public ECPoint.F2m addSimple(ECPoint.F2m b) - { if (this.isInfinity()) { return b; @@ -1679,10 +1725,10 @@ public abstract class ECPoint { if (dy.isZero()) { - return (ECPoint.F2m)twice(); + return twice(); } - return (ECPoint.F2m)curve.getInfinity(); + return curve.getInfinity(); } ECFieldElement L = dy.divide(dx); @@ -1710,10 +1756,10 @@ public abstract class ECPoint { if (U.isZero()) { - return (ECPoint.F2m)twice(); + return twice(); } - return (ECPoint.F2m)curve.getInfinity(); + return curve.getInfinity(); } ECFieldElement VSq = V.square(); @@ -1735,10 +1781,10 @@ public abstract class ECPoint { if (X2.isZero()) { - return (ECPoint.F2m)curve.getInfinity(); + return curve.getInfinity(); } - return b.addSimple(this); + return b.add(this); } ECFieldElement L1 = this.y, Z1 = this.zs[0]; @@ -1767,10 +1813,10 @@ public abstract class ECPoint { if (A.isZero()) { - return (ECPoint.F2m)twice(); + return twice(); } - return (ECPoint.F2m)curve.getInfinity(); + return curve.getInfinity(); } ECFieldElement X3, L3, Z3; @@ -1831,68 +1877,6 @@ public abstract class ECPoint } } - /* (non-Javadoc) - * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint) - */ - public ECPoint subtract(ECPoint b) - { - checkPoints(this, b); - return subtractSimple((ECPoint.F2m)b); - } - - /** - * Subtracts another <code>ECPoints.F2m</code> from <code>this</code> - * without checking if both points are on the same curve. Used by - * multiplication algorithms, because there all points are a multiple - * of the same point and hence the checks can be omitted. - * @param b The other <code>ECPoints.F2m</code> to subtract from - * <code>this</code>. - * @return <code>this - b</code> - */ - public ECPoint.F2m subtractSimple(ECPoint.F2m b) - { - if (b.isInfinity()) - { - return this; - } - - // Add -b - return addSimple((ECPoint.F2m)b.negate()); - } - - public ECPoint.F2m tau() - { - if (this.isInfinity()) - { - return this; - } - - ECCurve curve = this.getCurve(); - int coord = curve.getCoordinateSystem(); - - ECFieldElement X1 = this.x; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - case ECCurve.COORD_LAMBDA_AFFINE: - { - ECFieldElement Y1 = this.y; - return new ECPoint.F2m(curve, X1.square(), Y1.square(), this.withCompression); - } - case ECCurve.COORD_HOMOGENEOUS: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - ECFieldElement Y1 = this.y, Z1 = this.zs[0]; - return new ECPoint.F2m(curve, X1.square(), Y1.square(), new ECFieldElement[]{ Z1.square() }, this.withCompression); - } - default: - { - throw new IllegalStateException("unsupported coordinate system"); - } - } - } - public ECPoint twice() { if (this.isInfinity()) diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java b/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java index e3069dc0..b963118a 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java @@ -4,15 +4,17 @@ import org.bouncycastle.util.Arrays; import java.math.BigInteger; -class LongArray +class LongArray implements Cloneable { // private static long DEINTERLEAVE_MASK = 0x5555555555555555L; /* * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits. * In a binary field, this operation is the same as squaring an 8 bit number. + * + * NOTE: All entries are positive so sign-extension is not an issue. */ - private static final int[] INTERLEAVE2_TABLE = new int[] + private static final short[] INTERLEAVE2_TABLE = new short[] { 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java b/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java index 236bbc8e..aef0cf79 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java @@ -386,11 +386,11 @@ class Tnaf /** * Applies the operation <code>τ()</code> to an - * <code>ECPoint.F2m</code>. - * @param p The ECPoint.F2m to which <code>τ()</code> is applied. + * <code>ECPoint.AbstractF2m</code>. + * @param p The ECPoint.AbstractF2m to which <code>τ()</code> is applied. * @return <code>τ(p)</code> */ - public static ECPoint.F2m tau(ECPoint.F2m p) + public static ECPoint.AbstractF2m tau(ECPoint.AbstractF2m p) { return p.tau(); } @@ -405,7 +405,7 @@ class Tnaf * @throws IllegalArgumentException if the given ECCurve is not a Koblitz * curve. */ - public static byte getMu(ECCurve.F2m curve) + public static byte getMu(ECCurve.AbstractF2m curve) { if (!curve.isKoblitz()) { @@ -420,6 +420,16 @@ class Tnaf return 1; } + public static byte getMu(ECFieldElement curveA) + { + return (byte)(curveA.isZero() ? -1 : 1); + } + + public static byte getMu(int curveA) + { + return (byte)(curveA == 0 ? -1 : 1); + } + /** * Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and * <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and @@ -525,16 +535,16 @@ class Tnaf * @throws IllegalArgumentException if <code>curve</code> is not a * Koblitz curve (Anomalous Binary Curve, ABC). */ - public static BigInteger[] getSi(ECCurve.F2m curve) + public static BigInteger[] getSi(ECCurve.AbstractF2m curve) { if (!curve.isKoblitz()) { throw new IllegalArgumentException("si is defined for Koblitz curves only"); } - int m = curve.getM(); + int m = curve.getFieldSize(); int a = curve.getA().toBigInteger().intValue(); - byte mu = curve.getMu(); + byte mu = getMu(a); int shifts = getShiftsForCofactor(curve.getCofactor()); int index = m + 3 - a; BigInteger[] ui = getLucas(mu, index, false); @@ -550,6 +560,24 @@ class Tnaf return new BigInteger[] { dividend0, dividend1 }; } + public static BigInteger[] getSi(int fieldSize, int curveA, BigInteger cofactor) + { + byte mu = getMu(curveA); + int shifts = getShiftsForCofactor(cofactor); + int index = fieldSize + 3 - curveA; + BigInteger[] ui = getLucas(mu, index, false); + if (mu == 1) + { + ui[0] = ui[0].negate(); + ui[1] = ui[1].negate(); + } + + BigInteger dividend0 = ECConstants.ONE.add(ui[1]).shiftRight(shifts); + BigInteger dividend1 = ECConstants.ONE.add(ui[0]).shiftRight(shifts).negate(); + + return new BigInteger[] { dividend0, dividend1 }; + } + protected static int getShiftsForCofactor(BigInteger h) { if (h != null) @@ -616,70 +644,77 @@ class Tnaf } /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} + * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.AbstractF2m ECPoint.AbstractF2m} * by a <code>BigInteger</code> using the reduced <code>τ</code>-adic * NAF (RTNAF) method. - * @param p The ECPoint.F2m to multiply. + * @param p The ECPoint.AbstractF2m to multiply. * @param k The <code>BigInteger</code> by which to multiply <code>p</code>. * @return <code>k * p</code> */ - public static ECPoint.F2m multiplyRTnaf(ECPoint.F2m p, BigInteger k) + public static ECPoint.AbstractF2m multiplyRTnaf(ECPoint.AbstractF2m p, BigInteger k) { - ECCurve.F2m curve = (ECCurve.F2m) p.getCurve(); - int m = curve.getM(); - byte a = (byte) curve.getA().toBigInteger().intValue(); - byte mu = curve.getMu(); + ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m) p.getCurve(); + int m = curve.getFieldSize(); + int a = curve.getA().toBigInteger().intValue(); + byte mu = getMu(a); BigInteger[] s = curve.getSi(); - ZTauElement rho = partModReduction(k, m, a, s, mu, (byte)10); + ZTauElement rho = partModReduction(k, m, (byte)a, s, mu, (byte)10); return multiplyTnaf(p, rho); } /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} + * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.AbstractF2m ECPoint.AbstractF2m} * by an element <code>λ</code> of <code><b>Z</b>[τ]</code> * using the <code>τ</code>-adic NAF (TNAF) method. - * @param p The ECPoint.F2m to multiply. + * @param p The ECPoint.AbstractF2m to multiply. * @param lambda The element <code>λ</code> of * <code><b>Z</b>[τ]</code>. * @return <code>λ * p</code> */ - public static ECPoint.F2m multiplyTnaf(ECPoint.F2m p, ZTauElement lambda) + public static ECPoint.AbstractF2m multiplyTnaf(ECPoint.AbstractF2m p, ZTauElement lambda) { - ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); - byte mu = curve.getMu(); + ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m)p.getCurve(); + byte mu = getMu(curve.getA()); byte[] u = tauAdicNaf(mu, lambda); - ECPoint.F2m q = multiplyFromTnaf(p, u); + ECPoint.AbstractF2m q = multiplyFromTnaf(p, u); return q; } /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} + * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.AbstractF2m ECPoint.AbstractF2m} * by an element <code>λ</code> of <code><b>Z</b>[τ]</code> * using the <code>τ</code>-adic NAF (TNAF) method, given the TNAF * of <code>λ</code>. - * @param p The ECPoint.F2m to multiply. + * @param p The ECPoint.AbstractF2m to multiply. * @param u The the TNAF of <code>λ</code>.. * @return <code>λ * p</code> */ - public static ECPoint.F2m multiplyFromTnaf(ECPoint.F2m p, byte[] u) + public static ECPoint.AbstractF2m multiplyFromTnaf(ECPoint.AbstractF2m p, byte[] u) { - ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); - ECPoint.F2m q = (ECPoint.F2m) curve.getInfinity(); + ECCurve curve = p.getCurve(); + ECPoint.AbstractF2m q = (ECPoint.AbstractF2m)curve.getInfinity(); + ECPoint.AbstractF2m pNeg = (ECPoint.AbstractF2m)p.negate(); + int tauCount = 0; for (int i = u.length - 1; i >= 0; i--) { - q = tau(q); - if (u[i] == 1) - { - q = (ECPoint.F2m)q.addSimple(p); - } - else if (u[i] == -1) + ++tauCount; + byte ui = u[i]; + if (ui != 0) { - q = (ECPoint.F2m)q.subtractSimple(p); + q = q.tauPow(tauCount); + tauCount = 0; + + ECPoint x = ui > 0 ? p : pNeg; + q = (ECPoint.AbstractF2m)q.add(x); } } + if (tauCount > 0) + { + q = q.tauPow(tauCount); + } return q; } @@ -794,26 +829,17 @@ class Tnaf * @param a The parameter <code>a</code> of the elliptic curve. * @return The precomputation array for <code>p</code>. */ - public static ECPoint.F2m[] getPreComp(ECPoint.F2m p, byte a) + public static ECPoint.AbstractF2m[] getPreComp(ECPoint.AbstractF2m p, byte a) { - ECPoint.F2m[] pu; - pu = new ECPoint.F2m[16]; - pu[1] = p; - byte[][] alphaTnaf; - if (a == 0) - { - alphaTnaf = Tnaf.alpha0Tnaf; - } - else - { - // a == 1 - alphaTnaf = Tnaf.alpha1Tnaf; - } + byte[][] alphaTnaf = (a == 0) ? Tnaf.alpha0Tnaf : Tnaf.alpha1Tnaf; + + ECPoint.AbstractF2m[] pu = new ECPoint.AbstractF2m[(alphaTnaf.length + 1) >>> 1]; + pu[0] = p; int precompLen = alphaTnaf.length; - for (int i = 3; i < precompLen; i = i + 2) + for (int i = 3; i < precompLen; i += 2) { - pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]); + pu[i >>> 1] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]); } p.getCurve().normalizeAll(pu); diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java index 93d03b46..7974e1d3 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java @@ -12,26 +12,26 @@ public class WTauNafMultiplier extends AbstractECMultiplier static final String PRECOMP_NAME = "bc_wtnaf"; /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} + * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.AbstractF2m ECPoint.AbstractF2m} * by <code>k</code> using the reduced <code>τ</code>-adic NAF (RTNAF) * method. - * @param p The ECPoint.F2m to multiply. + * @param point The ECPoint.AbstractF2m to multiply. * @param k The integer by which to multiply <code>k</code>. * @return <code>p</code> multiplied by <code>k</code>. */ protected ECPoint multiplyPositive(ECPoint point, BigInteger k) { - if (!(point instanceof ECPoint.F2m)) + if (!(point instanceof ECPoint.AbstractF2m)) { - throw new IllegalArgumentException("Only ECPoint.F2m can be " + + throw new IllegalArgumentException("Only ECPoint.AbstractF2m can be " + "used in WTauNafMultiplier"); } - ECPoint.F2m p = (ECPoint.F2m)point; - ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); - int m = curve.getM(); + ECPoint.AbstractF2m p = (ECPoint.AbstractF2m)point; + ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m)p.getCurve(); + int m = curve.getFieldSize(); byte a = curve.getA().toBigInteger().byteValue(); - byte mu = curve.getMu(); + byte mu = Tnaf.getMu(a); BigInteger[] s = curve.getSi(); ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10); @@ -40,16 +40,16 @@ public class WTauNafMultiplier extends AbstractECMultiplier } /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} + * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.AbstractF2m ECPoint.AbstractF2m} * by an element <code>λ</code> of <code><b>Z</b>[τ]</code> using * the <code>τ</code>-adic NAF (TNAF) method. - * @param p The ECPoint.F2m to multiply. + * @param p The ECPoint.AbstractF2m to multiply. * @param lambda The element <code>λ</code> of * <code><b>Z</b>[τ]</code> of which to compute the * <code>[τ]</code>-adic NAF. * @return <code>p</code> multiplied by <code>λ</code>. */ - private ECPoint.F2m multiplyWTnaf(ECPoint.F2m p, ZTauElement lambda, + private ECPoint.AbstractF2m multiplyWTnaf(ECPoint.AbstractF2m p, ZTauElement lambda, PreCompInfo preCompInfo, byte a, byte mu) { ZTauElement[] alpha = (a == 0) ? Tnaf.alpha0 : Tnaf.alpha1; @@ -63,20 +63,20 @@ public class WTauNafMultiplier extends AbstractECMultiplier } /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} + * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.AbstractF2m ECPoint.AbstractF2m} * by an element <code>λ</code> of <code><b>Z</b>[τ]</code> * using the window <code>τ</code>-adic NAF (TNAF) method, given the * WTNAF of <code>λ</code>. - * @param p The ECPoint.F2m to multiply. + * @param p The ECPoint.AbstractF2m to multiply. * @param u The the WTNAF of <code>λ</code>.. * @return <code>λ * p</code> */ - private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u, PreCompInfo preCompInfo) + private static ECPoint.AbstractF2m multiplyFromWTnaf(ECPoint.AbstractF2m p, byte[] u, PreCompInfo preCompInfo) { - ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); + ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m)p.getCurve(); byte a = curve.getA().toBigInteger().byteValue(); - ECPoint.F2m[] pu; + ECPoint.AbstractF2m[] pu; if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo)) { pu = Tnaf.getPreComp(p, a); @@ -90,25 +90,35 @@ public class WTauNafMultiplier extends AbstractECMultiplier pu = ((WTauNafPreCompInfo)preCompInfo).getPreComp(); } + // TODO Include negations in precomp (optionally) and use from here + ECPoint.AbstractF2m[] puNeg = new ECPoint.AbstractF2m[pu.length]; + for (int i = 0; i < pu.length; ++i) + { + puNeg[i] = (ECPoint.AbstractF2m)pu[i].negate(); + } + + // q = infinity - ECPoint.F2m q = (ECPoint.F2m) p.getCurve().getInfinity(); + ECPoint.AbstractF2m q = (ECPoint.AbstractF2m) p.getCurve().getInfinity(); + + int tauCount = 0; for (int i = u.length - 1; i >= 0; i--) { - q = Tnaf.tau(q); - byte ui = u[i]; + ++tauCount; + int ui = u[i]; if (ui != 0) { - if (ui > 0) - { - q = q.addSimple(pu[ui]); - } - else - { - q = q.subtractSimple(pu[-ui]); - } + q = q.tauPow(tauCount); + tauCount = 0; + + ECPoint x = ui > 0 ? pu[ui >>> 1] : puNeg[(-ui) >>> 1]; + q = (ECPoint.AbstractF2m)q.add(x); } } - + if (tauCount > 0) + { + q = q.tauPow(tauCount); + } return q; } } diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java index 190eecba..58006600 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java @@ -7,19 +7,17 @@ package org.bouncycastle.math.ec; public class WTauNafPreCompInfo implements PreCompInfo { /** - * Array holding the precomputed <code>ECPoint.F2m</code>s used for the - * WTNAF multiplication in <code> - * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() - * WTauNafMultiplier.multiply()}</code>. + * Array holding the precomputed <code>ECPoint.AbstractF2m</code>s used for the + * WTNAF multiplication. */ - protected ECPoint.F2m[] preComp = null; + protected ECPoint.AbstractF2m[] preComp = null; - public ECPoint.F2m[] getPreComp() + public ECPoint.AbstractF2m[] getPreComp() { return preComp; } - public void setPreComp(ECPoint.F2m[] preComp) + public void setPreComp(ECPoint.AbstractF2m[] preComp) { this.preComp = preComp; } diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java index 0032f357..642c44cd 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java @@ -130,10 +130,10 @@ public class SecP192K1FieldElement extends ECFieldElement { /* * Raise this element to the exponent 2^190 - 2^30 - 2^10 - 2^6 - 2^5 - 2^4 - 2^1 - * + * * Breaking up the exponent's binary representation into "repunits", we get: * { 159 1s } { 1 0s } { 19 1s } { 1 0s } { 3 1s } { 3 0s} { 3 1s } { 1 0s } - * + * * Therefore we need an addition chain containing 3, 19, 159 (the lengths of the repunits) * We use: 1, 2, [3], 6, 8, 16, [19], 35, 70, 140, [159] */ @@ -187,7 +187,7 @@ public class SecP192K1FieldElement extends ECFieldElement int[] t2 = x3; SecP192K1Field.square(t1, t2); - return Nat192.eq(x1, t2) ? new SecP192K1FieldElement(t1) : null; + return Nat192.eq(x1, t2) ? new SecP192K1FieldElement(t1) : null; } public boolean equals(Object other) diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java index eaa97277..e4ecf01d 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java @@ -10,14 +10,14 @@ public class SecP192K1Point extends ECPoint.AbstractFp { /** * Create a point which encodes with point compression. - * + * * @param curve * the curve to use * @param x * affine x co-ordinate * @param y * affine y co-ordinate - * + * * @deprecated Use ECCurve.createPoint to construct points */ public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) @@ -27,7 +27,7 @@ public class SecP192K1Point extends ECPoint.AbstractFp /** * Create a point that encodes with or without point compresion. - * + * * @param curve * the curve to use * @param x @@ -36,7 +36,7 @@ public class SecP192K1Point extends ECPoint.AbstractFp * affine y co-ordinate * @param withCompression * if true encode with point compression - * + * * @deprecated per-point compression property will be removed, refer * {@link #getEncoded(boolean)} */ @@ -210,7 +210,7 @@ public class SecP192K1Point extends ECPoint.AbstractFp SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.x, Z1 = (SecP192K1FieldElement)this.zs[0]; int c; - + int[] Y1Squared = Nat192.create(); SecP192K1Field.square(Y1.x, Y1Squared); diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java index c8f5eed5..75e2f5c2 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java @@ -168,7 +168,7 @@ public class SecP192R1Field if (x != 0) { long xx06 = x & M; - + cc += (z[0] & M) + xx06; z[0] = (int)cc; cc >>= 32; diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java index 3ed72f85..f60fc131 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java @@ -10,14 +10,14 @@ public class SecP192R1Point extends ECPoint.AbstractFp { /** * Create a point which encodes with point compression. - * + * * @param curve * the curve to use * @param x * affine x co-ordinate * @param y * affine y co-ordinate - * + * * @deprecated Use ECCurve.createPoint to construct points */ public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) @@ -27,7 +27,7 @@ public class SecP192R1Point extends ECPoint.AbstractFp /** * Create a point that encodes with or without point compresion. - * + * * @param curve * the curve to use * @param x @@ -36,7 +36,7 @@ public class SecP192R1Point extends ECPoint.AbstractFp * affine y co-ordinate * @param withCompression * if true encode with point compression - * + * * @deprecated per-point compression property will be removed, refer * {@link #getEncoded(boolean)} */ diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java index 73f19993..8285a4e9 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java @@ -137,10 +137,10 @@ public class SecP224K1FieldElement extends ECFieldElement * Q == 8m + 5, so we use Pocklington's method for this case. * * First, raise this element to the exponent 2^221 - 2^29 - 2^9 - 2^8 - 2^6 - 2^4 - 2^1 (i.e. m + 1) - * + * * Breaking up the exponent's binary representation into "repunits", we get: * { 191 1s } { 1 0s } { 19 1s } { 2 0s } { 1 1s } { 1 0s} { 1 1s } { 1 0s} { 3 1s } { 1 0s} - * + * * Therefore we need an addition chain containing 1, 3, 19, 191 (the lengths of the repunits) * We use: [1], 2, [3], 4, 8, 11, [19], 23, 42, 84, 107, [191] */ diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java index 114623dc..a4d37b5f 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java @@ -10,14 +10,14 @@ public class SecP224K1Point extends ECPoint.AbstractFp { /** * Create a point which encodes with point compression. - * + * * @param curve * the curve to use * @param x * affine x co-ordinate * @param y * affine y co-ordinate - * + * * @deprecated Use ECCurve.createPoint to construct points */ public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) @@ -27,7 +27,7 @@ public class SecP224K1Point extends ECPoint.AbstractFp /** * Create a point that encodes with or without point compresion. - * + * * @param curve * the curve to use * @param x @@ -36,7 +36,7 @@ public class SecP224K1Point extends ECPoint.AbstractFp * affine y co-ordinate * @param withCompression * if true encode with point compression - * + * * @deprecated per-point compression property will be removed, refer * {@link #getEncoded(boolean)} */ @@ -210,7 +210,7 @@ public class SecP224K1Point extends ECPoint.AbstractFp SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.x, Z1 = (SecP224K1FieldElement)this.zs[0]; int c; - + int[] Y1Squared = Nat224.create(); SecP224K1Field.square(Y1.x, Y1Squared); diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java index 02a86f0f..e05f6775 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java @@ -171,7 +171,7 @@ public class SecP224R1Field if (x != 0) { long xx07 = x & M; - + cc += (z[0] & M) - xx07; z[0] = (int)cc; cc >>= 32; diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java index df10b9b4..31da6f60 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java @@ -10,14 +10,14 @@ public class SecP224R1Point extends ECPoint.AbstractFp { /** * Create a point which encodes with point compression. - * + * * @param curve * the curve to use * @param x * affine x co-ordinate * @param y * affine y co-ordinate - * + * * @deprecated Use ECCurve.createPoint to construct points */ public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) @@ -27,7 +27,7 @@ public class SecP224R1Point extends ECPoint.AbstractFp /** * Create a point that encodes with or without point compresion. - * + * * @param curve * the curve to use * @param x @@ -36,7 +36,7 @@ public class SecP224R1Point extends ECPoint.AbstractFp * affine y co-ordinate * @param withCompression * if true encode with point compression - * + * * @deprecated per-point compression property will be removed, refer * {@link #getEncoded(boolean)} */ diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java index 0f7e2951..467b17f5 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java @@ -131,10 +131,10 @@ public class SecP256K1FieldElement extends ECFieldElement { /* * Raise this element to the exponent 2^254 - 2^30 - 2^7 - 2^6 - 2^5 - 2^4 - 2^2 - * + * * Breaking up the exponent's binary representation into "repunits", we get: * { 223 1s } { 1 0s } { 22 1s } { 4 0s } { 2 1s } { 2 0s} - * + * * Therefore we need an addition chain containing 2, 22, 223 (the lengths of the repunits) * We use: 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] */ @@ -189,7 +189,7 @@ public class SecP256K1FieldElement extends ECFieldElement int[] t2 = x2; SecP256K1Field.square(t1, t2); - return Nat256.eq(x1, t2) ? new SecP256K1FieldElement(t1) : null; + return Nat256.eq(x1, t2) ? new SecP256K1FieldElement(t1) : null; } public boolean equals(Object other) diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java index f57b200a..43c9c558 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java @@ -10,14 +10,14 @@ public class SecP256K1Point extends ECPoint.AbstractFp { /** * Create a point which encodes with point compression. - * + * * @param curve * the curve to use * @param x * affine x co-ordinate * @param y * affine y co-ordinate - * + * * @deprecated Use ECCurve.createPoint to construct points */ public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) @@ -27,7 +27,7 @@ public class SecP256K1Point extends ECPoint.AbstractFp /** * Create a point that encodes with or without point compresion. - * + * * @param curve * the curve to use * @param x @@ -36,7 +36,7 @@ public class SecP256K1Point extends ECPoint.AbstractFp * affine y co-ordinate * @param withCompression * if true encode with point compression - * + * * @deprecated per-point compression property will be removed, refer * {@link #getEncoded(boolean)} */ @@ -210,7 +210,7 @@ public class SecP256K1Point extends ECPoint.AbstractFp SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.x, Z1 = (SecP256K1FieldElement)this.zs[0]; int c; - + int[] Y1Squared = Nat256.create(); SecP256K1Field.square(Y1.x, Y1Squared); diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java index 985cb0e2..5a066d81 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java @@ -30,7 +30,7 @@ public class SecP256R1Field public static void addExt(int[] xx, int[] yy, int[] zz) { int c = Nat.add(16, xx, yy, zz); - if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt))) + if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt))) { Nat.subFrom(16, PExt, zz); } @@ -78,7 +78,7 @@ public class SecP256R1Field public static void multiplyAddToExt(int[] x, int[] y, int[] zz) { int c = Nat256.mulAddTo(x, y, zz); - if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt))) + if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt))) { Nat.subFrom(16, PExt, zz); } diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java index 930fdc58..78b5ff8f 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java @@ -10,14 +10,14 @@ public class SecP256R1Point extends ECPoint.AbstractFp { /** * Create a point which encodes with point compression. - * + * * @param curve * the curve to use * @param x * affine x co-ordinate * @param y * affine y co-ordinate - * + * * @deprecated Use ECCurve.createPoint to construct points */ public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) @@ -27,7 +27,7 @@ public class SecP256R1Point extends ECPoint.AbstractFp /** * Create a point that encodes with or without point compresion. - * + * * @param curve * the curve to use * @param x @@ -36,7 +36,7 @@ public class SecP256R1Point extends ECPoint.AbstractFp * affine y co-ordinate * @param withCompression * if true encode with point compression - * + * * @deprecated per-point compression property will be removed, refer * {@link #getEncoded(boolean)} */ diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java index f321a105..fcbb8727 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java @@ -155,11 +155,11 @@ public class SecP384R1Field public static void reduce32(int x, int[] z) { long cc = 0; - + if (x != 0) { long xx12 = x & M; - + cc += (z[0] & M) + xx12; z[0] = (int)cc; cc >>= 32; diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java index 89f6bf4f..32c3b3f0 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java @@ -10,14 +10,14 @@ public class SecP384R1Point extends ECPoint.AbstractFp { /** * Create a point which encodes with point compression. - * + * * @param curve * the curve to use * @param x * affine x co-ordinate * @param y * affine y co-ordinate - * + * * @deprecated Use ECCurve.createPoint to construct points */ public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) @@ -27,7 +27,7 @@ public class SecP384R1Point extends ECPoint.AbstractFp /** * Create a point that encodes with or without point compresion. - * + * * @param curve * the curve to use * @param x @@ -36,7 +36,7 @@ public class SecP384R1Point extends ECPoint.AbstractFp * affine y co-ordinate * @param withCompression * if true encode with point compression - * + * * @deprecated per-point compression property will be removed, refer * {@link #getEncoded(boolean)} */ diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java index d9737152..d0445fa7 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java @@ -9,14 +9,14 @@ public class SecP521R1Point extends ECPoint.AbstractFp { /** * Create a point which encodes with point compression. - * + * * @param curve * the curve to use * @param x * affine x co-ordinate * @param y * affine y co-ordinate - * + * * @deprecated Use ECCurve.createPoint to construct points */ public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) @@ -26,7 +26,7 @@ public class SecP521R1Point extends ECPoint.AbstractFp /** * Create a point that encodes with or without point compresion. - * + * * @param curve * the curve to use * @param x @@ -35,7 +35,7 @@ public class SecP521R1Point extends ECPoint.AbstractFp * affine y co-ordinate * @param withCompression * if true encode with point compression - * + * * @deprecated per-point compression property will be removed, refer * {@link #getEncoded(boolean)} */ diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java index ab710d1a..38591c05 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java @@ -26,9 +26,9 @@ public class GLVTypeBEndomorphism implements GLVEndomorphism BigInteger b1 = calculateB(k, parameters.getG1(), bits); BigInteger b2 = calculateB(k, parameters.getG2(), bits); - BigInteger[] v1 = parameters.getV1(), v2 = parameters.getV2(); - BigInteger a = k.subtract((b1.multiply(v1[0])).add(b2.multiply(v2[0]))); - BigInteger b = (b1.multiply(v1[1])).add(b2.multiply(v2[1])).negate(); + GLVTypeBParameters p = parameters; + BigInteger a = k.subtract((b1.multiply(p.getV1A())).add(b2.multiply(p.getV2A()))); + BigInteger b = (b1.multiply(p.getV1B())).add(b2.multiply(p.getV2B())).negate(); return new BigInteger[]{ a, b }; } diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java index f02a882f..92c175ab 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java @@ -4,19 +4,32 @@ import java.math.BigInteger; public class GLVTypeBParameters { + private static void checkVector(BigInteger[] v, String name) + { + if (v == null || v.length != 2 || v[0] == null || v[1] == null) + { + throw new IllegalArgumentException("'" + name + "' must consist of exactly 2 (non-null) values"); + } + } + protected final BigInteger beta; protected final BigInteger lambda; - protected final BigInteger[] v1, v2; + protected final BigInteger v1A, v1B, v2A, v2B; protected final BigInteger g1, g2; protected final int bits; public GLVTypeBParameters(BigInteger beta, BigInteger lambda, BigInteger[] v1, BigInteger[] v2, BigInteger g1, BigInteger g2, int bits) { + checkVector(v1, "v1"); + checkVector(v2, "v2"); + this.beta = beta; this.lambda = lambda; - this.v1 = v1; - this.v2 = v2; + this.v1A = v1[0]; + this.v1B = v1[1]; + this.v2A = v2[0]; + this.v2B = v2[1]; this.g1 = g1; this.g2 = g2; this.bits = bits; @@ -32,14 +45,40 @@ public class GLVTypeBParameters return lambda; } + /** + * @deprecated Use {@link #getV1A()} and {@link #getV1B()} instead. + */ public BigInteger[] getV1() { - return v1; + return new BigInteger[]{ v1A, v1B }; + } + + public BigInteger getV1A() + { + return v1A; + } + + public BigInteger getV1B() + { + return v1B; } + /** + * @deprecated Use {@link #getV2A()} and {@link #getV2B()} instead. + */ public BigInteger[] getV2() { - return v2; + return new BigInteger[]{ v2A, v2B }; + } + + public BigInteger getV2A() + { + return v2A; + } + + public BigInteger getV2B() + { + return v2B; } public BigInteger getG1() diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java index 75e15434..2057c8bc 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java +++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java @@ -211,6 +211,11 @@ public abstract class Nat return new int[len]; } + public static long[] create64(int len) + { + return new long[len]; + } + public static int dec(int len, int[] z) { for (int i = 0; i < len; ++i) @@ -691,6 +696,17 @@ public abstract class Nat return c >>> 31; } + public static long shiftUpBit64(int len, long[] x, int xOff, long c, long[] z, int zOff) + { + for (int i = 0; i < len; ++i) + { + long next = x[xOff + i]; + z[zOff + i] = (next << 1) | (c >>> 63); + c = next; + } + return c >>> 63; + } + public static int shiftUpBits(int len, int[] z, int bits, int c) { // assert bits > 0 && bits < 32; @@ -715,6 +731,18 @@ public abstract class Nat return c >>> -bits; } + public static long shiftUpBits64(int len, long[] z, int zOff, int bits, long c) + { +// assert bits > 0 && bits < 64; + for (int i = 0; i < len; ++i) + { + long next = z[zOff + i]; + z[zOff + i] = (next << bits) | (c >>> -bits); + c = next; + } + return c >>> -bits; + } + public static int shiftUpBits(int len, int[] x, int bits, int c, int[] z) { // assert bits > 0 && bits < 32; @@ -739,6 +767,18 @@ public abstract class Nat return c >>> -bits; } + public static long shiftUpBits64(int len, long[] x, int xOff, int bits, long c, long[] z, int zOff) + { +// assert bits > 0 && bits < 64; + for (int i = 0; i < len; ++i) + { + long next = x[xOff + i]; + z[zOff + i] = (next << bits) | (c >>> -bits); + c = next; + } + return c >>> -bits; + } + public static void square(int len, int[] x, int[] zz) { int extLen = len << 1; diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java index e7e3dfa5..421883e0 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java +++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java @@ -144,16 +144,33 @@ public abstract class Nat192 z[5] = x[5]; } + public static void copy64(long[] x, long[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + } + public static int[] create() { return new int[6]; } + public static long[] create64() + { + return new long[3]; + } + public static int[] createExt() { return new int[12]; } + public static long[] createExt64() + { + return new long[6]; + } + public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) { boolean pos = gte(x, xOff, y, yOff); @@ -180,6 +197,18 @@ public abstract class Nat192 return true; } + public static boolean eq64(long[] x, long[] y) + { + for (int i = 2; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + public static int[] fromBigInteger(BigInteger x) { if (x.signum() < 0 || x.bitLength() > 192) @@ -197,6 +226,23 @@ public abstract class Nat192 return z; } + public static long[] fromBigInteger64(BigInteger x) + { + if (x.signum() < 0 || x.bitLength() > 192) + { + throw new IllegalArgumentException(); + } + + long[] z = create64(); + int i = 0; + while (x.signum() != 0) + { + z[i++] = x.longValue(); + x = x.shiftRight(64); + } + return z; + } + public static int getBit(int[] x, int bit) { if (bit == 0) @@ -256,6 +302,22 @@ public abstract class Nat192 return true; } + public static boolean isOne64(long[] x) + { + if (x[0] != 1L) + { + return false; + } + for (int i = 1; i < 3; ++i) + { + if (x[i] != 0L) + { + return false; + } + } + return true; + } + public static boolean isZero(int[] x) { for (int i = 0; i < 6; ++i) @@ -268,6 +330,18 @@ public abstract class Nat192 return true; } + public static boolean isZero64(long[] x) + { + for (int i = 0; i < 3; ++i) + { + if (x[i] != 0L) + { + return false; + } + } + return true; + } + public static void mul(int[] x, int[] y, int[] zz) { long y_0 = y[0] & M; @@ -956,6 +1030,20 @@ public abstract class Nat192 return new BigInteger(1, bs); } + public static BigInteger toBigInteger64(long[] x) + { + byte[] bs = new byte[24]; + for (int i = 0; i < 3; ++i) + { + long x_i = x[i]; + if (x_i != 0L) + { + Pack.longToBigEndian(x_i, bs, (2 - i) << 3); + } + } + return new BigInteger(1, bs); + } + public static void zero(int[] z) { z[0] = 0; diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java index 9886678a..db1daac0 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java +++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java @@ -238,16 +238,34 @@ public abstract class Nat256 z[7] = x[7]; } + public static void copy64(long[] x, long[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + } + public static int[] create() { return new int[8]; } + public static long[] create64() + { + return new long[4]; + } + public static int[] createExt() { return new int[16]; } + public static long[] createExt64() + { + return new long[8]; + } + public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) { boolean pos = gte(x, xOff, y, yOff); @@ -274,6 +292,18 @@ public abstract class Nat256 return true; } + public static boolean eq64(long[] x, long[] y) + { + for (int i = 3; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + public static int[] fromBigInteger(BigInteger x) { if (x.signum() < 0 || x.bitLength() > 256) @@ -291,6 +321,23 @@ public abstract class Nat256 return z; } + public static long[] fromBigInteger64(BigInteger x) + { + if (x.signum() < 0 || x.bitLength() > 256) + { + throw new IllegalArgumentException(); + } + + long[] z = create64(); + int i = 0; + while (x.signum() != 0) + { + z[i++] = x.longValue(); + x = x.shiftRight(64); + } + return z; + } + public static int getBit(int[] x, int bit) { if (bit == 0) @@ -350,6 +397,22 @@ public abstract class Nat256 return true; } + public static boolean isOne64(long[] x) + { + if (x[0] != 1L) + { + return false; + } + for (int i = 1; i < 4; ++i) + { + if (x[i] != 0L) + { + return false; + } + } + return true; + } + public static boolean isZero(int[] x) { for (int i = 0; i < 8; ++i) @@ -362,6 +425,18 @@ public abstract class Nat256 return true; } + public static boolean isZero64(long[] x) + { + for (int i = 0; i < 4; ++i) + { + if (x[i] != 0L) + { + return false; + } + } + return true; + } + public static void mul(int[] x, int[] y, int[] zz) { long y_0 = y[0] & M; @@ -1292,6 +1367,20 @@ public abstract class Nat256 return new BigInteger(1, bs); } + public static BigInteger toBigInteger64(long[] x) + { + byte[] bs = new byte[32]; + for (int i = 0; i < 4; ++i) + { + long x_i = x[i]; + if (x_i != 0L) + { + Pack.longToBigEndian(x_i, bs, (3 - i) << 3); + } + } + return new BigInteger(1, bs); + } + public static void zero(int[] z) { z[0] = 0; diff --git a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java index 3c0646ab..99325a9f 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java @@ -1,7 +1,7 @@ package org.bouncycastle.util; import java.math.BigInteger; -import java.util.Iterator; +import java.util.NoSuchElementException; /** * General array utilities. @@ -324,7 +324,7 @@ public final class Arrays return hc; } - + public static int hashCode(byte[] data, int off, int len) { if (data == null) @@ -413,6 +413,50 @@ public final class Arrays return hc; } + public static int hashCode(long[] data) + { + if (data == null) + { + return 0; + } + + int i = data.length; + int hc = i + 1; + + while (--i >= 0) + { + long di = data[i]; + hc *= 257; + hc ^= (int)di; + hc *= 257; + hc ^= (int)(di >>> 32); + } + + return hc; + } + + public static int hashCode(long[] data, int off, int len) + { + if (data == null) + { + return 0; + } + + int i = len; + int hc = i + 1; + + while (--i >= 0) + { + long di = data[off + i]; + hc *= 257; + hc ^= (int)di; + hc *= 257; + hc ^= (int)(di >>> 32); + } + + return hc; + } + public static int hashCode(short[][][] shorts) { int hc = 0; @@ -488,6 +532,19 @@ public final class Arrays return copy; } + public static char[] clone(char[] data) + { + if (data == null) + { + return null; + } + char[] copy = new char[data.length]; + + System.arraycopy(data, 0, copy, 0, data.length); + + return copy; + } + public static byte[] clone(byte[] data, byte[] existing) { if (data == null) @@ -852,6 +909,10 @@ public final class Arrays return rv; } + else if (a == null) + { + return concatenate(b, c); + } else if (b == null) { return concatenate(a, c); @@ -970,6 +1031,24 @@ public final class Arrays return result; } + public static int[] reverse(int[] a) + { + if (a == null) + { + return null; + } + + int p1 = 0, p2 = a.length; + int[] result = new int[p2]; + + while (--p2 >= 0) + { + result[p2] = a[p1++]; + } + + return result; + } + /** * Iterator backed by a specific array. */ @@ -1000,6 +1079,11 @@ public final class Arrays public T next() { + if (position == dataArray.length) + { + throw new NoSuchElementException("Out of elements: " + position); + } + return dataArray[position++]; } diff --git a/bcprov/src/main/java/org/bouncycastle/util/IPAddress.java b/bcprov/src/main/java/org/bouncycastle/util/IPAddress.java index 9f5d1cbc..8af1709e 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/IPAddress.java +++ b/bcprov/src/main/java/org/bouncycastle/util/IPAddress.java @@ -1,5 +1,8 @@ package org.bouncycastle.util; +/** + * Utility methods for processing String objects containing IP addresses. + */ public class IPAddress { /** diff --git a/bcprov/src/main/java/org/bouncycastle/util/Integers.java b/bcprov/src/main/java/org/bouncycastle/util/Integers.java index f52baf52..cbae4a37 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Integers.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Integers.java @@ -1,5 +1,8 @@ package org.bouncycastle.util; +/** + * Utility methods for ints. + */ public class Integers { public static int rotateLeft(int i, int distance) diff --git a/bcprov/src/main/java/org/bouncycastle/util/Memoable.java b/bcprov/src/main/java/org/bouncycastle/util/Memoable.java index ee0bedac..bf40f4eb 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Memoable.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Memoable.java @@ -1,5 +1,9 @@ package org.bouncycastle.util; +/** + * Interface for Memoable objects. Memoable objects allow the taking of a snapshot of their internal state + * via the copy() method and then reseting the object back to that state later using the reset() method. + */ public interface Memoable { /** @@ -8,7 +12,7 @@ public interface Memoable * The returned object may be used simply to store the state, or may be used as a similar object * starting from the copied state. */ - public Memoable copy(); + Memoable copy(); /** * Restore a copied object state into this object. @@ -19,5 +23,5 @@ public interface Memoable * @throws ClassCastException if the provided object is not of the correct type. * @throws MemoableResetException if the <b>other</b> parameter is in some other way invalid. */ - public void reset(Memoable other); + void reset(Memoable other); } diff --git a/bcprov/src/main/java/org/bouncycastle/util/Pack.java b/bcprov/src/main/java/org/bouncycastle/util/Pack.java index 2f96af84..94ba17b1 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Pack.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Pack.java @@ -1,5 +1,8 @@ package org.bouncycastle.util; +/** + * Utility methods for converting byte arrays into ints and longs, and back again. + */ public abstract class Pack { public static int bigEndianToInt(byte[] bs, int off) diff --git a/bcprov/src/main/java/org/bouncycastle/util/Properties.java b/bcprov/src/main/java/org/bouncycastle/util/Properties.java new file mode 100644 index 00000000..96cef357 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/util/Properties.java @@ -0,0 +1,36 @@ +package org.bouncycastle.util; + +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Utility method for accessing system properties. + */ +public class Properties +{ + public static boolean isOverrideSet(final String propertyName) + { + try + { + return "true".equals(AccessController.doPrivileged(new PrivilegedAction() + { + // JDK 1.4 compatibility + public Object run() + { + String value = System.getProperty(propertyName); + if (value == null) + { + return null; + } + + return Strings.toLowerCase(value); + } + })); + } + catch (AccessControlException e) + { + return false; + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/util/Selector.java b/bcprov/src/main/java/org/bouncycastle/util/Selector.java index a3a5ec86..f3366c7d 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Selector.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Selector.java @@ -1,8 +1,19 @@ package org.bouncycastle.util; +/** + * Interface a selector from a store should conform to. + * + * @param <T> the type stored in the store. + */ public interface Selector<T> extends Cloneable { + /** + * Match the passed in object, returning true if it would be selected by this selector, false otherwise. + * + * @param obj the object to be matched. + * @return true if the object is a match for this selector, false otherwise. + */ boolean match(T obj); Object clone(); diff --git a/bcprov/src/main/java/org/bouncycastle/util/Store.java b/bcprov/src/main/java/org/bouncycastle/util/Store.java index fd28b838..0f55039e 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Store.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Store.java @@ -2,8 +2,21 @@ package org.bouncycastle.util; import java.util.Collection; +/** + * A generic interface describing a simple store of objects. + * + * @param <T> the object type stored. + */ public interface Store<T> { + /** + * Return a possibly empty collection of objects that match the criteria implemented + * in the passed in Selector. + * + * @param selector the selector defining the match criteria. + * @return a collection of matching objects, empty if none available. + * @throws StoreException if there is a failure during matching. + */ Collection<T> getMatches(Selector<T> selector) throws StoreException; } diff --git a/bcprov/src/main/java/org/bouncycastle/util/StoreException.java b/bcprov/src/main/java/org/bouncycastle/util/StoreException.java index 5ea09e80..7cca2716 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/StoreException.java +++ b/bcprov/src/main/java/org/bouncycastle/util/StoreException.java @@ -1,14 +1,23 @@ package org.bouncycastle.util; +/** + * Exception thrown if there's an issue doing a match in store. + */ public class StoreException extends RuntimeException { private Throwable _e; - public StoreException(String s, Throwable e) + /** + * Basic Constructor. + * + * @param msg message to be associated with this exception. + * @param cause the throwable that caused this exception to be raised. + */ + public StoreException(String msg, Throwable cause) { - super(s); - _e = e; + super(msg); + _e = cause; } public Throwable getCause() diff --git a/bcprov/src/main/java/org/bouncycastle/util/StringList.java b/bcprov/src/main/java/org/bouncycastle/util/StringList.java index e7334427..4eb85141 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/StringList.java +++ b/bcprov/src/main/java/org/bouncycastle/util/StringList.java @@ -1,14 +1,34 @@ package org.bouncycastle.util; +/** + * An interface defining a list of strings. + */ public interface StringList extends Iterable<String> { + /** + * Add a String to the list. + * + * @param s the String to add. + * @return true + */ boolean add(String s); + /** + * Get the string at index index. + * + * @param index the index position of the String of interest. + * @return the String at position index. + */ String get(int index); int size(); + /** + * Return the contents of the list as an array. + * + * @return an array of String. + */ String[] toStringArray(); /** diff --git a/bcprov/src/main/java/org/bouncycastle/util/Strings.java b/bcprov/src/main/java/org/bouncycastle/util/Strings.java index 44ff3aec..a42830b3 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Strings.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Strings.java @@ -3,11 +3,46 @@ package org.bouncycastle.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Vector; +/** + * String utilities. + */ public final class Strings { + private static String LINE_SEPARATOR; + + static + { + try + { + LINE_SEPARATOR = AccessController.doPrivileged(new PrivilegedAction<String>() + { + public String run() + { + // the easy way + return System.getProperty("line.separator"); + } + }); + + } + catch (Exception e) + { + try + { + // the harder way + LINE_SEPARATOR = String.format("%n"); + } + catch (Exception ef) + { + LINE_SEPARATOR = "\n"; // we're desperate use this... + } + } + } + public static String fromUTF8ByteArray(byte[] bytes) { int i = 0; @@ -47,7 +82,7 @@ public final class Strings if ((bytes[i] & 0xf0) == 0xf0) { - int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F); + int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i + 1] & 0x3F) << 12) | ((bytes[i + 2] & 0x3F) << 6) | (bytes[i + 3] & 0x3F); int U = codePoint - 0x10000; char W1 = (char)(0xD800 | (U >> 10)); char W2 = (char)(0xDC00 | (U & 0x3FF)); @@ -58,7 +93,7 @@ public final class Strings else if ((bytes[i] & 0xe0) == 0xe0) { ch = (char)(((bytes[i] & 0x0f) << 12) - | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f)); + | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f)); i += 3; } else if ((bytes[i] & 0xd0) == 0xd0) @@ -82,7 +117,7 @@ public final class Strings return new String(cs); } - + public static byte[] toUTF8ByteArray(String string) { return toUTF8ByteArray(string.toCharArray()); @@ -100,7 +135,7 @@ public final class Strings { throw new IllegalStateException("cannot encode string to byte array!"); } - + return bOut.toByteArray(); } @@ -160,7 +195,7 @@ public final class Strings /** * A locale independent version of toUpperCase. - * + * * @param string input to be converted * @return a US Ascii uppercase version */ @@ -168,7 +203,7 @@ public final class Strings { boolean changed = false; char[] chars = string.toCharArray(); - + for (int i = 0; i != chars.length; i++) { char ch = chars[i]; @@ -178,18 +213,18 @@ public final class Strings chars[i] = (char)(ch - 'a' + 'A'); } } - + if (changed) { return new String(chars); } - + return string; } - + /** * A locale independent version of toLowerCase. - * + * * @param string input to be converted * @return a US ASCII lowercase version */ @@ -197,7 +232,7 @@ public final class Strings { boolean changed = false; char[] chars = string.toCharArray(); - + for (int i = 0; i != chars.length; i++) { char ch = chars[i]; @@ -207,12 +242,12 @@ public final class Strings chars[i] = (char)(ch - 'A' + 'a'); } } - + if (changed) { return new String(chars); } - + return string; } @@ -284,7 +319,7 @@ public final class Strings public static String[] split(String input, char delimiter) { - Vector v = new Vector(); + Vector v = new Vector(); boolean moreTokens = true; String subString; @@ -318,6 +353,11 @@ public final class Strings return new StringListImpl(); } + public static String lineSeparator() + { + return LINE_SEPARATOR; + } + private static class StringListImpl extends ArrayList<String> implements StringList diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java b/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java index 0dea2369..f39e026e 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java +++ b/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java @@ -10,7 +10,7 @@ import java.io.OutputStream; */ public final class Streams { - private static int BUFFER_SIZE = 512; + private static int BUFFER_SIZE = 4096; /** * Read stream till EOF is encountered. @@ -133,11 +133,11 @@ public final class Streams int numRead; while ((numRead = inStr.read(bs, 0, bs.length)) >= 0) { - total += numRead; - if (total > limit) + if ((limit - total) < numRead) { throw new StreamOverflowException("Data Overflow"); } + total += numRead; outStr.write(bs, 0, numRead); } return total; diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java index ccefa36e..b4964475 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java +++ b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.Writer; import java.util.Iterator; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Base64; /** @@ -27,7 +28,7 @@ public class PemWriter { super(out); - String nl = System.getProperty("line.separator"); + String nl = Strings.lineSeparator(); if (nl != null) { nlLength = nl.length(); diff --git a/bcprov/src/main/java/org/bouncycastle/x509/AttributeCertificateHolder.java b/bcprov/src/main/java/org/bouncycastle/x509/AttributeCertificateHolder.java index b00cd1d4..15375ab1 100644 --- a/bcprov/src/main/java/org/bouncycastle/x509/AttributeCertificateHolder.java +++ b/bcprov/src/main/java/org/bouncycastle/x509/AttributeCertificateHolder.java @@ -126,7 +126,7 @@ public class AttributeCertificateHolder String digestAlgorithm, String otherObjectTypeID, byte[] objectDigest) { holder = new Holder(new ObjectDigestInfo(digestedObjectType, - new ASN1ObjectIdentifier(otherObjectTypeID), new AlgorithmIdentifier(digestAlgorithm), Arrays + new ASN1ObjectIdentifier(otherObjectTypeID), new AlgorithmIdentifier(new ASN1ObjectIdentifier(digestAlgorithm)), Arrays .clone(objectDigest))); } @@ -164,7 +164,7 @@ public class AttributeCertificateHolder { if (holder.getObjectDigestInfo() != null) { - return holder.getObjectDigestInfo().getDigestAlgorithm().getObjectId() + return holder.getObjectDigestInfo().getDigestAlgorithm().getAlgorithm() .getId(); } return null; @@ -322,7 +322,7 @@ public class AttributeCertificateHolder public Object clone() { return new AttributeCertificateHolder((ASN1Sequence)holder - .toASN1Object()); + .toASN1Primitive()); } public boolean match(Certificate cert) diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509Attribute.java b/bcprov/src/main/java/org/bouncycastle/x509/X509Attribute.java index 95da2925..f5e9531b 100644 --- a/bcprov/src/main/java/org/bouncycastle/x509/X509Attribute.java +++ b/bcprov/src/main/java/org/bouncycastle/x509/X509Attribute.java @@ -11,6 +11,7 @@ import org.bouncycastle.asn1.x509.Attribute; /** * Class for carrying the values in an X.509 Attribute. + * @deprecated see X509CertificateHolder class in the PKIX package. */ public class X509Attribute extends ASN1Object diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java b/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java index f7ff3e43..01f4469f 100644 --- a/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java @@ -1,6 +1,5 @@ package org.bouncycastle.x509; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.GeneralSecurityException; @@ -20,10 +19,8 @@ import java.util.Iterator; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; @@ -143,8 +140,7 @@ public class X509V1CertificateGenerator { try { - tbsGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream( - new ByteArrayInputStream(key.getEncoded())).readObject())); + tbsGen.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(key.getEncoded())); } catch (Exception e) { diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509V2AttributeCertificate.java b/bcprov/src/main/java/org/bouncycastle/x509/X509V2AttributeCertificate.java index 14db8eab..61319a85 100644 --- a/bcprov/src/main/java/org/bouncycastle/x509/X509V2AttributeCertificate.java +++ b/bcprov/src/main/java/org/bouncycastle/x509/X509V2AttributeCertificate.java @@ -103,7 +103,7 @@ public class X509V2AttributeCertificate public AttributeCertificateHolder getHolder() { - return new AttributeCertificateHolder((ASN1Sequence)cert.getAcinfo().getHolder().toASN1Object()); + return new AttributeCertificateHolder((ASN1Sequence)cert.getAcinfo().getHolder().toASN1Primitive()); } public AttributeCertificateIssuer getIssuer() @@ -164,7 +164,7 @@ public class X509V2AttributeCertificate public byte[] getSignature() { - return cert.getSignatureValue().getBytes(); + return cert.getSignatureValue().getOctets(); } public final void verify( @@ -180,7 +180,7 @@ public class X509V2AttributeCertificate throw new CertificateException("Signature algorithm in certificate info not same as outer certificate"); } - signature = Signature.getInstance(cert.getSignatureAlgorithm().getObjectId().getId(), provider); + signature = Signature.getInstance(cert.getSignatureAlgorithm().getAlgorithm().getId(), provider); signature.initVerify(key); diff --git a/bcprov/src/main/java/org/bouncycastle/x509/extension/AuthorityKeyIdentifierStructure.java b/bcprov/src/main/java/org/bouncycastle/x509/extension/AuthorityKeyIdentifierStructure.java index 2164d1fb..bcd59932 100644 --- a/bcprov/src/main/java/org/bouncycastle/x509/extension/AuthorityKeyIdentifierStructure.java +++ b/bcprov/src/main/java/org/bouncycastle/x509/extension/AuthorityKeyIdentifierStructure.java @@ -6,7 +6,6 @@ import java.security.PublicKey; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; -import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; @@ -15,7 +14,6 @@ import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.X509Extension; -import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.jce.PrincipalUtil; /** @@ -70,32 +68,30 @@ public class AuthorityKeyIdentifierStructure if (certificate.getVersion() != 3) { GeneralName genName = new GeneralName(PrincipalUtil.getIssuerX509Principal(certificate)); - SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( - (ASN1Sequence)new ASN1InputStream(certificate.getPublicKey().getEncoded()).readObject()); + SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(certificate.getPublicKey().getEncoded()); return (ASN1Sequence)new AuthorityKeyIdentifier( - info, new GeneralNames(genName), certificate.getSerialNumber()).toASN1Object(); + info, new GeneralNames(genName), certificate.getSerialNumber()).toASN1Primitive(); } else { GeneralName genName = new GeneralName(PrincipalUtil.getIssuerX509Principal(certificate)); - byte[] ext = certificate.getExtensionValue(X509Extensions.SubjectKeyIdentifier.getId()); + byte[] ext = certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId()); if (ext != null) { ASN1OctetString str = (ASN1OctetString)X509ExtensionUtil.fromExtensionValue(ext); return (ASN1Sequence)new AuthorityKeyIdentifier( - str.getOctets(), new GeneralNames(genName), certificate.getSerialNumber()).toASN1Object(); + str.getOctets(), new GeneralNames(genName), certificate.getSerialNumber()).toASN1Primitive(); } else { - SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( - (ASN1Sequence)new ASN1InputStream(certificate.getPublicKey().getEncoded()).readObject()); + SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(certificate.getPublicKey().getEncoded()); return (ASN1Sequence)new AuthorityKeyIdentifier( - info, new GeneralNames(genName), certificate.getSerialNumber()).toASN1Object(); + info, new GeneralNames(genName), certificate.getSerialNumber()).toASN1Primitive(); } } } @@ -111,10 +107,9 @@ public class AuthorityKeyIdentifierStructure { try { - SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( - (ASN1Sequence)new ASN1InputStream(pubKey.getEncoded()).readObject()); + SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()); - return (ASN1Sequence)new AuthorityKeyIdentifier(info).toASN1Object(); + return (ASN1Sequence)new AuthorityKeyIdentifier(info).toASN1Primitive(); } catch (Exception e) { diff --git a/bouncycastle.version b/bouncycastle.version index 6bbeb95f..00639910 100644 --- a/bouncycastle.version +++ b/bouncycastle.version @@ -1,2 +1,2 @@ BOUNCYCASTLE_JDK=15on -BOUNCYCASTLE_VERSION=152 +BOUNCYCASTLE_VERSION=154 |