diff options
author | Brian Carlstrom <bdc@google.com> | 2010-11-08 14:02:51 -0800 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2010-11-17 15:20:52 -0800 |
commit | 8212855a312dc8ebe081a3e08b1d2d8f8757af02 (patch) | |
tree | 5a552d77fb57d594c517daaabf6e5df0b1088924 | |
parent | 4fd8dc053196f660b5bd66c8a6d5dbf5d6428b67 (diff) | |
download | bouncycastle-8212855a312dc8ebe081a3e08b1d2d8f8757af02.tar.gz |
Restoring bouncycastle Elliptic Curve Key support
Specific algorithms now available:
- KeyAgreement.ECDH
- KeyFactory.EC
- KeyPairGenerator.EC
- Signature.NONEWITHECDSA
- Signature.ECDSA
- Signature.SHA256WITHECDSA
- Signature.SHA384WITHECDSA
- Signature.SHA512WITHECDSA
Bug: 3058375
Change-Id: I611b23b2f72bb5d9898d4c695f1677c7914353c6
62 files changed, 12327 insertions, 825 deletions
diff --git a/bouncycastle.config b/bouncycastle.config index 42ca6109..d615ad20 100644 --- a/bouncycastle.config +++ b/bouncycastle.config @@ -13,7 +13,6 @@ org/bouncycastle/asn1/microsoft \ org/bouncycastle/asn1/mozilla \ org/bouncycastle/asn1/ntt \ org/bouncycastle/asn1/ocsp \ -org/bouncycastle/asn1/sec \ org/bouncycastle/asn1/smime \ org/bouncycastle/asn1/test \ org/bouncycastle/asn1/tsp \ @@ -30,10 +29,8 @@ org/bouncycastle/crypto/test \ org/bouncycastle/crypto/tls/ \ org/bouncycastle/i18n/ \ org/bouncycastle/jce/examples \ -org/bouncycastle/jce/provider/asymmetric/ \ org/bouncycastle/jce/provider/test \ org/bouncycastle/mail \ -org/bouncycastle/math \ org/bouncycastle/mozilla \ org/bouncycastle/ocsp \ org/bouncycastle/openpgp \ @@ -114,7 +111,6 @@ org/bouncycastle/asn1/isismtt/x509/Restriction.java \ org/bouncycastle/asn1/misc/CAST5CBCParameters.java \ org/bouncycastle/asn1/misc/IDEACBCPar.java \ org/bouncycastle/asn1/misc/package.html \ -org/bouncycastle/asn1/nist/NISTNamedCurves.java \ org/bouncycastle/asn1/nist/package.html \ org/bouncycastle/asn1/oiw/ElGamalParameter.java \ org/bouncycastle/asn1/oiw/package.html \ @@ -123,6 +119,7 @@ org/bouncycastle/asn1/pkcs/Attribute.java \ org/bouncycastle/asn1/pkcs/RC2CBCParameter.java \ org/bouncycastle/asn1/pkcs/SignerInfo.java \ org/bouncycastle/asn1/pkcs/package.html \ +org/bouncycastle/asn1/sec/package.html \ org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java \ org/bouncycastle/asn1/teletrust/package.html \ org/bouncycastle/asn1/util/DERDump.java \ @@ -152,20 +149,10 @@ org/bouncycastle/asn1/x509/X509Attributes.java \ org/bouncycastle/asn1/x509/package.html \ org/bouncycastle/asn1/x9/KeySpecificInfo.java \ org/bouncycastle/asn1/x9/OtherInfo.java \ -org/bouncycastle/asn1/x9/X962NamedCurves.java \ -org/bouncycastle/asn1/x9/X962Parameters.java \ -org/bouncycastle/asn1/x9/X9Curve.java \ -org/bouncycastle/asn1/x9/X9ECParameters.java \ -org/bouncycastle/asn1/x9/X9ECParametersHolder.java \ -org/bouncycastle/asn1/x9/X9ECPoint.java \ -org/bouncycastle/asn1/x9/X9FieldElement.java \ -org/bouncycastle/asn1/x9/X9FieldID.java \ -org/bouncycastle/asn1/x9/X9IntegerConverter.java \ org/bouncycastle/asn1/x9/package.html \ org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java \ org/bouncycastle/crypto/MaxBytesExceededException.java \ org/bouncycastle/crypto/agreement/DHAgreement.java \ -org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java \ org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java \ org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java \ org/bouncycastle/crypto/agreement/package.html \ @@ -220,7 +207,6 @@ org/bouncycastle/crypto/engines/XTEAEngine.java \ org/bouncycastle/crypto/engines/package.html \ org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java \ org/bouncycastle/crypto/generators/DHKeyPairGenerator.java \ -org/bouncycastle/crypto/generators/ECKeyPairGenerator.java \ org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java \ org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java \ org/bouncycastle/crypto/generators/GOST3410KeyPairGenerator.java \ @@ -250,11 +236,7 @@ org/bouncycastle/crypto/modes/package.html \ org/bouncycastle/crypto/package.html \ org/bouncycastle/crypto/paddings/package.html \ org/bouncycastle/crypto/params/CCMParameters.java \ -org/bouncycastle/crypto/params/ECDomainParameters.java \ -org/bouncycastle/crypto/params/ECKeyGenerationParameters.java \ -org/bouncycastle/crypto/params/ECKeyParameters.java \ -org/bouncycastle/crypto/params/ECPrivateKeyParameters.java \ -org/bouncycastle/crypto/params/ECPublicKeyParameters.java \ +org/bouncycastle/math/ec/test \ org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java \ org/bouncycastle/crypto/params/ElGamalKeyParameters.java \ org/bouncycastle/crypto/params/ElGamalParameters.java \ @@ -282,7 +264,6 @@ org/bouncycastle/crypto/params/RC5Parameters.java \ org/bouncycastle/crypto/params/RSABlindingParameters.java \ org/bouncycastle/crypto/params/package.html \ org/bouncycastle/crypto/signers/DSADigestSigner.java \ -org/bouncycastle/crypto/signers/ECDSASigner.java \ org/bouncycastle/crypto/signers/ECGOST3410Signer.java \ org/bouncycastle/crypto/signers/ECNRSigner.java \ org/bouncycastle/crypto/signers/GOST3410Signer.java \ @@ -305,10 +286,6 @@ org/bouncycastle/jce/X509V2CRLGenerator.java \ org/bouncycastle/jce/X509V3CertificateGenerator.java \ org/bouncycastle/jce/exception/ExtCertificateEncodingException.java \ org/bouncycastle/jce/exception/ExtIOException.java \ -org/bouncycastle/jce/interfaces/ECKey.java \ -org/bouncycastle/jce/interfaces/ECPointEncoder.java \ -org/bouncycastle/jce/interfaces/ECPrivateKey.java \ -org/bouncycastle/jce/interfaces/ECPublicKey.java \ org/bouncycastle/jce/interfaces/ElGamalKey.java \ org/bouncycastle/jce/interfaces/ElGamalPrivateKey.java \ org/bouncycastle/jce/interfaces/ElGamalPublicKey.java \ @@ -324,12 +301,8 @@ org/bouncycastle/jce/package.html \ org/bouncycastle/jce/provider/BrokenJCEBlockCipher.java \ org/bouncycastle/jce/provider/BrokenKDF2BytesGenerator.java \ org/bouncycastle/jce/provider/BrokenPBE.java \ -org/bouncycastle/jce/provider/DSABase.java \ -org/bouncycastle/jce/provider/DSAEncoder.java \ org/bouncycastle/jce/provider/ElGamalUtil.java \ org/bouncycastle/jce/provider/GOST3410Util.java \ -org/bouncycastle/jce/provider/JCEECPrivateKey.java \ -org/bouncycastle/jce/provider/JCEECPublicKey.java \ org/bouncycastle/jce/provider/JCEElGamalCipher.java \ org/bouncycastle/jce/provider/JCEElGamalPrivateKey.java \ org/bouncycastle/jce/provider/JCEElGamalPublicKey.java \ @@ -371,12 +344,6 @@ org/bouncycastle/jce/provider/symmetric/Noekeon.java \ org/bouncycastle/jce/provider/symmetric/NoekeonMappings.java \ org/bouncycastle/jce/provider/symmetric/SEED.java \ org/bouncycastle/jce/provider/symmetric/SEEDMappings.java \ -org/bouncycastle/jce/spec/ECKeySpec.java \ -org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java \ -org/bouncycastle/jce/spec/ECNamedCurveSpec.java \ -org/bouncycastle/jce/spec/ECParameterSpec.java \ -org/bouncycastle/jce/spec/ECPrivateKeySpec.java \ -org/bouncycastle/jce/spec/ECPublicKeySpec.java \ org/bouncycastle/jce/spec/ElGamalGenParameterSpec.java \ org/bouncycastle/jce/spec/ElGamalKeySpec.java \ org/bouncycastle/jce/spec/ElGamalParameterSpec.java \ @@ -392,6 +359,12 @@ org/bouncycastle/jce/spec/IESParameterSpec.java \ org/bouncycastle/jce/spec/MQVPrivateKeySpec.java \ org/bouncycastle/jce/spec/MQVPublicKeySpec.java \ org/bouncycastle/jce/spec/package.html \ +org/bouncycastle/math/ec/ReferenceMultiplier.java \ +org/bouncycastle/math/ec/WNafMultiplier.java \ +org/bouncycastle/math/ec/WNafPreCompInfo.java \ +org/bouncycastle/math/ec/WTauNafMultiplier.java \ +org/bouncycastle/math/ec/WTauNafPreCompInfo.java \ +org/bouncycastle/math/ec/package.html \ org/bouncycastle/openssl/PEMException.java \ org/bouncycastle/openssl/PEMReader.java \ org/bouncycastle/openssl/PasswordException.java \ diff --git a/patches/android.patch b/patches/android.patch index be9e66ad..4f4a0b6c 100644 --- a/patches/android.patch +++ b/patches/android.patch @@ -1,6 +1,6 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Collection.java bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Collection.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Collection.java 1970-01-01 00:00:00.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Collection.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Collection.java 2010-11-17 22:23:31.000000000 +0000 @@ -0,0 +1,298 @@ +package org.bouncycastle.asn1; + @@ -302,7 +302,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Collection.java bcpro +} diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1InputStream.java bcprov-jdk16-145/org/bouncycastle/asn1/ASN1InputStream.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1InputStream.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1InputStream.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1InputStream.java 2010-11-17 22:23:31.000000000 +0000 @@ -348,7 +348,9 @@ case BMP_STRING: return new DERBMPString(bytes); @@ -316,7 +316,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1InputStream.java bcpr case GENERALIZED_TIME: diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Null.java bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Null.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Null.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Null.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Null.java 2010-11-17 22:23:31.000000000 +0000 @@ -8,9 +8,11 @@ public abstract class ASN1Null extends ASN1Object @@ -332,7 +332,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Null.java bcprov-jdk1 { diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Sequence.java bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Sequence.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Sequence.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Sequence.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Sequence.java 2010-11-17 22:23:31.000000000 +0000 @@ -2,12 +2,20 @@ import java.io.IOException; @@ -496,7 +496,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Sequence.java bcprov- } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Set.java bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Set.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Set.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Set.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/ASN1Set.java 2010-11-17 22:23:31.000000000 +0000 @@ -3,12 +3,20 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -845,7 +845,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/ASN1Set.java bcprov-jdk16 } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERBoolean.java bcprov-jdk16-145/org/bouncycastle/asn1/DERBoolean.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERBoolean.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/DERBoolean.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/DERBoolean.java 2010-11-17 22:23:31.000000000 +0000 @@ -5,7 +5,9 @@ public class DERBoolean extends ASN1Object @@ -918,7 +918,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERBoolean.java bcprov-jd { diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERInputStream.java bcprov-jdk16-145/org/bouncycastle/asn1/DERInputStream.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERInputStream.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/DERInputStream.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/DERInputStream.java 2010-11-17 22:23:31.000000000 +0000 @@ -144,7 +144,9 @@ return new DERConstructedSet(v); } @@ -943,7 +943,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERInputStream.java bcpro { diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERNull.java bcprov-jdk16-145/org/bouncycastle/asn1/DERNull.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERNull.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/DERNull.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/DERNull.java 2010-11-17 22:23:31.000000000 +0000 @@ -10,9 +10,13 @@ { public static final DERNull INSTANCE = new DERNull(); @@ -962,7 +962,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERNull.java bcprov-jdk16 diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERObjectIdentifier.java bcprov-jdk16-145/org/bouncycastle/asn1/DERObjectIdentifier.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERObjectIdentifier.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/DERObjectIdentifier.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/DERObjectIdentifier.java 2010-11-17 22:23:31.000000000 +0000 @@ -111,7 +111,13 @@ } } @@ -995,7 +995,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERObjectIdentifier.java public String getId() diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERPrintableString.java bcprov-jdk16-145/org/bouncycastle/asn1/DERPrintableString.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERPrintableString.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/DERPrintableString.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/DERPrintableString.java 2010-11-17 22:23:31.000000000 +0000 @@ -9,7 +9,9 @@ extends ASN1Object implements DERString @@ -1031,7 +1031,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/DERPrintableString.java b public String getString() diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/OrderedTable.java bcprov-jdk16-145/org/bouncycastle/asn1/OrderedTable.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/OrderedTable.java 1970-01-01 00:00:00.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/OrderedTable.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/OrderedTable.java 2010-11-17 22:23:31.000000000 +0000 @@ -0,0 +1,281 @@ +package org.bouncycastle.asn1; + @@ -1316,7 +1316,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/OrderedTable.java bcprov- +} diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java 2010-11-17 22:23:31.000000000 +0000 @@ -37,10 +37,13 @@ public static EncryptedPrivateKeyInfo getInstance( Object obj) @@ -1334,7 +1334,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyI return new EncryptedPrivateKeyInfo((ASN1Sequence)obj); diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java 2010-11-17 22:23:31.000000000 +0000 @@ -10,7 +10,10 @@ // static final String pkcs_1 = "1.2.840.113549.1.1"; @@ -1361,7 +1361,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifier // md4 OBJECT IDENTIFIER ::= diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java 2010-11-17 22:23:31.000000000 +0000 @@ -19,7 +19,9 @@ private AlgorithmIdentifier maskGenAlgorithm; private AlgorithmIdentifier pSourceAlgorithm; @@ -1375,7 +1375,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java 2010-11-17 22:23:31.000000000 +0000 @@ -20,7 +20,9 @@ private DERInteger saltLength; private DERInteger trailerField; @@ -1389,7 +1389,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java public final static DERInteger DEFAULT_TRAILER_FIELD = new DERInteger(1); diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/util/ASN1Dump.java bcprov-jdk16-145/org/bouncycastle/asn1/util/ASN1Dump.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/util/ASN1Dump.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/util/ASN1Dump.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/util/ASN1Dump.java 2010-11-17 22:23:31.000000000 +0000 @@ -90,7 +90,9 @@ { Object o = e.nextElement(); @@ -1403,7 +1403,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/util/ASN1Dump.java bcprov buf.append("NULL"); diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/AttCertIssuer.java bcprov-jdk16-145/org/bouncycastle/asn1/x509/AttCertIssuer.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/AttCertIssuer.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/AttCertIssuer.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/AttCertIssuer.java 2010-11-17 22:23:31.000000000 +0000 @@ -45,7 +45,7 @@ ASN1TaggedObject obj, boolean explicit) @@ -1415,7 +1415,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/AttCertIssuer.java b /** diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/BasicConstraints.java bcprov-jdk16-145/org/bouncycastle/asn1/x509/BasicConstraints.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/BasicConstraints.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/BasicConstraints.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/BasicConstraints.java 2010-11-17 22:23:31.000000000 +0000 @@ -14,7 +14,9 @@ public class BasicConstraints extends ASN1Encodable @@ -1462,7 +1462,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/BasicConstraints.jav diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java bcprov-jdk16-145/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java 2010-11-17 22:23:31.000000000 +0000 @@ -96,11 +96,15 @@ } if (onlyContainsUserCerts) @@ -1501,7 +1501,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/IssuingDistributionP seq = new DERSequence(vec); diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509Extensions.java bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509Extensions.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509Extensions.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509Extensions.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509Extensions.java 2010-11-17 22:23:31.000000000 +0000 @@ -9,6 +9,9 @@ import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; @@ -1690,7 +1690,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509Extensions.java } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509Name.java bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509Name.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509Name.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509Name.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509Name.java 2010-11-17 22:23:31.000000000 +0000 @@ -247,8 +247,10 @@ */ public static final Hashtable SymbolLookUp = DefaultLookUp; @@ -2156,7 +2156,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509Name.java bcprov { diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509NameElementList.java bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509NameElementList.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509NameElementList.java 1970-01-01 00:00:00.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509NameElementList.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509NameElementList.java 2010-11-17 22:23:31.000000000 +0000 @@ -0,0 +1,206 @@ +package org.bouncycastle.asn1.x509; + @@ -2366,7 +2366,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509NameElementList. +} diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509NameTokenizer.java --- bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509NameTokenizer.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/asn1/x509/X509NameTokenizer.java 2010-11-17 22:23:31.000000000 +0000 @@ -58,6 +58,17 @@ } else @@ -2394,7 +2394,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.ja \ No newline at end of file diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/PBEParametersGenerator.java bcprov-jdk16-145/org/bouncycastle/crypto/PBEParametersGenerator.java --- bcprov-jdk16-145.orig/org/bouncycastle/crypto/PBEParametersGenerator.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/crypto/PBEParametersGenerator.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/crypto/PBEParametersGenerator.java 2010-11-17 22:23:30.000000000 +0000 @@ -136,7 +136,8 @@ public static byte[] PKCS12PasswordToBytes( char[] password) @@ -2414,7 +2414,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/PBEParametersGenerator. } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java bcprov-jdk16-145/org/bouncycastle/crypto/digests/OpenSSLDigest.java --- bcprov-jdk16-145.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java 1970-01-01 00:00:00.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/crypto/digests/OpenSSLDigest.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/crypto/digests/OpenSSLDigest.java 2010-11-17 22:23:30.000000000 +0000 @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2008 The Android Open Source Project @@ -2540,7 +2540,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.j +} diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/engines/RC2Engine.java bcprov-jdk16-145/org/bouncycastle/crypto/engines/RC2Engine.java --- bcprov-jdk16-145.orig/org/bouncycastle/crypto/engines/RC2Engine.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/crypto/engines/RC2Engine.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/crypto/engines/RC2Engine.java 2010-11-17 22:23:30.000000000 +0000 @@ -313,4 +313,4 @@ out[outOff + 6] = (byte)x76; out[outOff + 7] = (byte)(x76 >> 8); @@ -2550,7 +2550,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/engines/RC2Engine.java \ No newline at end of file diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/macs/HMac.java bcprov-jdk16-145/org/bouncycastle/crypto/macs/HMac.java --- bcprov-jdk16-145.orig/org/bouncycastle/crypto/macs/HMac.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/crypto/macs/HMac.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/crypto/macs/HMac.java 2010-11-17 22:23:30.000000000 +0000 @@ -32,23 +32,23 @@ { blockLengths = new Hashtable(); @@ -2592,7 +2592,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/macs/HMac.java bcprov-j private static int getByteLength( diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java bcprov-jdk16-145/org/bouncycastle/crypto/signers/RSADigestSigner.java --- bcprov-jdk16-145.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/crypto/signers/RSADigestSigner.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/crypto/signers/RSADigestSigner.java 2010-11-17 22:23:30.000000000 +0000 @@ -46,8 +46,10 @@ oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384); oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512); @@ -2608,61 +2608,43 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/signers/RSADigestSigner diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java bcprov-jdk16-145/org/bouncycastle/crypto/util/PrivateKeyFactory.java --- bcprov-jdk16-145.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/crypto/util/PrivateKeyFactory.java 2010-11-09 01:06:52.000000000 +0000 -@@ -7,31 +7,39 @@ - import org.bouncycastle.asn1.DERInteger; ++++ bcprov-jdk16-145/org/bouncycastle/crypto/util/PrivateKeyFactory.java 2010-11-17 22:23:30.000000000 +0000 +@@ -8,7 +8,9 @@ import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; --import org.bouncycastle.asn1.nist.NISTNamedCurves; + import org.bouncycastle.asn1.nist.NISTNamedCurves; -import org.bouncycastle.asn1.oiw.ElGamalParameter; +// BEGIN android-removed -+// import org.bouncycastle.asn1.nist.NISTNamedCurves; +// import org.bouncycastle.asn1.oiw.ElGamalParameter; +// END android-removed import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.DHParameter; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; - import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +@@ -16,7 +18,9 @@ import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure; --import org.bouncycastle.asn1.sec.ECPrivateKeyStructure; --import org.bouncycastle.asn1.sec.SECNamedCurves; + import org.bouncycastle.asn1.sec.ECPrivateKeyStructure; + import org.bouncycastle.asn1.sec.SECNamedCurves; -import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; +// BEGIN android-removed -+// import org.bouncycastle.asn1.sec.ECPrivateKeyStructure; -+// import org.bouncycastle.asn1.sec.SECNamedCurves; +// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; +// END android-removed import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.DSAParameter; --import org.bouncycastle.asn1.x9.X962NamedCurves; --import org.bouncycastle.asn1.x9.X962Parameters; --import org.bouncycastle.asn1.x9.X9ECParameters; --import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; -+// BEGIN android-removed -+// import org.bouncycastle.asn1.x9.X962NamedCurves; -+// import org.bouncycastle.asn1.x9.X962Parameters; -+// import org.bouncycastle.asn1.x9.X9ECParameters; -+// import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; -+// END android-removed - import org.bouncycastle.crypto.params.AsymmetricKeyParameter; - import org.bouncycastle.crypto.params.DHParameters; - import org.bouncycastle.crypto.params.DHPrivateKeyParameters; - import org.bouncycastle.crypto.params.DSAParameters; + import org.bouncycastle.asn1.x9.X962NamedCurves; +@@ -30,8 +34,10 @@ import org.bouncycastle.crypto.params.DSAPrivateKeyParameters; --import org.bouncycastle.crypto.params.ECDomainParameters; --import org.bouncycastle.crypto.params.ECPrivateKeyParameters; + import org.bouncycastle.crypto.params.ECDomainParameters; + import org.bouncycastle.crypto.params.ECPrivateKeyParameters; -import org.bouncycastle.crypto.params.ElGamalParameters; -import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters; +// BEGIN android-removed -+// import org.bouncycastle.crypto.params.ECDomainParameters; -+// import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +// import org.bouncycastle.crypto.params.ElGamalParameters; +// import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters; +// END android-removed import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; import java.io.IOException; -@@ -113,75 +121,77 @@ +@@ -113,52 +119,56 @@ return new DHPrivateKeyParameters(derX.getValue(), dhParams); } @@ -2673,199 +2655,118 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/util/PrivateKeyFactory. - - return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(params.getP(), params.getG())); - } -- else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa)) -- { -- DERInteger derX = (DERInteger)keyInfo.getPrivateKey(); -- DEREncodable de = keyInfo.getAlgorithmId().getParameters(); ++ // BEGIN android-removed ++ // else if (algId.getObjectId().equals(OIWObjectIdentifiers.elGamalAlgorithm)) ++ // { ++ // ElGamalParameter params = new ElGamalParameter((ASN1Sequence)keyInfo.getAlgorithmId().getParameters()); ++ // DERInteger derX = (DERInteger)keyInfo.getPrivateKey(); ++ // ++ // return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(params.getP(), params.getG())); ++ // } ++ // END android-removed + else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa)) + { + DERInteger derX = (DERInteger)keyInfo.getPrivateKey(); + DEREncodable de = keyInfo.getAlgorithmId().getParameters(); - -- DSAParameters parameters = null; -- if (de != null) -- { -- DSAParameter params = DSAParameter.getInstance(de.getDERObject()); -- parameters = new DSAParameters(params.getP(), params.getQ(), params.getG()); -- } ++ + DSAParameters parameters = null; + if (de != null) + { + DSAParameter params = DSAParameter.getInstance(de.getDERObject()); + parameters = new DSAParameters(params.getP(), params.getQ(), params.getG()); + } - -- return new DSAPrivateKeyParameters(derX.getValue(), parameters); -- } -- else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) -- { -- X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); -- ECDomainParameters dParams = null; ++ + return new DSAPrivateKeyParameters(derX.getValue(), parameters); + } + else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) + { + X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); + ECDomainParameters dParams = null; - -- if (params.isNamedCurve()) -- { -- DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); -- X9ECParameters ecP = X962NamedCurves.getByOID(oid); ++ + if (params.isNamedCurve()) + { + DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); + X9ECParameters ecP = X962NamedCurves.getByOID(oid); - -- if (ecP == null) -- { -- ecP = SECNamedCurves.getByOID(oid); ++ + if (ecP == null) + { + ecP = SECNamedCurves.getByOID(oid); - -- if (ecP == null) -- { -- ecP = NISTNamedCurves.getByOID(oid); ++ + if (ecP == null) + { + ecP = NISTNamedCurves.getByOID(oid); - - if (ecP == null) - { - ecP = TeleTrusTNamedCurves.getByOID(oid); - } -- } -- } ++ ++ // BEGIN android-removed ++ // if (ecP == null) ++ // { ++ // ecP = TeleTrusTNamedCurves.getByOID(oid); ++ // } ++ // END android-removed + } + } - -- dParams = new ECDomainParameters( -- ecP.getCurve(), -- ecP.getG(), -- ecP.getN(), -- ecP.getH(), -- ecP.getSeed()); -- } -- else -- { -- X9ECParameters ecP = new X9ECParameters( -- (ASN1Sequence)params.getParameters()); -- dParams = new ECDomainParameters( -- ecP.getCurve(), -- ecP.getG(), -- ecP.getN(), -- ecP.getH(), -- ecP.getSeed()); -- } ++ + dParams = new ECDomainParameters( + ecP.getCurve(), + ecP.getG(), +@@ -177,9 +187,9 @@ + ecP.getH(), + ecP.getSeed()); + } - -- ECPrivateKeyStructure ec = new ECPrivateKeyStructure((ASN1Sequence)keyInfo.getPrivateKey()); ++ + ECPrivateKeyStructure ec = new ECPrivateKeyStructure((ASN1Sequence)keyInfo.getPrivateKey()); - -- return new ECPrivateKeyParameters(ec.getKey(), dParams); -- } -+ // BEGIN android-removed -+ // else if (algId.getObjectId().equals(OIWObjectIdentifiers.elGamalAlgorithm)) -+ // { -+ // ElGamalParameter params = new ElGamalParameter((ASN1Sequence)keyInfo.getAlgorithmId().getParameters()); -+ // DERInteger derX = (DERInteger)keyInfo.getPrivateKey(); -+ // -+ // return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(params.getP(), params.getG())); -+ // } -+ // else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa)) -+ // { -+ // DERInteger derX = (DERInteger)keyInfo.getPrivateKey(); -+ // DEREncodable de = keyInfo.getAlgorithmId().getParameters(); -+ // -+ // DSAParameters parameters = null; -+ // if (de != null) -+ // { -+ // DSAParameter params = DSAParameter.getInstance(de.getDERObject()); -+ // parameters = new DSAParameters(params.getP(), params.getQ(), params.getG()); -+ // } -+ // -+ // return new DSAPrivateKeyParameters(derX.getValue(), parameters); -+ // } -+ // else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) -+ // { -+ // X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); -+ // ECDomainParameters dParams = null; -+ // -+ // if (params.isNamedCurve()) -+ // { -+ // DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); -+ // X9ECParameters ecP = X962NamedCurves.getByOID(oid); -+ // -+ // if (ecP == null) -+ // { -+ // ecP = SECNamedCurves.getByOID(oid); -+ // -+ // if (ecP == null) -+ // { -+ // ecP = NISTNamedCurves.getByOID(oid); -+ // -+ // if (ecP == null) -+ // { -+ // ecP = TeleTrusTNamedCurves.getByOID(oid); -+ // } -+ // } -+ // } -+ // -+ // dParams = new ECDomainParameters( -+ // ecP.getCurve(), -+ // ecP.getG(), -+ // ecP.getN(), -+ // ecP.getH(), -+ // ecP.getSeed()); -+ // } -+ // else -+ // { -+ // X9ECParameters ecP = new X9ECParameters( -+ // (ASN1Sequence)params.getParameters()); -+ // dParams = new ECDomainParameters( -+ // ecP.getCurve(), -+ // ecP.getG(), -+ // ecP.getN(), -+ // ecP.getH(), -+ // ecP.getSeed()); -+ // } -+ // -+ // ECPrivateKeyStructure ec = new ECPrivateKeyStructure((ASN1Sequence)keyInfo.getPrivateKey()); -+ // -+ // return new ECPrivateKeyParameters(ec.getKey(), dParams); -+ // } -+ // END android-removed ++ + return new ECPrivateKeyParameters(ec.getKey(), dParams); + } else - { - throw new RuntimeException("algorithm identifier in key not recognised"); diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java bcprov-jdk16-145/org/bouncycastle/crypto/util/PublicKeyFactory.java --- bcprov-jdk16-145.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/crypto/util/PublicKeyFactory.java 2010-11-09 01:06:52.000000000 +0000 -@@ -10,32 +10,40 @@ - import org.bouncycastle.asn1.DERObject; ++++ bcprov-jdk16-145/org/bouncycastle/crypto/util/PublicKeyFactory.java 2010-11-17 22:23:30.000000000 +0000 +@@ -11,12 +11,16 @@ import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROctetString; --import org.bouncycastle.asn1.nist.NISTNamedCurves; + import org.bouncycastle.asn1.nist.NISTNamedCurves; -import org.bouncycastle.asn1.oiw.ElGamalParameter; +// BEGIN android-removed -+// import org.bouncycastle.asn1.nist.NISTNamedCurves; +// import org.bouncycastle.asn1.oiw.ElGamalParameter; +// END android-removed import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.DHParameter; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; --import org.bouncycastle.asn1.sec.SECNamedCurves; + import org.bouncycastle.asn1.sec.SECNamedCurves; -import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; +// BEGIN android-removed -+// import org.bouncycastle.asn1.sec.SECNamedCurves; +// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; +// END android-removed import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.DSAParameter; import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; - import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; - import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; --import org.bouncycastle.asn1.x9.X962NamedCurves; --import org.bouncycastle.asn1.x9.X962Parameters; --import org.bouncycastle.asn1.x9.X9ECParameters; --import org.bouncycastle.asn1.x9.X9ECPoint; -+// BEGIN android-removed -+// import org.bouncycastle.asn1.x9.X962NamedCurves; -+// import org.bouncycastle.asn1.x9.X962Parameters; -+// import org.bouncycastle.asn1.x9.X9ECParameters; -+// import org.bouncycastle.asn1.x9.X9ECPoint; -+// END android-removed - import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; - import org.bouncycastle.crypto.params.AsymmetricKeyParameter; - import org.bouncycastle.crypto.params.DHParameters; - import org.bouncycastle.crypto.params.DHPublicKeyParameters; - import org.bouncycastle.crypto.params.DSAParameters; +@@ -34,8 +38,10 @@ import org.bouncycastle.crypto.params.DSAPublicKeyParameters; --import org.bouncycastle.crypto.params.ECDomainParameters; --import org.bouncycastle.crypto.params.ECPublicKeyParameters; + import org.bouncycastle.crypto.params.ECDomainParameters; + import org.bouncycastle.crypto.params.ECPublicKeyParameters; -import org.bouncycastle.crypto.params.ElGamalParameters; -import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters; +// BEGIN android-removed -+// import org.bouncycastle.crypto.params.ECDomainParameters; -+// import org.bouncycastle.crypto.params.ECPublicKeyParameters; +// import org.bouncycastle.crypto.params.ElGamalParameters; +// import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters; +// END android-removed import org.bouncycastle.crypto.params.RSAKeyParameters; import java.io.IOException; -@@ -112,13 +120,15 @@ +@@ -112,13 +118,15 @@ return new DHPublicKeyParameters(derY.getValue(), dhParams); } @@ -2888,122 +2789,65 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/crypto/util/PublicKeyFactory.j else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa) || algId.getObjectId().equals(OIWObjectIdentifiers.dsaWithSHA1)) { -@@ -134,58 +144,60 @@ - - return new DSAPublicKeyParameters(derY.getValue(), parameters); - } -- else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) -- { -- X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); -- ECDomainParameters dParams = null; +@@ -138,27 +146,29 @@ + { + X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); + ECDomainParameters dParams = null; - -- if (params.isNamedCurve()) -- { -- DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); -- X9ECParameters ecP = X962NamedCurves.getByOID(oid); ++ + if (params.isNamedCurve()) + { + DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); + X9ECParameters ecP = X962NamedCurves.getByOID(oid); - -- if (ecP == null) -- { -- ecP = SECNamedCurves.getByOID(oid); ++ + if (ecP == null) + { + ecP = SECNamedCurves.getByOID(oid); - -- if (ecP == null) -- { -- ecP = NISTNamedCurves.getByOID(oid); ++ + if (ecP == null) + { + ecP = NISTNamedCurves.getByOID(oid); - - if (ecP == null) - { - ecP = TeleTrusTNamedCurves.getByOID(oid); - } -- } -- } ++ ++ // BEGIN android-removed ++ // if (ecP == null) ++ // { ++ // ecP = TeleTrusTNamedCurves.getByOID(oid); ++ // } ++ // END android-removed + } + } - -- dParams = new ECDomainParameters( -- ecP.getCurve(), -- ecP.getG(), -- ecP.getN(), -- ecP.getH(), -- ecP.getSeed()); -- } -- else -- { -- X9ECParameters ecP = new X9ECParameters( -- (ASN1Sequence)params.getParameters()); -- dParams = new ECDomainParameters( -- ecP.getCurve(), -- ecP.getG(), -- ecP.getN(), -- ecP.getH(), -- ecP.getSeed()); -- } ++ + dParams = new ECDomainParameters( + ecP.getCurve(), + ecP.getG(), +@@ -177,13 +187,13 @@ + ecP.getH(), + ecP.getSeed()); + } - -- DERBitString bits = keyInfo.getPublicKeyData(); -- byte[] data = bits.getBytes(); -- ASN1OctetString key = new DEROctetString(data); ++ + DERBitString bits = keyInfo.getPublicKeyData(); + byte[] data = bits.getBytes(); + ASN1OctetString key = new DEROctetString(data); - -- X9ECPoint derQ = new X9ECPoint(dParams.getCurve(), key); ++ + X9ECPoint derQ = new X9ECPoint(dParams.getCurve(), key); - -- return new ECPublicKeyParameters(derQ.getPoint(), dParams); -- } -+ // BEGIN android-removed -+ // else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) -+ // { -+ // X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); -+ // ECDomainParameters dParams = null; -+ // -+ // if (params.isNamedCurve()) -+ // { -+ // DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); -+ // X9ECParameters ecP = X962NamedCurves.getByOID(oid); -+ // -+ // if (ecP == null) -+ // { -+ // ecP = SECNamedCurves.getByOID(oid); -+ // -+ // if (ecP == null) -+ // { -+ // ecP = NISTNamedCurves.getByOID(oid); -+ // -+ // if (ecP == null) -+ // { -+ // ecP = TeleTrusTNamedCurves.getByOID(oid); -+ // } -+ // } -+ // } -+ // -+ // dParams = new ECDomainParameters( -+ // ecP.getCurve(), -+ // ecP.getG(), -+ // ecP.getN(), -+ // ecP.getH(), -+ // ecP.getSeed()); -+ // } -+ // else -+ // { -+ // X9ECParameters ecP = new X9ECParameters( -+ // (ASN1Sequence)params.getParameters()); -+ // dParams = new ECDomainParameters( -+ // ecP.getCurve(), -+ // ecP.getG(), -+ // ecP.getN(), -+ // ecP.getH(), -+ // ecP.getSeed()); -+ // } -+ // -+ // DERBitString bits = keyInfo.getPublicKeyData(); -+ // byte[] data = bits.getBytes(); -+ // ASN1OctetString key = new DEROctetString(data); -+ // -+ // X9ECPoint derQ = new X9ECPoint(dParams.getCurve(), key); -+ // -+ // return new ECPublicKeyParameters(derQ.getPoint(), dParams); -+ // } -+ // END android-removed ++ + return new ECPublicKeyParameters(derQ.getPoint(), dParams); + } else - { - throw new RuntimeException("algorithm identifier in key not recognised"); diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java bcprov-jdk16-145/org/bouncycastle/jce/PKCS10CertificationRequest.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/PKCS10CertificationRequest.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/PKCS10CertificationRequest.java 2010-11-17 22:23:30.000000000 +0000 @@ -78,8 +78,11 @@ static @@ -3067,7 +2911,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/PKCS10CertificationRequest diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java bcprov-jdk16-145/org/bouncycastle/jce/provider/BouncyCastleProvider.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/BouncyCastleProvider.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/BouncyCastleProvider.java 2010-11-17 22:23:30.000000000 +0000 @@ -45,7 +45,10 @@ { private static String info = "BouncyCastle Security Provider v1.45"; @@ -3094,18 +2938,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi }; /* -@@ -62,7 +70,9 @@ - private static final String ASYMMETRIC_CIPHER_PACKAGE = "org.bouncycastle.jce.provider.asymmetric."; - private static final String[] ASYMMETRIC_CIPHERS = - { -- "EC" -+ // BEGIN android-removed -+ // "EC" -+ // END android-removed - }; - - /** -@@ -89,26 +99,28 @@ +@@ -89,26 +97,28 @@ loadAlgorithms(SYMMETRIC_CIPHER_PACKAGE, SYMMETRIC_CIPHERS); loadAlgorithms(ASYMMETRIC_CIPHER_PACKAGE, ASYMMETRIC_CIPHERS); @@ -3154,7 +2987,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi // -@@ -117,14 +129,24 @@ +@@ -117,14 +127,24 @@ put("KeyStore.BKS", "org.bouncycastle.jce.provider.JDKKeyStore"); put("KeyStore.BouncyCastle", "org.bouncycastle.jce.provider.JDKKeyStore$BouncyCastleStore"); put("KeyStore.PKCS12", "org.bouncycastle.jce.provider.JDKPKCS12KeyStore$BCPKCS12KeyStore"); @@ -3187,7 +3020,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.KeyStore.UBER", "BouncyCastle"); put("Alg.Alias.KeyStore.BOUNCYCASTLE", "BouncyCastle"); -@@ -141,44 +163,63 @@ +@@ -141,44 +161,63 @@ // put("AlgorithmParameterGenerator.DH", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DH"); put("AlgorithmParameterGenerator.DSA", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DSA"); @@ -3275,7 +3108,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND40BITRC2-CBC", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND40BITRC4", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND128BITRC2-CBC", "PKCS12PBE"); -@@ -192,7 +233,7 @@ +@@ -192,7 +231,7 @@ put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.5", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.6", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWithSHAAnd3KeyTripleDES", "PKCS12PBE"); @@ -3284,7 +3117,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.AlgorithmParameters." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.getId(), "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.getId(), "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc.getId(), "PKCS12PBE"); -@@ -202,22 +243,24 @@ +@@ -202,22 +241,24 @@ put("Alg.Alias.AlgorithmParameters." + PKCSObjectIdentifiers.id_RSAES_OAEP, "OAEP"); @@ -3325,7 +3158,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND128BITAES-CBC-BC", "PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND192BITAES-CBC-BC", "PKCS12PBE"); -@@ -234,12 +277,14 @@ +@@ -234,12 +275,14 @@ put("Alg.Alias.AlgorithmParameters.PBEWITHSHA-256AND128BITAES-CBC-BC","PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHA-256AND192BITAES-CBC-BC","PKCS12PBE"); put("Alg.Alias.AlgorithmParameters.PBEWITHSHA-256AND256BITAES-CBC-BC","PKCS12PBE"); @@ -3346,7 +3179,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi // // key agreement -@@ -252,97 +297,129 @@ +@@ -252,97 +295,129 @@ // put("Cipher.DES", "org.bouncycastle.jce.provider.JCEBlockCipher$DES"); put("Cipher.DESEDE", "org.bouncycastle.jce.provider.JCEBlockCipher$DESede"); @@ -3542,7 +3375,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.getId(), "PBEWITHSHAAND128BITAES-CBC-BC"); put("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.getId(), "PBEWITHSHAAND192BITAES-CBC-BC"); -@@ -350,7 +427,7 @@ +@@ -350,7 +425,7 @@ put("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc.getId(), "PBEWITHSHA256AND128BITAES-CBC-BC"); put("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.getId(), "PBEWITHSHA256AND192BITAES-CBC-BC"); put("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.getId(), "PBEWITHSHA256AND256BITAES-CBC-BC"); @@ -3551,7 +3384,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Cipher.PBEWITHSHAAND128BITAES-CBC-BC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithAESCBC"); put("Cipher.PBEWITHSHAAND192BITAES-CBC-BC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithAESCBC"); put("Cipher.PBEWITHSHAAND256BITAES-CBC-BC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithAESCBC"); -@@ -372,7 +449,9 @@ +@@ -372,7 +447,9 @@ put("Cipher.PBEWITHMD5AND256BITAES-CBC-OPENSSL", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithAESCBC"); put("Cipher.PBEWITHSHAANDTWOFISH-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAndTwofish"); @@ -3562,7 +3395,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.1", "PBEWITHSHAAND128BITRC4"); put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.2", "PBEWITHSHAAND40BITRC4"); -@@ -387,38 +466,49 @@ +@@ -387,38 +464,49 @@ put("KeyGenerator.DES", "org.bouncycastle.jce.provider.JCEKeyGenerator$DES"); put("Alg.Alias.KeyGenerator." + OIWObjectIdentifiers.desCBC, "DES"); put("KeyGenerator.DESEDE", "org.bouncycastle.jce.provider.JCEKeyGenerator$DESede"); @@ -3640,7 +3473,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi // // key pair generators. -@@ -426,14 +516,18 @@ +@@ -426,14 +514,18 @@ put("KeyPairGenerator.RSA", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$RSA"); put("KeyPairGenerator.DH", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$DH"); put("KeyPairGenerator.DSA", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$DSA"); @@ -3663,7 +3496,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi // // key factories -@@ -441,20 +535,24 @@ +@@ -441,20 +533,24 @@ put("KeyFactory.RSA", "org.bouncycastle.jce.provider.JDKKeyFactory$RSA"); put("KeyFactory.DH", "org.bouncycastle.jce.provider.JDKKeyFactory$DH"); put("KeyFactory.DSA", "org.bouncycastle.jce.provider.JDKKeyFactory$DSA"); @@ -3696,7 +3529,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi // // Algorithm parameters -@@ -462,16 +560,22 @@ +@@ -462,16 +558,22 @@ put("AlgorithmParameters.DES", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); put("Alg.Alias.AlgorithmParameters." + OIWObjectIdentifiers.desCBC, "DES"); put("AlgorithmParameters.DESEDE", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters"); @@ -3727,7 +3560,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi // -@@ -479,8 +583,10 @@ +@@ -479,8 +581,10 @@ // put("SecretKeyFactory.DES", "org.bouncycastle.jce.provider.JCESecretKeyFactory$DES"); put("SecretKeyFactory.DESEDE", "org.bouncycastle.jce.provider.JCESecretKeyFactory$DESede"); @@ -3740,7 +3573,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("SecretKeyFactory.PBEWITHMD5ANDDES", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBEWithMD5AndDES"); put("SecretKeyFactory.PBEWITHMD5ANDRC2", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBEWithMD5AndRC2"); put("SecretKeyFactory.PBEWITHSHA1ANDDES", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBEWithSHA1AndDES"); -@@ -492,31 +598,41 @@ +@@ -492,31 +596,41 @@ put("SecretKeyFactory.PBEWITHSHAAND128BITRC2-CBC", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBEWithSHAAnd128BitRC2"); put("SecretKeyFactory.PBEWITHSHAAND40BITRC2-CBC", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBEWithSHAAnd40BitRC2"); put("SecretKeyFactory.PBEWITHSHAANDTWOFISH-CBC", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBEWithSHAAndTwofish"); @@ -3797,7 +3630,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, "PBEWITHMD5ANDDES"); put("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC, "PBEWITHMD5ANDRC2"); put("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, "PBEWITHSHA1ANDDES"); -@@ -553,6 +669,10 @@ +@@ -553,6 +667,10 @@ put("Alg.Alias.SecretKeyFactory." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc.getId(), "PBEWITHSHA256AND128BITAES-CBC-BC"); put("Alg.Alias.SecretKeyFactory." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.getId(), "PBEWITHSHA256AND192BITAES-CBC-BC"); put("Alg.Alias.SecretKeyFactory." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.getId(), "PBEWITHSHA256AND256BITAES-CBC-BC"); @@ -3808,7 +3641,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi addMacAlgorithms(); -@@ -561,16 +681,23 @@ +@@ -561,16 +679,23 @@ addSignatureAlgorithms(); // Certification Path API @@ -3839,7 +3672,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi } private void loadAlgorithms(String packageName, String[] names) -@@ -631,68 +758,72 @@ +@@ -631,68 +756,72 @@ // private void addMacAlgorithms() { @@ -3968,7 +3801,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi addHMACAlgorithm("SHA256", "org.bouncycastle.jce.provider.JCEMac$SHA256", "org.bouncycastle.jce.provider.JCEKeyGenerator$HMACSHA256"); addHMACAlias("SHA256", PKCSObjectIdentifiers.id_hmacWithSHA256); addHMACAlgorithm("SHA384", "org.bouncycastle.jce.provider.JCEMac$SHA384", "org.bouncycastle.jce.provider.JCEKeyGenerator$HMACSHA384"); -@@ -700,16 +831,20 @@ +@@ -700,16 +829,20 @@ addHMACAlgorithm("SHA512", "org.bouncycastle.jce.provider.JCEMac$SHA512", "org.bouncycastle.jce.provider.JCEKeyGenerator$HMACSHA512"); addHMACAlias("SHA512", PKCSObjectIdentifiers.id_hmacWithSHA512); @@ -3996,7 +3829,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.Mac.1.3.14.3.2.26", "PBEWITHHMACSHA"); } -@@ -747,9 +882,11 @@ +@@ -747,9 +880,11 @@ put("Alg.Alias.MessageDigest.SHA1", "SHA-1"); put("Alg.Alias.MessageDigest.SHA", "SHA-1"); put("Alg.Alias.MessageDigest." + OIWObjectIdentifiers.idSHA1, "SHA-1"); @@ -4011,7 +3844,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("MessageDigest.SHA-256", "org.bouncycastle.jce.provider.JDKMessageDigest$SHA256"); put("Alg.Alias.MessageDigest.SHA256", "SHA-256"); put("Alg.Alias.MessageDigest." + NISTObjectIdentifiers.id_sha256, "SHA-256"); -@@ -760,27 +897,31 @@ +@@ -760,27 +895,31 @@ put("Alg.Alias.MessageDigest.SHA512", "SHA-512"); put("Alg.Alias.MessageDigest." + NISTObjectIdentifiers.id_sha512, "SHA-512"); @@ -4062,7 +3895,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi } // -@@ -788,55 +929,70 @@ +@@ -788,55 +927,70 @@ // private void addSignatureAlgorithms() { @@ -4171,7 +4004,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.Signature.SHA256withRSAEncryption", "SHA256WithRSAEncryption"); put("Alg.Alias.Signature.SHA384withRSAEncryption", "SHA384WithRSAEncryption"); -@@ -850,24 +1006,30 @@ +@@ -850,24 +1004,30 @@ put("Alg.Alias.Signature.SHA384WITHRSAENCRYPTION", "SHA384WithRSAEncryption"); put("Alg.Alias.Signature.SHA512WITHRSAENCRYPTION", "SHA512WithRSAEncryption"); @@ -4214,7 +4047,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi put("Alg.Alias.Signature.SHA256WithRSA", "SHA256WithRSAEncryption"); put("Alg.Alias.Signature.SHA256withRSA", "SHA256WithRSAEncryption"); put("Alg.Alias.Signature.SHA384WithRSA", "SHA384WithRSAEncryption"); -@@ -877,92 +1039,110 @@ +@@ -877,92 +1037,110 @@ put("Alg.Alias.Signature.SHA1/RSA", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature.SHA-1/RSA", "SHA1WithRSAEncryption"); put("Alg.Alias.Signature." + PKCSObjectIdentifiers.sha1WithRSAEncryption, "SHA1WithRSAEncryption"); @@ -4398,7 +4231,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/BouncyCastleProvi { diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java bcprov-jdk16-145/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java 2010-11-17 22:23:30.000000000 +0000 @@ -24,6 +24,7 @@ import java.security.spec.DSAPublicKeySpec; import java.text.ParseException; @@ -4703,7 +4536,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/CertPathValidator CRLDistPoint crldp, ExtendedPKIXParameters pkixParams) diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEBlockCipher.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEBlockCipher.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEBlockCipher.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEBlockCipher.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEBlockCipher.java 2010-11-17 22:23:30.000000000 +0000 @@ -7,22 +7,31 @@ import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.engines.AESFastEngine; @@ -5652,7 +5485,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEBlockCipher.ja */ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEDHKeyAgreement.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEDHKeyAgreement.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEDHKeyAgreement.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEDHKeyAgreement.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEDHKeyAgreement.java 2010-11-17 22:23:30.000000000 +0000 @@ -37,9 +37,11 @@ static @@ -5670,7 +5503,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEDHKeyAgreement algorithms.put("DESEDE", i192); diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEDigestUtil.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEDigestUtil.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEDigestUtil.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEDigestUtil.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEDigestUtil.java 2010-11-17 22:23:30.000000000 +0000 @@ -12,7 +12,9 @@ import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.MD5Digest; @@ -5751,9 +5584,329 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEDigestUtil.jav || (sha256.contains(digest1) && sha256.contains(digest2)) || (sha384.contains(digest1) && sha384.contains(digest2)) || (sha512.contains(digest1) && sha512.contains(digest2)) +diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEECPrivateKey.java +--- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java 2010-01-11 21:46:14.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEECPrivateKey.java 2010-11-17 22:23:30.000000000 +0000 +@@ -20,7 +20,9 @@ + import org.bouncycastle.asn1.DERObject; + import org.bouncycastle.asn1.DERObjectIdentifier; + import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +-import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; ++// BEGIN android-removed ++// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; ++// END android-removed + import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; + import org.bouncycastle.asn1.sec.ECPrivateKeyStructure; + import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +@@ -199,21 +201,23 @@ + DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); + X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); + +- if (ecP == null) // GOST Curve +- { +- ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid); +- EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed()); +- +- ecSpec = new ECNamedCurveSpec( +- ECGOST3410NamedCurves.getName(oid), +- ellipticCurve, +- new ECPoint( +- gParam.getG().getX().toBigInteger(), +- gParam.getG().getY().toBigInteger()), +- gParam.getN(), +- gParam.getH()); +- } +- else ++ // BEGIN android-removed ++ // if (ecP == null) // GOST Curve ++ // { ++ // ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid); ++ // EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed()); ++ // ++ // ecSpec = new ECNamedCurveSpec( ++ // ECGOST3410NamedCurves.getName(oid), ++ // ellipticCurve, ++ // new ECPoint( ++ // gParam.getG().getX().toBigInteger(), ++ // gParam.getG().getY().toBigInteger()), ++ // gParam.getN(), ++ // gParam.getH()); ++ // } ++ // else ++ // END android-removed + { + EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed()); + +@@ -321,11 +325,13 @@ + keyStructure = new ECPrivateKeyStructure(this.getS(), params); + } + +- if (algorithm.equals("ECGOST3410")) +- { +- info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.getDERObject()), keyStructure.getDERObject()); +- } +- else ++ // BEGIN android-removed ++ // if (algorithm.equals("ECGOST3410")) ++ // { ++ // info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.getDERObject()), keyStructure.getDERObject()); ++ // } ++ // else ++ // END android-removed + { + + info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.getDERObject()), keyStructure.getDERObject()); +diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEECPublicKey.java +--- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java 2010-01-11 21:46:14.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEECPublicKey.java 2010-11-17 22:23:30.000000000 +0000 +@@ -20,8 +20,10 @@ + import org.bouncycastle.asn1.DERObjectIdentifier; + import org.bouncycastle.asn1.DEROctetString; + import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +-import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; +-import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters; ++// BEGIN android-removed ++// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; ++// import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters; ++// END android-removed + import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; + import org.bouncycastle.asn1.x9.X962Parameters; +@@ -31,11 +33,15 @@ + import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; + import org.bouncycastle.crypto.params.ECDomainParameters; + import org.bouncycastle.crypto.params.ECPublicKeyParameters; +-import org.bouncycastle.jce.ECGOST3410NamedCurveTable; ++// BEGIN android-removed ++// import org.bouncycastle.jce.ECGOST3410NamedCurveTable; ++// END android-removed + import org.bouncycastle.jce.interfaces.ECPointEncoder; + import org.bouncycastle.jce.provider.asymmetric.ec.EC5Util; + import org.bouncycastle.jce.provider.asymmetric.ec.ECUtil; +-import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; ++// BEGIN android-removed ++// import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; ++// END android-removed + import org.bouncycastle.jce.spec.ECNamedCurveSpec; + import org.bouncycastle.math.ec.ECCurve; + +@@ -46,7 +52,9 @@ + private org.bouncycastle.math.ec.ECPoint q; + private ECParameterSpec ecSpec; + private boolean withCompression; +- private GOST3410PublicKeyAlgParameters gostParams; ++ // BEGIN android-removed ++ // private GOST3410PublicKeyAlgParameters gostParams; ++ // END android-removed + + public JCEECPublicKey( + String algorithm, +@@ -56,7 +64,9 @@ + this.q = key.q; + this.ecSpec = key.ecSpec; + this.withCompression = key.withCompression; +- this.gostParams = key.gostParams; ++ // BEGIN android-removed ++ // this.gostParams = key.gostParams; ++ // END android-removed + } + + public JCEECPublicKey( +@@ -179,54 +189,56 @@ + + private void populateFromPubKeyInfo(SubjectPublicKeyInfo info) + { +- if (info.getAlgorithmId().getObjectId().equals(CryptoProObjectIdentifiers.gostR3410_2001)) +- { +- DERBitString bits = info.getPublicKeyData(); +- ASN1OctetString key; +- this.algorithm = "ECGOST3410"; +- +- try +- { +- key = (ASN1OctetString) ASN1Object.fromByteArray(bits.getBytes()); +- } +- catch (IOException ex) +- { +- throw new IllegalArgumentException("error recovering public key"); +- } +- +- byte[] keyEnc = key.getOctets(); +- byte[] x = new byte[32]; +- byte[] y = new byte[32]; +- +- for (int i = 0; i != x.length; i++) +- { +- x[i] = keyEnc[32 - 1 - i]; +- } +- +- for (int i = 0; i != y.length; i++) +- { +- y[i] = keyEnc[64 - 1 - i]; +- } +- +- gostParams = new GOST3410PublicKeyAlgParameters((ASN1Sequence)info.getAlgorithmId().getParameters()); +- +- ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet())); +- +- ECCurve curve = spec.getCurve(); +- EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed()); +- +- this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y), false); +- +- ecSpec = new ECNamedCurveSpec( +- ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()), +- ellipticCurve, +- new ECPoint( +- spec.getG().getX().toBigInteger(), +- spec.getG().getY().toBigInteger()), +- spec.getN(), spec.getH()); +- +- } +- else ++ // BEGIN android-removed ++ // if (info.getAlgorithmId().getObjectId().equals(CryptoProObjectIdentifiers.gostR3410_2001)) ++ // { ++ // DERBitString bits = info.getPublicKeyData(); ++ // ASN1OctetString key; ++ // this.algorithm = "ECGOST3410"; ++ // ++ // try ++ // { ++ // key = (ASN1OctetString) ASN1Object.fromByteArray(bits.getBytes()); ++ // } ++ // catch (IOException ex) ++ // { ++ // throw new IllegalArgumentException("error recovering public key"); ++ // } ++ // ++ // byte[] keyEnc = key.getOctets(); ++ // byte[] x = new byte[32]; ++ // byte[] y = new byte[32]; ++ // ++ // for (int i = 0; i != x.length; i++) ++ // { ++ // x[i] = keyEnc[32 - 1 - i]; ++ // } ++ // ++ // for (int i = 0; i != y.length; i++) ++ // { ++ // y[i] = keyEnc[64 - 1 - i]; ++ // } ++ // ++ // gostParams = new GOST3410PublicKeyAlgParameters((ASN1Sequence)info.getAlgorithmId().getParameters()); ++ // ++ // ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet())); ++ // ++ // ECCurve curve = spec.getCurve(); ++ // EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed()); ++ // ++ // this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y), false); ++ // ++ // ecSpec = new ECNamedCurveSpec( ++ // ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()), ++ // ellipticCurve, ++ // new ECPoint( ++ // spec.getG().getX().toBigInteger(), ++ // spec.getG().getY().toBigInteger()), ++ // spec.getN(), spec.getH()); ++ // ++ // } ++ // else ++ // END android-removed + { + X962Parameters params = new X962Parameters((DERObject)info.getAlgorithmId().getParameters()); + ECCurve curve; +@@ -315,45 +327,47 @@ + ASN1Encodable params; + SubjectPublicKeyInfo info; + +- if (algorithm.equals("ECGOST3410")) +- { +- if (gostParams != null) +- { +- params = gostParams; +- } +- else +- { +- if (ecSpec instanceof ECNamedCurveSpec) +- { +- params = new GOST3410PublicKeyAlgParameters( +- ECGOST3410NamedCurves.getOID(((ECNamedCurveSpec)ecSpec).getName()), +- CryptoProObjectIdentifiers.gostR3411_94_CryptoProParamSet); +- } +- else +- { // strictly speaking this may not be applicable... +- ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); +- +- X9ECParameters ecP = new X9ECParameters( +- curve, +- EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), +- ecSpec.getOrder(), +- BigInteger.valueOf(ecSpec.getCofactor()), +- ecSpec.getCurve().getSeed()); +- +- params = new X962Parameters(ecP); +- } +- } +- +- BigInteger bX = this.q.getX().toBigInteger(); +- BigInteger bY = this.q.getY().toBigInteger(); +- byte[] encKey = new byte[64]; +- +- extractBytes(encKey, 0, bX); +- extractBytes(encKey, 32, bY); +- +- info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.getDERObject()), new DEROctetString(encKey)); +- } +- else ++ // BEGIN android-removed ++ // if (algorithm.equals("ECGOST3410")) ++ // { ++ // if (gostParams != null) ++ // { ++ // params = gostParams; ++ // } ++ // else ++ // { ++ // if (ecSpec instanceof ECNamedCurveSpec) ++ // { ++ // params = new GOST3410PublicKeyAlgParameters( ++ // ECGOST3410NamedCurves.getOID(((ECNamedCurveSpec)ecSpec).getName()), ++ // CryptoProObjectIdentifiers.gostR3411_94_CryptoProParamSet); ++ // } ++ // else ++ // { // strictly speaking this may not be applicable... ++ // ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); ++ // ++ // X9ECParameters ecP = new X9ECParameters( ++ // curve, ++ // EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), ++ // ecSpec.getOrder(), ++ // BigInteger.valueOf(ecSpec.getCofactor()), ++ // ecSpec.getCurve().getSeed()); ++ // ++ // params = new X962Parameters(ecP); ++ // } ++ // } ++ // ++ // BigInteger bX = this.q.getX().toBigInteger(); ++ // BigInteger bY = this.q.getY().toBigInteger(); ++ // byte[] encKey = new byte[64]; ++ // ++ // extractBytes(encKey, 0, bX); ++ // extractBytes(encKey, 32, bY); ++ // ++ // info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.getDERObject()), new DEROctetString(encKey)); ++ // } ++ // else ++ // END android-removed + { + if (ecSpec instanceof ECNamedCurveSpec) + { diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEKeyGenerator.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEKeyGenerator.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEKeyGenerator.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEKeyGenerator.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEKeyGenerator.java 2010-11-17 22:23:30.000000000 +0000 @@ -57,6 +57,11 @@ { try @@ -6397,7 +6550,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEKeyGenerator.j } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEMac.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEMac.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEMac.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEMac.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEMac.java 2010-11-17 22:23:30.000000000 +0000 @@ -2,29 +2,43 @@ import org.bouncycastle.crypto.CipherParameters; @@ -7150,7 +7303,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEMac.java bcpro } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSACipher.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSACipher.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSACipher.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSACipher.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSACipher.java 2010-11-17 22:23:30.000000000 +0000 @@ -534,48 +534,50 @@ } } @@ -7248,7 +7401,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSACipher.java } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSAPrivateCrtKey.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSAPrivateCrtKey.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSAPrivateCrtKey.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSAPrivateCrtKey.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSAPrivateCrtKey.java 2010-11-17 22:23:30.000000000 +0000 @@ -125,7 +125,9 @@ */ public byte[] getEncoded() @@ -7262,7 +7415,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSAPrivateCrtK } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSAPrivateKey.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSAPrivateKey.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSAPrivateKey.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSAPrivateKey.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSAPrivateKey.java 2010-11-17 22:23:30.000000000 +0000 @@ -77,7 +77,9 @@ public byte[] getEncoded() @@ -7276,7 +7429,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSAPrivateKey. } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSAPublicKey.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSAPublicKey.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSAPublicKey.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSAPublicKey.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCERSAPublicKey.java 2010-11-17 22:23:30.000000000 +0000 @@ -90,7 +90,9 @@ public byte[] getEncoded() @@ -7290,7 +7443,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCERSAPublicKey.j } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCESecretKeyFactory.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCESecretKeyFactory.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCESecretKeyFactory.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCESecretKeyFactory.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCESecretKeyFactory.java 2010-11-17 22:23:30.000000000 +0000 @@ -321,29 +321,31 @@ } } @@ -7467,7 +7620,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCESecretKeyFacto } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEStreamCipher.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEStreamCipher.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEStreamCipher.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEStreamCipher.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JCEStreamCipher.java 2010-11-17 22:23:30.000000000 +0000 @@ -5,17 +5,21 @@ import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.StreamBlockCipher; @@ -7911,7 +8064,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JCEStreamCipher.j } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator.java 2010-11-17 22:23:30.000000000 +0000 @@ -2,19 +2,25 @@ import org.bouncycastle.crypto.generators.DHParametersGenerator; @@ -8338,7 +8491,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKAlgorithmParam } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKAlgorithmParameters.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKAlgorithmParameters.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKAlgorithmParameters.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKAlgorithmParameters.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKAlgorithmParameters.java 2010-11-17 22:23:30.000000000 +0000 @@ -10,21 +10,27 @@ import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROctetString; @@ -9838,7 +9991,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKAlgorithmParam } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKDSASigner.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKDSASigner.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKDSASigner.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKDSASigner.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKDSASigner.java 2010-11-17 22:23:30.000000000 +0000 @@ -22,13 +22,17 @@ import org.bouncycastle.crypto.DSA; import org.bouncycastle.crypto.Digest; @@ -9989,7 +10142,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKDSASigner.java extends JDKDSASigner diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKDigestSignature.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKDigestSignature.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKDigestSignature.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKDigestSignature.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKDigestSignature.java 2010-11-17 22:23:30.000000000 +0000 @@ -23,14 +23,20 @@ import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.CipherParameters; @@ -10190,7 +10343,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKDigestSignatur } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyFactory.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKKeyFactory.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyFactory.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKKeyFactory.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKKeyFactory.java 2010-11-17 22:23:30.000000000 +0000 @@ -36,17 +36,21 @@ import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; @@ -10310,14 +10463,10 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyFactory.jav else if (algOid.equals(X9ObjectIdentifiers.id_dsa)) { return new JDKDSAPublicKey(info); -@@ -245,18 +261,19 @@ +@@ -249,14 +265,15 @@ { - return new JDKDSAPublicKey(info); + return new JCEECPublicKey(info); } -- else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey)) -- { -- return new JCEECPublicKey(info); -- } - else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94)) - { - return new JDKGOST3410PublicKey(info); @@ -10327,10 +10476,6 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyFactory.jav - return new JCEECPublicKey(info); - } + // BEGIN android-removed -+ // else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey)) -+ // { -+ // return new JCEECPublicKey(info); -+ // } + // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94)) + // { + // return new JDKGOST3410PublicKey(info); @@ -10342,7 +10487,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyFactory.jav else { throw new RuntimeException("algorithm identifier " + algOid + " in key not recognised"); -@@ -290,26 +307,30 @@ +@@ -290,10 +307,12 @@ { return new JCEDHPrivateKey(info); } @@ -10359,11 +10504,10 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyFactory.jav else if (algOid.equals(X9ObjectIdentifiers.id_dsa)) { return new JDKDSAPrivateKey(info); +@@ -302,14 +321,16 @@ + { + return new JCEECPrivateKey(info); } -- else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey)) -- { -- return new JCEECPrivateKey(info); -- } - else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94)) - { - return new JDKGOST3410PrivateKey(info); @@ -10373,10 +10517,6 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyFactory.jav - return new JCEECPrivateKey(info); - } + // BEGIN android-removed -+ // else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey)) -+ // { -+ // return new JCEECPrivateKey(info); -+ // } + // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94)) + // { + // return new JDKGOST3410PrivateKey(info); @@ -10568,7 +10708,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyFactory.jav } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyPairGenerator.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKKeyPairGenerator.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyPairGenerator.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKKeyPairGenerator.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKKeyPairGenerator.java 2010-11-17 22:23:30.000000000 +0000 @@ -6,9 +6,11 @@ import org.bouncycastle.crypto.generators.DHParametersGenerator; import org.bouncycastle.crypto.generators.DSAKeyPairGenerator; @@ -10912,7 +11052,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyPairGenerat } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyStore.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKKeyStore.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyStore.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKKeyStore.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKKeyStore.java 2010-11-17 22:23:30.000000000 +0000 @@ -39,7 +39,12 @@ import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; @@ -11015,7 +11155,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKKeyStore.java } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKMessageDigest.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKMessageDigest.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKMessageDigest.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKMessageDigest.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKMessageDigest.java 2010-11-17 22:23:30.000000000 +0000 @@ -57,36 +57,38 @@ { super(new SHA1Digest()); @@ -11462,7 +11602,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKMessageDigest. } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java 2010-11-17 22:23:30.000000000 +0000 @@ -255,10 +255,13 @@ } } @@ -11632,7 +11772,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/JDKPKCS12KeyStore return null; diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PBE.java bcprov-jdk16-145/org/bouncycastle/jce/provider/PBE.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PBE.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PBE.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PBE.java 2010-11-17 22:23:30.000000000 +0000 @@ -7,12 +7,18 @@ import org.bouncycastle.crypto.CipherParameters; @@ -11707,7 +11847,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PBE.java bcprov-j break; diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKCS12BagAttributeCarrierImpl.java bcprov-jdk16-145/org/bouncycastle/jce/provider/PKCS12BagAttributeCarrierImpl.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKCS12BagAttributeCarrierImpl.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKCS12BagAttributeCarrierImpl.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKCS12BagAttributeCarrierImpl.java 2010-11-17 22:23:30.000000000 +0000 @@ -1,6 +1,9 @@ package org.bouncycastle.jce.provider; @@ -11850,7 +11990,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKCS12BagAttribut { diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXCertPath.java bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXCertPath.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXCertPath.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXCertPath.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXCertPath.java 2010-11-17 22:23:30.000000000 +0000 @@ -33,7 +33,9 @@ import org.bouncycastle.asn1.pkcs.ContentInfo; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; @@ -11915,7 +12055,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXCertPath.java throw new CertificateEncodingException("unsupported encoding: " + encoding); diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java 2010-11-17 22:23:30.000000000 +0000 @@ -172,8 +172,9 @@ try { @@ -11930,7 +12070,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXCertPathBuild // chains diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java 2010-11-17 22:23:30.000000000 +0000 @@ -13,6 +13,7 @@ import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; @@ -11983,7 +12123,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXCertPathValid { diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXNameConstraintValidator.java bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXNameConstraintValidator.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXNameConstraintValidator.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXNameConstraintValidator.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/PKIXNameConstraintValidator.java 2010-11-17 22:23:30.000000000 +0000 @@ -1533,7 +1533,9 @@ for (Enumeration e = permitted.getObjects(); e.hasMoreElements();) { @@ -11995,158 +12135,9 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/PKIXNameConstrain if (subtreesMap.get(tagNo) == null) { subtreesMap.put(tagNo, new HashSet()); -diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/ProviderUtil.java bcprov-jdk16-145/org/bouncycastle/jce/provider/ProviderUtil.java ---- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/ProviderUtil.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/ProviderUtil.java 2010-11-09 01:06:52.000000000 +0000 -@@ -1,9 +1,13 @@ - package org.bouncycastle.jce.provider; - - import org.bouncycastle.jce.ProviderConfigurationPermission; --import org.bouncycastle.jce.provider.asymmetric.ec.EC5Util; -+// BEGIN android-removed -+// import org.bouncycastle.jce.provider.asymmetric.ec.EC5Util; -+// END android-removed - import org.bouncycastle.jce.interfaces.ConfigurableProvider; --import org.bouncycastle.jce.spec.ECParameterSpec; -+// BEGIN android-removed -+// import org.bouncycastle.jce.spec.ECParameterSpec; -+// END android-removed - - import java.io.ByteArrayInputStream; - import java.io.IOException; -@@ -20,68 +24,74 @@ - "BC", ConfigurableProvider.EC_IMPLICITLY_CA); - - private static ThreadLocal threadSpec = new ThreadLocal(); -- private static volatile ECParameterSpec ecImplicitCaParams; -+ // BEGIN android-removed -+ // private static volatile ECParameterSpec ecImplicitCaParams; -+ // END android-removed - - static void setParameter(String parameterName, Object parameter) - { - SecurityManager securityManager = System.getSecurityManager(); - -- if (parameterName.equals(ConfigurableProvider.THREAD_LOCAL_EC_IMPLICITLY_CA)) -- { -- ECParameterSpec curveSpec; -- -- if (securityManager != null) -- { -- securityManager.checkPermission(BC_EC_LOCAL_PERMISSION); -- } -- -- if (parameter instanceof ECParameterSpec || parameter == null) -- { -- curveSpec = (ECParameterSpec)parameter; -- } -- else // assume java.security.spec -- { -- curveSpec = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false); -- } -- -- if (curveSpec == null) -- { -- threadSpec.remove(); -- } -- else -- { -- threadSpec.set(curveSpec); -- } -- } -- else if (parameterName.equals(ConfigurableProvider.EC_IMPLICITLY_CA)) -- { -- if (securityManager != null) -- { -- securityManager.checkPermission(BC_EC_PERMISSION); -- } -- -- if (parameter instanceof ECParameterSpec || parameter == null) -- { -- ecImplicitCaParams = (ECParameterSpec)parameter; -- } -- else // assume java.security.spec -- { -- ecImplicitCaParams = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false); -- } -- } -+ // BEGIN android-removed -+ // if (parameterName.equals(ConfigurableProvider.THREAD_LOCAL_EC_IMPLICITLY_CA)) -+ // { -+ // ECParameterSpec curveSpec; -+ // -+ // if (securityManager != null) -+ // { -+ // securityManager.checkPermission(BC_EC_LOCAL_PERMISSION); -+ // } -+ // -+ // if (parameter instanceof ECParameterSpec || parameter == null) -+ // { -+ // curveSpec = (ECParameterSpec)parameter; -+ // } -+ // else // assume java.security.spec -+ // { -+ // curveSpec = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false); -+ // } -+ // -+ // if (curveSpec == null) -+ // { -+ // threadSpec.remove(); -+ // } -+ // else -+ // { -+ // threadSpec.set(curveSpec); -+ // } -+ // } -+ // else if (parameterName.equals(ConfigurableProvider.EC_IMPLICITLY_CA)) -+ // { -+ // if (securityManager != null) -+ // { -+ // securityManager.checkPermission(BC_EC_PERMISSION); -+ // } -+ // -+ // if (parameter instanceof ECParameterSpec || parameter == null) -+ // { -+ // ecImplicitCaParams = (ECParameterSpec)parameter; -+ // } -+ // else // assume java.security.spec -+ // { -+ // ecImplicitCaParams = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false); -+ // } -+ // } -+ // END android-removed - } - -- public static ECParameterSpec getEcImplicitlyCa() -- { -- ECParameterSpec spec = (ECParameterSpec)threadSpec.get(); -- -- if (spec != null) -- { -- return spec; -- } -- -- return ecImplicitCaParams; -- } -+ // BEGIN android-removed -+ // public static ECParameterSpec getEcImplicitlyCa() -+ // { -+ // ECParameterSpec spec = (ECParameterSpec)threadSpec.get(); -+ // -+ // if (spec != null) -+ // { -+ // return spec; -+ // } -+ // -+ // return ecImplicitCaParams; -+ // } -+ // END android-removed - - static int getReadLimit(InputStream in) - throws IOException diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/WrapCipherSpi.java bcprov-jdk16-145/org/bouncycastle/jce/provider/WrapCipherSpi.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/WrapCipherSpi.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/WrapCipherSpi.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/WrapCipherSpi.java 2010-11-17 22:23:30.000000000 +0000 @@ -12,8 +12,10 @@ import org.bouncycastle.crypto.Wrapper; import org.bouncycastle.crypto.engines.DESedeEngine; @@ -12221,37 +12212,24 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/WrapCipherSpi.jav { byte[] encoded; try -@@ -354,15 +368,20 @@ - - DERObjectIdentifier oid = in.getAlgorithmId().getObjectId(); - -- if (oid.equals(X9ObjectIdentifiers.id_ecPublicKey)) -- { -- privKey = new JCEECPrivateKey(in); -- } +@@ -358,10 +372,12 @@ + { + privKey = new JCEECPrivateKey(in); + } - else if (oid.equals(CryptoProObjectIdentifiers.gostR3410_94)) - { - privKey = new JDKGOST3410PrivateKey(in); - } -- else if (oid.equals(X9ObjectIdentifiers.id_dsa)) + // BEGIN android-removed -+ // if (oid.equals(X9ObjectIdentifiers.id_ecPublicKey)) -+ // { -+ // privKey = new JCEECPrivateKey(in); -+ // } + // else if (oid.equals(CryptoProObjectIdentifiers.gostR3410_94)) + // { + // privKey = new JDKGOST3410PrivateKey(in); + // } -+ // else if (oid.equals(X9ObjectIdentifiers.id_dsa)) + // END android-removed -+ // BEGIN android-added -+ if (oid.equals(X9ObjectIdentifiers.id_dsa)) -+ // END android-added + else if (oid.equals(X9ObjectIdentifiers.id_dsa)) { privKey = new JDKDSAPrivateKey(in); - } -@@ -405,10 +424,12 @@ +@@ -405,10 +421,12 @@ { throw new InvalidKeyException("Unknown key type " + e.getMessage()); } @@ -12268,7 +12246,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/WrapCipherSpi.jav catch (InvalidKeySpecException e2) { throw new InvalidKeyException("Unknown key type " + e2.getMessage()); -@@ -433,21 +454,23 @@ +@@ -433,21 +451,23 @@ } } @@ -12311,7 +12289,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/WrapCipherSpi.jav } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/X509CertificateObject.java bcprov-jdk16-145/org/bouncycastle/jce/provider/X509CertificateObject.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/X509CertificateObject.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/X509CertificateObject.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/X509CertificateObject.java 2010-11-17 22:23:30.000000000 +0000 @@ -518,12 +518,20 @@ return JDKKeyFactory.createPublicKeyFromPublicKeyInfo(c.getSubjectPublicKeyInfo()); } @@ -12345,7 +12323,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/X509CertificateOb signature = Signature.getInstance(sigName, "BC"); diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java bcprov-jdk16-145/org/bouncycastle/jce/provider/X509SignatureUtil.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/X509SignatureUtil.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/X509SignatureUtil.java 2010-11-17 22:23:30.000000000 +0000 @@ -25,7 +25,9 @@ class X509SignatureUtil @@ -12436,9 +12414,938 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/X509SignatureUtil else { return digestAlgOID.getId(); +diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ECMappings.java bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ECMappings.java +--- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ECMappings.java 2010-01-11 21:46:14.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ECMappings.java 2010-11-17 22:23:30.000000000 +0000 +@@ -4,8 +4,10 @@ + + import org.bouncycastle.asn1.DERObjectIdentifier; + import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +-import org.bouncycastle.asn1.eac.EACObjectIdentifiers; +-import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; ++// BEGIN android-removed ++// import org.bouncycastle.asn1.eac.EACObjectIdentifiers; ++// import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; ++// END android-removed + import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; + + public class ECMappings +@@ -14,39 +16,49 @@ + public ECMappings() + { + put("KeyAgreement.ECDH", "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$DH"); +- put("KeyAgreement.ECDHC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$DHC"); +- put("KeyAgreement.ECMQV", "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$MQV"); +- put("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$DHwithSHA1KDF"); +- put("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$MQVwithSHA1KDF"); ++ // BEGIN android-removed ++ // put("KeyAgreement.ECDHC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$DHC"); ++ // put("KeyAgreement.ECMQV", "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$MQV"); ++ // put("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$DHwithSHA1KDF"); ++ // put("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$MQVwithSHA1KDF"); ++ // END android-removed + + put("KeyFactory.EC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$EC"); +- put("KeyFactory.ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECDSA"); +- put("KeyFactory.ECDH", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECDH"); +- put("KeyFactory.ECDHC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECDHC"); +- put("KeyFactory.ECMQV", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECMQV"); ++ // BEGIN android-removed ++ // put("KeyFactory.ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECDSA"); ++ // put("KeyFactory.ECDH", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECDH"); ++ // put("KeyFactory.ECDHC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECDHC"); ++ // put("KeyFactory.ECMQV", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECMQV"); ++ // END android-removed + put("Alg.Alias.KeyFactory." + X9ObjectIdentifiers.id_ecPublicKey, "EC"); + // TODO Should this be an alias for ECDH? + put("Alg.Alias.KeyFactory." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC"); +- put("Alg.Alias.KeyFactory." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV"); ++ // BEGIN android-removed ++ // put("Alg.Alias.KeyFactory." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV"); + +- put("KeyFactory.ECGOST3410", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECGOST3410"); +- put("Alg.Alias.KeyFactory.GOST-3410-2001", "ECGOST3410"); +- put("Alg.Alias.KeyFactory.ECGOST-3410", "ECGOST3410"); +- put("Alg.Alias.KeyFactory." + CryptoProObjectIdentifiers.gostR3410_2001, "ECGOST3410"); ++ // put("KeyFactory.ECGOST3410", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECGOST3410"); ++ // put("Alg.Alias.KeyFactory.GOST-3410-2001", "ECGOST3410"); ++ // put("Alg.Alias.KeyFactory.ECGOST-3410", "ECGOST3410"); ++ // put("Alg.Alias.KeyFactory." + CryptoProObjectIdentifiers.gostR3410_2001, "ECGOST3410"); ++ // END android-removed + + put("KeyPairGenerator.EC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$EC"); +- put("KeyPairGenerator.ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDSA"); +- put("KeyPairGenerator.ECDH", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDH"); +- put("KeyPairGenerator.ECDHC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDHC"); +- put("KeyPairGenerator.ECIES", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDH"); +- put("KeyPairGenerator.ECMQV", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECMQV"); ++ // BEGIN android-removed ++ // put("KeyPairGenerator.ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDSA"); ++ // put("KeyPairGenerator.ECDH", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDH"); ++ // put("KeyPairGenerator.ECDHC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDHC"); ++ // put("KeyPairGenerator.ECIES", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDH"); ++ // put("KeyPairGenerator.ECMQV", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECMQV"); ++ // END android-removed + // TODO Should this be an alias for ECDH? + put("Alg.Alias.KeyPairGenerator." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC"); +- put("Alg.Alias.KeyPairGenerator." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV"); ++ // BEGIN android-removed ++ // put("Alg.Alias.KeyPairGenerator." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV"); + +- put("KeyPairGenerator.ECGOST3410", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECGOST3410"); +- put("Alg.Alias.KeyPairGenerator.ECGOST-3410", "ECGOST3410"); +- put("Alg.Alias.KeyPairGenerator.GOST-3410-2001", "ECGOST3410"); ++ // put("KeyPairGenerator.ECGOST3410", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECGOST3410"); ++ // put("Alg.Alias.KeyPairGenerator.ECGOST-3410", "ECGOST3410"); ++ // put("Alg.Alias.KeyPairGenerator.GOST-3410-2001", "ECGOST3410"); ++ // END android-removed + + put("Signature.ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA"); + put("Signature.NONEwithECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSAnone"); +@@ -58,23 +70,27 @@ + put("Alg.Alias.Signature.SHA1WithECDSA", "ECDSA"); + put("Alg.Alias.Signature.ECDSAWithSHA1", "ECDSA"); + put("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA"); +- put("Alg.Alias.Signature." + TeleTrusTObjectIdentifiers.ecSignWithSha1, "ECDSA"); ++ // BEGIN android-removed ++ // put("Alg.Alias.Signature." + TeleTrusTObjectIdentifiers.ecSignWithSha1, "ECDSA"); + +- addSignatureAlgorithm("SHA224", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA224", X9ObjectIdentifiers.ecdsa_with_SHA224); ++ // addSignatureAlgorithm("SHA224", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA224", X9ObjectIdentifiers.ecdsa_with_SHA224); ++ // END android-removed + addSignatureAlgorithm("SHA256", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA256", X9ObjectIdentifiers.ecdsa_with_SHA256); + addSignatureAlgorithm("SHA384", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA384", X9ObjectIdentifiers.ecdsa_with_SHA384); + addSignatureAlgorithm("SHA512", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA512", X9ObjectIdentifiers.ecdsa_with_SHA512); +- addSignatureAlgorithm("RIPEMD160", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSARipeMD160",TeleTrusTObjectIdentifiers.ecSignWithRipemd160); ++ // BEGIN android-removed ++ // addSignatureAlgorithm("RIPEMD160", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSARipeMD160",TeleTrusTObjectIdentifiers.ecSignWithRipemd160); + +- put("Signature.SHA1WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR"); +- put("Signature.SHA224WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR224"); +- put("Signature.SHA256WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR256"); +- put("Signature.SHA384WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR384"); +- put("Signature.SHA512WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR512"); +- +- addSignatureAlgorithm("SHA1", "CVC-ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecCVCDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1); +- addSignatureAlgorithm("SHA224", "CVC-ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecCVCDSA224", EACObjectIdentifiers.id_TA_ECDSA_SHA_224); +- addSignatureAlgorithm("SHA256", "CVC-ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecCVCDSA256", EACObjectIdentifiers.id_TA_ECDSA_SHA_256); ++ // put("Signature.SHA1WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR"); ++ // put("Signature.SHA224WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR224"); ++ // put("Signature.SHA256WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR256"); ++ // put("Signature.SHA384WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR384"); ++ // put("Signature.SHA512WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR512"); ++ ++ // addSignatureAlgorithm("SHA1", "CVC-ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecCVCDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1); ++ // addSignatureAlgorithm("SHA224", "CVC-ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecCVCDSA224", EACObjectIdentifiers.id_TA_ECDSA_SHA_224); ++ // addSignatureAlgorithm("SHA256", "CVC-ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecCVCDSA256", EACObjectIdentifiers.id_TA_ECDSA_SHA_256); ++ // END android-removed + } + + private void addSignatureAlgorithm( +diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ec/ECUtil.java bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ec/ECUtil.java +--- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ec/ECUtil.java 2010-01-11 21:46:14.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ec/ECUtil.java 2010-11-17 22:23:30.000000000 +0000 +@@ -1,10 +1,14 @@ + package org.bouncycastle.jce.provider.asymmetric.ec; + + import org.bouncycastle.asn1.DERObjectIdentifier; +-import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; ++// BEGIN android-removed ++// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; ++// END android-removed + import org.bouncycastle.asn1.nist.NISTNamedCurves; + import org.bouncycastle.asn1.sec.SECNamedCurves; +-import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; ++// BEGIN android-removed ++// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; ++// END android-removed + import org.bouncycastle.asn1.x9.X962NamedCurves; + import org.bouncycastle.asn1.x9.X9ECParameters; + import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +@@ -167,14 +171,16 @@ + { + oid = NISTNamedCurves.getOID(name); + } +- if (oid == null) +- { +- oid = TeleTrusTNamedCurves.getOID(name); +- } +- if (oid == null) +- { +- oid = ECGOST3410NamedCurves.getOID(name); +- } ++ // BEGIN android-removed ++ // if (oid == null) ++ // { ++ // oid = TeleTrusTNamedCurves.getOID(name); ++ // } ++ // if (oid == null) ++ // { ++ // oid = ECGOST3410NamedCurves.getOID(name); ++ // } ++ // END android-removed + } + + return oid; +@@ -192,10 +198,12 @@ + { + params = NISTNamedCurves.getByOID(oid); + } +- if (params == null) +- { +- params = TeleTrusTNamedCurves.getByOID(oid); +- } ++ // BEGIN android-removed ++ // if (params == null) ++ // { ++ // params = TeleTrusTNamedCurves.getByOID(oid); ++ // } ++ // END android-removed + } + + return params; +@@ -213,14 +221,16 @@ + { + name = NISTNamedCurves.getName(oid); + } +- if (name == null) +- { +- name = TeleTrusTNamedCurves.getName(oid); +- } +- if (name == null) +- { +- name = ECGOST3410NamedCurves.getName(oid); +- } ++ // BEGIN android-removed ++ // if (name == null) ++ // { ++ // name = TeleTrusTNamedCurves.getName(oid); ++ // } ++ // if (name == null) ++ // { ++ // name = ECGOST3410NamedCurves.getName(oid); ++ // } ++ // END android-removed + } + + return name; +diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ec/KeyAgreement.java bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ec/KeyAgreement.java +--- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ec/KeyAgreement.java 2010-01-11 21:46:14.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ec/KeyAgreement.java 2010-11-17 22:23:30.000000000 +0000 +@@ -24,20 +24,26 @@ + import org.bouncycastle.crypto.CipherParameters; + import org.bouncycastle.crypto.DerivationFunction; + import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; +-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; ++// 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; ++// END android-removed + import org.bouncycastle.crypto.digests.SHA1Digest; + import org.bouncycastle.crypto.params.ECDomainParameters; + import org.bouncycastle.crypto.params.ECPrivateKeyParameters; + import org.bouncycastle.crypto.params.ECPublicKeyParameters; +-import org.bouncycastle.crypto.params.MQVPrivateParameters; +-import org.bouncycastle.crypto.params.MQVPublicParameters; ++// BEGIN android-removed ++// import org.bouncycastle.crypto.params.MQVPrivateParameters; ++// import org.bouncycastle.crypto.params.MQVPublicParameters; ++// END android-removed + import org.bouncycastle.jce.interfaces.ECPrivateKey; + import org.bouncycastle.jce.interfaces.ECPublicKey; +-import org.bouncycastle.jce.interfaces.MQVPrivateKey; +-import org.bouncycastle.jce.interfaces.MQVPublicKey; ++// BEGIN android-removed ++// import org.bouncycastle.jce.interfaces.MQVPrivateKey; ++// import org.bouncycastle.jce.interfaces.MQVPublicKey; ++// END android-removed + + /** + * Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363 +@@ -70,7 +76,9 @@ + private BigInteger result; + private ECDomainParameters parameters; + private BasicAgreement agreement; +- private DerivationFunction kdf; ++ // BEGIN android-removed ++ // private DerivationFunction kdf; ++ // END android-removed + + private byte[] bigIntToBytes( + BigInteger r) +@@ -85,7 +93,9 @@ + { + this.kaAlgorithm = kaAlgorithm; + this.agreement = agreement; +- this.kdf = kdf; ++ // BEGIN android-removed ++ // this.kdf = kdf; ++ // END android-removed + } + + protected Key engineDoPhase( +@@ -104,25 +114,27 @@ + } + + CipherParameters pubKey; +- if (agreement instanceof ECMQVBasicAgreement) +- { +- if (!(key instanceof MQVPublicKey)) +- { +- throw new InvalidKeyException(kaAlgorithm + " key agreement requires " +- + getSimpleName(MQVPublicKey.class) + " for doPhase"); +- } +- +- MQVPublicKey mqvPubKey = (MQVPublicKey)key; +- ECPublicKeyParameters staticKey = (ECPublicKeyParameters) +- ECUtil.generatePublicKeyParameter(mqvPubKey.getStaticKey()); +- ECPublicKeyParameters ephemKey = (ECPublicKeyParameters) +- ECUtil.generatePublicKeyParameter(mqvPubKey.getEphemeralKey()); +- +- pubKey = new MQVPublicParameters(staticKey, ephemKey); +- +- // TODO Validate that all the keys are using the same parameters? +- } +- else ++ // BEGIN android-removed ++ // if (agreement instanceof ECMQVBasicAgreement) ++ // { ++ // if (!(key instanceof MQVPublicKey)) ++ // { ++ // throw new InvalidKeyException(kaAlgorithm + " key agreement requires " ++ // + getSimpleName(MQVPublicKey.class) + " for doPhase"); ++ // } ++ // ++ // MQVPublicKey mqvPubKey = (MQVPublicKey)key; ++ // ECPublicKeyParameters staticKey = (ECPublicKeyParameters) ++ // ECUtil.generatePublicKeyParameter(mqvPubKey.getStaticKey()); ++ // ECPublicKeyParameters ephemKey = (ECPublicKeyParameters) ++ // ECUtil.generatePublicKeyParameter(mqvPubKey.getEphemeralKey()); ++ // ++ // pubKey = new MQVPublicParameters(staticKey, ephemKey); ++ // ++ // // TODO Validate that all the keys are using the same parameters? ++ // } ++ // else ++ // END android-removed + { + if (!(key instanceof ECPublicKey)) + { +@@ -143,11 +155,13 @@ + protected byte[] engineGenerateSecret() + throws IllegalStateException + { +- if (kdf != null) +- { +- throw new UnsupportedOperationException( +- "KDF can only be used when algorithm is known"); +- } ++ // BEGIN android-removed ++ // if (kdf != null) ++ // { ++ // throw new UnsupportedOperationException( ++ // "KDF can only be used when algorithm is known"); ++ // } ++ // END android-removed + + return bigIntToBytes(result); + } +@@ -175,23 +189,25 @@ + { + byte[] secret = bigIntToBytes(result); + +- if (kdf != null) +- { +- if (!algorithms.containsKey(algorithm)) +- { +- throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm); +- } +- +- int keySize = ((Integer)algorithms.get(algorithm)).intValue(); +- +- DHKDFParameters params = new DHKDFParameters(new DERObjectIdentifier(algorithm), keySize, secret); +- +- byte[] keyBytes = new byte[keySize / 8]; +- kdf.init(params); +- kdf.generateBytes(keyBytes, 0, keyBytes.length); +- secret = keyBytes; +- } +- else ++ // BEGIN android-removed ++ // if (kdf != null) ++ // { ++ // if (!algorithms.containsKey(algorithm)) ++ // { ++ // throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm); ++ // } ++ // ++ // int keySize = ((Integer)algorithms.get(algorithm)).intValue(); ++ // ++ // DHKDFParameters params = new DHKDFParameters(new DERObjectIdentifier(algorithm), keySize, secret); ++ // ++ // byte[] keyBytes = new byte[keySize / 8]; ++ // kdf.init(params); ++ // kdf.generateBytes(keyBytes, 0, keyBytes.length); ++ // secret = keyBytes; ++ // } ++ // else ++ // END android-removed + { + // TODO Should we be ensuring the key is the right length? + } +@@ -219,35 +235,37 @@ + private void initFromKey(Key key) + throws InvalidKeyException + { +- if (agreement instanceof ECMQVBasicAgreement) +- { +- if (!(key instanceof MQVPrivateKey)) +- { +- throw new InvalidKeyException(kaAlgorithm + " key agreement requires " +- + getSimpleName(MQVPrivateKey.class) + " for initialisation"); +- } +- +- MQVPrivateKey mqvPrivKey = (MQVPrivateKey)key; +- ECPrivateKeyParameters staticPrivKey = (ECPrivateKeyParameters) +- ECUtil.generatePrivateKeyParameter(mqvPrivKey.getStaticPrivateKey()); +- ECPrivateKeyParameters ephemPrivKey = (ECPrivateKeyParameters) +- ECUtil.generatePrivateKeyParameter(mqvPrivKey.getEphemeralPrivateKey()); +- +- ECPublicKeyParameters ephemPubKey = null; +- if (mqvPrivKey.getEphemeralPublicKey() != null) +- { +- ephemPubKey = (ECPublicKeyParameters) +- ECUtil.generatePublicKeyParameter(mqvPrivKey.getEphemeralPublicKey()); +- } +- +- MQVPrivateParameters localParams = new MQVPrivateParameters(staticPrivKey, ephemPrivKey, ephemPubKey); +- this.parameters = staticPrivKey.getParameters(); +- +- // TODO Validate that all the keys are using the same parameters? +- +- agreement.init(localParams); +- } +- else ++ // BEGIN android-removed ++ // if (agreement instanceof ECMQVBasicAgreement) ++ // { ++ // if (!(key instanceof MQVPrivateKey)) ++ // { ++ // throw new InvalidKeyException(kaAlgorithm + " key agreement requires " ++ // + getSimpleName(MQVPrivateKey.class) + " for initialisation"); ++ // } ++ // ++ // MQVPrivateKey mqvPrivKey = (MQVPrivateKey)key; ++ // ECPrivateKeyParameters staticPrivKey = (ECPrivateKeyParameters) ++ // ECUtil.generatePrivateKeyParameter(mqvPrivKey.getStaticPrivateKey()); ++ // ECPrivateKeyParameters ephemPrivKey = (ECPrivateKeyParameters) ++ // ECUtil.generatePrivateKeyParameter(mqvPrivKey.getEphemeralPrivateKey()); ++ // ++ // ECPublicKeyParameters ephemPubKey = null; ++ // if (mqvPrivKey.getEphemeralPublicKey() != null) ++ // { ++ // ephemPubKey = (ECPublicKeyParameters) ++ // ECUtil.generatePublicKeyParameter(mqvPrivKey.getEphemeralPublicKey()); ++ // } ++ // ++ // MQVPrivateParameters localParams = new MQVPrivateParameters(staticPrivKey, ephemPrivKey, ephemPubKey); ++ // this.parameters = staticPrivKey.getParameters(); ++ // ++ // // TODO Validate that all the keys are using the same parameters? ++ // ++ // agreement.init(localParams); ++ // } ++ // else ++ // END android-removed + { + if (!(key instanceof ECPrivateKey)) + { +@@ -278,39 +296,41 @@ + } + } + +- public static class DHC +- extends KeyAgreement +- { +- public DHC() +- { +- super("ECDHC", new ECDHCBasicAgreement(), null); +- } +- } +- +- public static class MQV +- extends KeyAgreement +- { +- public MQV() +- { +- super("ECMQV", new ECMQVBasicAgreement(), null); +- } +- } +- +- public static class DHwithSHA1KDF +- extends KeyAgreement +- { +- public DHwithSHA1KDF() +- { +- super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest())); +- } +- } +- +- public static class MQVwithSHA1KDF +- extends KeyAgreement +- { +- public MQVwithSHA1KDF() +- { +- super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest())); +- } +- } ++ // BEGIN android-removed ++ // public static class DHC ++ // extends KeyAgreement ++ // { ++ // public DHC() ++ // { ++ // super("ECDHC", new ECDHCBasicAgreement(), null); ++ // } ++ // } ++ // ++ // public static class MQV ++ // extends KeyAgreement ++ // { ++ // public MQV() ++ // { ++ // super("ECMQV", new ECMQVBasicAgreement(), null); ++ // } ++ // } ++ // ++ // public static class DHwithSHA1KDF ++ // extends KeyAgreement ++ // { ++ // public DHwithSHA1KDF() ++ // { ++ // super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest())); ++ // } ++ // } ++ // ++ // public static class MQVwithSHA1KDF ++ // extends KeyAgreement ++ // { ++ // public MQVwithSHA1KDF() ++ // { ++ // super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest())); ++ // } ++ // } ++ // END android-removed + } +diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ec/KeyPairGenerator.java bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ec/KeyPairGenerator.java +--- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ec/KeyPairGenerator.java 2010-01-11 21:46:14.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ec/KeyPairGenerator.java 2010-11-17 22:23:30.000000000 +0000 +@@ -10,10 +10,14 @@ + import java.util.Hashtable; + + import org.bouncycastle.asn1.DERObjectIdentifier; +-import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; ++// BEGIN android-removed ++// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; ++// END android-removed + import org.bouncycastle.asn1.nist.NISTNamedCurves; + import org.bouncycastle.asn1.sec.SECNamedCurves; +-import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; ++// BEGIN android-removed ++// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; ++// END android-removed + import org.bouncycastle.asn1.x9.X962NamedCurves; + import org.bouncycastle.asn1.x9.X9ECParameters; + import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +@@ -83,7 +87,13 @@ + SecureRandom random) + { + this.strength = strength; ++ // BEGIN android-added ++ if (random != null) { ++ // END android-added + this.random = random; ++ // BEGIN android-added ++ } ++ // END android-added + this.ecParams = ecParameters.get(new Integer(strength)); + + if (ecParams != null) +@@ -108,6 +118,11 @@ + SecureRandom random) + throws InvalidAlgorithmParameterException + { ++ // BEGIN android-added ++ if (random == null) { ++ random = this.random; ++ } ++ // END android-added + if (params instanceof ECParameterSpec) + { + ECParameterSpec p = (ECParameterSpec)params; +@@ -135,23 +150,25 @@ + { + final String curveName = ((ECGenParameterSpec)params).getName(); + +- if (this.algorithm.equals("ECGOST3410")) +- { +- ECDomainParameters ecP = ECGOST3410NamedCurves.getByName(curveName); +- if (ecP == null) +- { +- throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); +- } +- +- this.ecParams = new ECNamedCurveSpec( +- curveName, +- ecP.getCurve(), +- ecP.getG(), +- ecP.getN(), +- ecP.getH(), +- ecP.getSeed()); +- } +- else ++ // BEGIN android-removed ++ // if (this.algorithm.equals("ECGOST3410")) ++ // { ++ // ECDomainParameters ecP = ECGOST3410NamedCurves.getByName(curveName); ++ // if (ecP == null) ++ // { ++ // throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); ++ // } ++ // ++ // this.ecParams = new ECNamedCurveSpec( ++ // curveName, ++ // ecP.getCurve(), ++ // ecP.getG(), ++ // ecP.getN(), ++ // ecP.getH(), ++ // ecP.getSeed()); ++ // } ++ // else ++ // END android-removed + { + X9ECParameters ecP = X962NamedCurves.getByName(curveName); + if (ecP == null) +@@ -161,10 +178,12 @@ + { + ecP = NISTNamedCurves.getByName(curveName); + } +- if (ecP == null) +- { +- ecP = TeleTrusTNamedCurves.getByName(curveName); +- } ++ // BEGIN android-removed ++ // if (ecP == null) ++ // { ++ // ecP = TeleTrusTNamedCurves.getByName(curveName); ++ // } ++ // END android-removed + if (ecP == null) + { + // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug) +@@ -180,10 +199,12 @@ + { + ecP = NISTNamedCurves.getByOID(oid); + } +- if (ecP == null) +- { +- ecP = TeleTrusTNamedCurves.getByOID(oid); +- } ++ // BEGIN android-removed ++ // if (ecP == null) ++ // { ++ // ecP = TeleTrusTNamedCurves.getByOID(oid); ++ // } ++ // END android-removed + if (ecP == null) + { + throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName); +@@ -239,7 +260,15 @@ + { + if (!initialised) + { +- throw new IllegalStateException("EC Key Pair Generator not initialised"); ++ // BEGIN android-removed ++ // throw new IllegalStateException("EC Key Pair Generator not initialised"); ++ // END android-removed ++ // BEGIN android-added ++ /* ++ * KeyPairGenerator documentation says that a default initialization must be provided ++ */ ++ initialize(192, random); ++ // END android-added + } + + AsymmetricCipherKeyPair pair = engine.generateKeyPair(); +@@ -279,14 +308,16 @@ + } + } + +- public static class ECGOST3410 +- extends EC +- { +- public ECGOST3410() +- { +- super("ECGOST3410"); +- } +- } ++ // BEGIN android-removed ++ // public static class ECGOST3410 ++ // extends EC ++ // { ++ // public ECGOST3410() ++ // { ++ // super("ECGOST3410"); ++ // } ++ // } ++ // END android-removed + + public static class ECDH + extends EC +@@ -314,4 +345,4 @@ + super("ECMQV"); + } + } +-} +\ No newline at end of file ++} +diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ec/Signature.java bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ec/Signature.java +--- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/asymmetric/ec/Signature.java 2010-01-11 21:46:14.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/asymmetric/ec/Signature.java 2010-11-17 22:23:30.000000000 +0000 +@@ -18,15 +18,21 @@ + import org.bouncycastle.crypto.CipherParameters; + import org.bouncycastle.crypto.DSA; + import org.bouncycastle.crypto.Digest; +-import org.bouncycastle.crypto.digests.RIPEMD160Digest; ++// BEGIN android-removed ++// import org.bouncycastle.crypto.digests.RIPEMD160Digest; ++// END android-removed + import org.bouncycastle.crypto.digests.SHA1Digest; +-import org.bouncycastle.crypto.digests.SHA224Digest; ++// BEGIN android-removed ++// import org.bouncycastle.crypto.digests.SHA224Digest; ++// END android-removed + import org.bouncycastle.crypto.digests.SHA256Digest; + import org.bouncycastle.crypto.digests.SHA384Digest; + import org.bouncycastle.crypto.digests.SHA512Digest; + import org.bouncycastle.crypto.params.ParametersWithRandom; + import org.bouncycastle.crypto.signers.ECDSASigner; +-import org.bouncycastle.crypto.signers.ECNRSigner; ++// BEGIN android-removed ++// import org.bouncycastle.crypto.signers.ECNRSigner; ++// END android-removed + import org.bouncycastle.jce.interfaces.ECKey; + import org.bouncycastle.jce.provider.DSABase; + import org.bouncycastle.jce.provider.DSAEncoder; +@@ -123,14 +129,16 @@ + } + } + +- static public class ecDSA224 +- extends Signature +- { +- public ecDSA224() +- { +- super(new SHA224Digest(), new ECDSASigner(), new StdDSAEncoder()); +- } +- } ++ // BEGIN android-removed ++ // static public class ecDSA224 ++ // extends Signature ++ // { ++ // public ecDSA224() ++ // { ++ // super(new SHA224Digest(), new ECDSASigner(), new StdDSAEncoder()); ++ // } ++ // } ++ // END android-removed + + static public class ecDSA256 + extends Signature +@@ -159,86 +167,88 @@ + } + } + +- static public class ecDSARipeMD160 +- extends Signature +- { +- public ecDSARipeMD160() +- { +- super(new RIPEMD160Digest(), new ECDSASigner(), new StdDSAEncoder()); +- } +- } +- +- static public class ecNR +- extends Signature +- { +- public ecNR() +- { +- super(new SHA1Digest(), new ECNRSigner(), new StdDSAEncoder()); +- } +- } +- +- static public class ecNR224 +- extends Signature +- { +- public ecNR224() +- { +- super(new SHA224Digest(), new ECNRSigner(), new StdDSAEncoder()); +- } +- } +- +- static public class ecNR256 +- extends Signature +- { +- public ecNR256() +- { +- super(new SHA256Digest(), new ECNRSigner(), new StdDSAEncoder()); +- } +- } +- +- static public class ecNR384 +- extends Signature +- { +- public ecNR384() +- { +- super(new SHA384Digest(), new ECNRSigner(), new StdDSAEncoder()); +- } +- } +- +- static public class ecNR512 +- extends Signature +- { +- public ecNR512() +- { +- super(new SHA512Digest(), new ECNRSigner(), new StdDSAEncoder()); +- } +- } +- +- static public class ecCVCDSA +- extends Signature +- { +- public ecCVCDSA() +- { +- super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder()); +- } +- } +- +- static public class ecCVCDSA224 +- extends Signature +- { +- public ecCVCDSA224() +- { +- super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder()); +- } +- } +- +- static public class ecCVCDSA256 +- extends Signature +- { +- public ecCVCDSA256() +- { +- super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder()); +- } +- } ++ // BEGIN android-removed ++ // static public class ecDSARipeMD160 ++ // extends Signature ++ // { ++ // public ecDSARipeMD160() ++ // { ++ // super(new RIPEMD160Digest(), new ECDSASigner(), new StdDSAEncoder()); ++ // } ++ // } ++ // ++ // static public class ecNR ++ // extends Signature ++ // { ++ // public ecNR() ++ // { ++ // super(new SHA1Digest(), new ECNRSigner(), new StdDSAEncoder()); ++ // } ++ // } ++ // ++ // static public class ecNR224 ++ // extends Signature ++ // { ++ // public ecNR224() ++ // { ++ // super(new SHA224Digest(), new ECNRSigner(), new StdDSAEncoder()); ++ // } ++ // } ++ // ++ // static public class ecNR256 ++ // extends Signature ++ // { ++ // public ecNR256() ++ // { ++ // super(new SHA256Digest(), new ECNRSigner(), new StdDSAEncoder()); ++ // } ++ // } ++ // ++ // static public class ecNR384 ++ // extends Signature ++ // { ++ // public ecNR384() ++ // { ++ // super(new SHA384Digest(), new ECNRSigner(), new StdDSAEncoder()); ++ // } ++ // } ++ // ++ // static public class ecNR512 ++ // extends Signature ++ // { ++ // public ecNR512() ++ // { ++ // super(new SHA512Digest(), new ECNRSigner(), new StdDSAEncoder()); ++ // } ++ // } ++ // ++ // static public class ecCVCDSA ++ // extends Signature ++ // { ++ // public ecCVCDSA() ++ // { ++ // super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder()); ++ // } ++ // } ++ // ++ // static public class ecCVCDSA224 ++ // extends Signature ++ // { ++ // public ecCVCDSA224() ++ // { ++ // super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder()); ++ // } ++ // } ++ // ++ // static public class ecCVCDSA256 ++ // extends Signature ++ // { ++ // public ecCVCDSA256() ++ // { ++ // super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder()); ++ // } ++ // } ++ // END android-removed + + private static class StdDSAEncoder + implements DSAEncoder +@@ -332,4 +342,4 @@ + return sig; + } + } +-} +\ No newline at end of file ++} diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/symmetric/AES.java bcprov-jdk16-145/org/bouncycastle/jce/provider/symmetric/AES.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/symmetric/AES.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/symmetric/AES.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/symmetric/AES.java 2010-11-17 22:23:30.000000000 +0000 @@ -5,7 +5,9 @@ import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.engines.AESFastEngine; @@ -12675,7 +13582,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/symmetric/AES.jav extends JDKAlgorithmParameters.IVAlgorithmParameters diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/symmetric/AESMappings.java bcprov-jdk16-145/org/bouncycastle/jce/provider/symmetric/AESMappings.java --- bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/symmetric/AESMappings.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/jce/provider/symmetric/AESMappings.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/jce/provider/symmetric/AESMappings.java 2010-11-17 22:23:30.000000000 +0000 @@ -26,55 +26,63 @@ put("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_CBC, "AES"); put("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_CBC, "AES"); @@ -12781,7 +13688,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/jce/provider/symmetric/AESMapp } diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/x509/X509Util.java bcprov-jdk16-145/org/bouncycastle/x509/X509Util.java --- bcprov-jdk16-145.orig/org/bouncycastle/x509/X509Util.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/x509/X509Util.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/x509/X509Util.java 2010-11-17 22:23:30.000000000 +0000 @@ -43,8 +43,10 @@ static @@ -12843,7 +13750,7 @@ diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/x509/X509Util.java bcprov-jdk1 diff -Naur bcprov-jdk16-145.orig/org/bouncycastle/x509/extension/X509ExtensionUtil.java bcprov-jdk16-145/org/bouncycastle/x509/extension/X509ExtensionUtil.java --- bcprov-jdk16-145.orig/org/bouncycastle/x509/extension/X509ExtensionUtil.java 2010-01-11 21:46:14.000000000 +0000 -+++ bcprov-jdk16-145/org/bouncycastle/x509/extension/X509ExtensionUtil.java 2010-11-09 01:06:52.000000000 +0000 ++++ bcprov-jdk16-145/org/bouncycastle/x509/extension/X509ExtensionUtil.java 2010-11-17 22:23:30.000000000 +0000 @@ -62,7 +62,9 @@ { GeneralName genName = GeneralName.getInstance(it.nextElement()); diff --git a/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java b/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java new file mode 100644 index 00000000..821e0d13 --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java @@ -0,0 +1,96 @@ +package org.bouncycastle.asn1.nist; + +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.sec.SECNamedCurves; +import org.bouncycastle.asn1.sec.SECObjectIdentifiers; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.util.Strings; + +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * Utility class for fetching curves using their NIST names as published in FIPS-PUB 186-2 + */ +public class NISTNamedCurves +{ + static final Hashtable objIds = new Hashtable(); + static final Hashtable names = new Hashtable(); + + static void defineCurve(String name, DERObjectIdentifier oid) + { + objIds.put(name, oid); + names.put(oid, name); + } + + static + { + // TODO Missing the "K-" curves + + 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("P-521", SECObjectIdentifiers.secp521r1); + defineCurve("P-384", SECObjectIdentifiers.secp384r1); + defineCurve("P-256", SECObjectIdentifiers.secp256r1); + defineCurve("P-224", SECObjectIdentifiers.secp224r1); + defineCurve("P-192", SECObjectIdentifiers.secp192r1); + } + + public static X9ECParameters getByName( + String name) + { + DERObjectIdentifier oid = (DERObjectIdentifier)objIds.get(Strings.toUpperCase(name)); + + if (oid != null) + { + return getByOID(oid); + } + + return null; + } + + /** + * return the X9ECParameters object for the named curve represented by + * the passed in object identifier. Null if the curve isn't present. + * + * @param oid an object identifier representing a named curve, if present. + */ + public static X9ECParameters getByOID( + DERObjectIdentifier oid) + { + return SECNamedCurves.getByOID(oid); + } + + /** + * return the object identifier signified by the passed in name. Null + * if there is no object identifier associated with name. + * + * @return the object identifier associated with name, if present. + */ + public static DERObjectIdentifier getOID( + String name) + { + return (DERObjectIdentifier)objIds.get(Strings.toUpperCase(name)); + } + + /** + * return the named curve name represented by the given object identifier. + */ + public static String getName( + DERObjectIdentifier oid) + { + return (String)names.get(oid); + } + + /** + * returns an enumeration containing the name strings for curves + * contained in this structure. + */ + public static Enumeration getNames() + { + return objIds.keys(); + } +} diff --git a/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java b/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java new file mode 100644 index 00000000..b9a04073 --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java @@ -0,0 +1,128 @@ +package org.bouncycastle.asn1.sec; + +import java.math.BigInteger; +import java.util.Enumeration; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.util.BigIntegers; + +/** + * the elliptic curve private key object from SEC 1 + */ +public class ECPrivateKeyStructure + extends ASN1Encodable +{ + private ASN1Sequence seq; + + public ECPrivateKeyStructure( + ASN1Sequence seq) + { + this.seq = seq; + } + + public ECPrivateKeyStructure( + BigInteger key) + { + byte[] bytes = BigIntegers.asUnsignedByteArray(key); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(new DERInteger(1)); + v.add(new DEROctetString(bytes)); + + seq = new DERSequence(v); + } + + public ECPrivateKeyStructure( + BigInteger key, + ASN1Encodable parameters) + { + this(key, null, parameters); + } + + public ECPrivateKeyStructure( + BigInteger key, + DERBitString publicKey, + ASN1Encodable parameters) + { + byte[] bytes = BigIntegers.asUnsignedByteArray(key); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(new DERInteger(1)); + v.add(new DEROctetString(bytes)); + + if (parameters != null) + { + v.add(new DERTaggedObject(true, 0, parameters)); + } + + if (publicKey != null) + { + v.add(new DERTaggedObject(true, 1, publicKey)); + } + + seq = new DERSequence(v); + } + + public BigInteger getKey() + { + ASN1OctetString octs = (ASN1OctetString)seq.getObjectAt(1); + + return new BigInteger(1, octs.getOctets()); + } + + public DERBitString getPublicKey() + { + return (DERBitString)getObjectInTag(1); + } + + public ASN1Object getParameters() + { + return getObjectInTag(0); + } + + private ASN1Object getObjectInTag(int tagNo) + { + Enumeration e = seq.getObjects(); + + while (e.hasMoreElements()) + { + DEREncodable obj = (DEREncodable)e.nextElement(); + + if (obj instanceof ASN1TaggedObject) + { + ASN1TaggedObject tag = (ASN1TaggedObject)obj; + if (tag.getTagNo() == tagNo) + { + return (ASN1Object)((DEREncodable)tag.getObject()).getDERObject(); + } + } + } + return null; + } + + /** + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] Parameters OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL } + */ + public DERObject toASN1Object() + { + return seq; + } +} diff --git a/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java b/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java new file mode 100644 index 00000000..67ead069 --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java @@ -0,0 +1,1029 @@ +package org.bouncycastle.asn1.sec; + +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.asn1.x9.X9ECParametersHolder; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.math.ec.ECConstants; +import org.bouncycastle.util.Strings; +import org.bouncycastle.util.encoders.Hex; + +import java.math.BigInteger; +import java.util.Enumeration; +import java.util.Hashtable; + +public class SECNamedCurves +{ + private static BigInteger fromHex( + String hex) + { + return new BigInteger(1, Hex.decode(hex)); + } + + /* + * secp112r1 + */ + static X9ECParametersHolder secp112r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = (2^128 - 3) / 76439 + BigInteger p = fromHex("DB7C2ABF62E35E668076BEAD208B"); + BigInteger a = fromHex("DB7C2ABF62E35E668076BEAD2088"); + BigInteger b = fromHex("659EF8BA043916EEDE8911702B22"); + byte[] S = Hex.decode("00F50B028E4D696E676875615175290472783FB1"); + BigInteger n = fromHex("DB7C2ABF62E35E7628DFAC6561C5"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("02" + //+ "09487239995A5EE76B55F9C2F098")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "09487239995A5EE76B55F9C2F098" + + "A89CE5AF8724C0A23E0E0FF77500")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp112r2 + */ + static X9ECParametersHolder secp112r2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = (2^128 - 3) / 76439 + BigInteger p = fromHex("DB7C2ABF62E35E668076BEAD208B"); + BigInteger a = fromHex("6127C24C05F38A0AAAF65C0EF02C"); + BigInteger b = fromHex("51DEF1815DB5ED74FCC34C85D709"); + byte[] S = Hex.decode("002757A1114D696E6768756151755316C05E0BD4"); + BigInteger n = fromHex("36DF0AAFD8B8D7597CA10520D04B"); + BigInteger h = BigInteger.valueOf(4); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "4BA30AB5E892B4E1649DD0928643")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "4BA30AB5E892B4E1649DD0928643" + + "ADCD46F5882E3747DEF36E956E97")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp128r1 + */ + static X9ECParametersHolder secp128r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^128 - 2^97 - 1 + BigInteger p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"); + BigInteger a = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC"); + BigInteger b = fromHex("E87579C11079F43DD824993C2CEE5ED3"); + byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679"); + BigInteger n = fromHex("FFFFFFFE0000000075A30D1B9038A115"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "161FF7528B899B2D0C28607CA52C5B86")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "161FF7528B899B2D0C28607CA52C5B86" + + "CF5AC8395BAFEB13C02DA292DDED7A83")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp128r2 + */ + static X9ECParametersHolder secp128r2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^128 - 2^97 - 1 + BigInteger p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"); + BigInteger a = fromHex("D6031998D1B3BBFEBF59CC9BBFF9AEE1"); + BigInteger b = fromHex("5EEEFCA380D02919DC2C6558BB6D8A5D"); + byte[] S = Hex.decode("004D696E67687561517512D8F03431FCE63B88F4"); + BigInteger n = fromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3"); + BigInteger h = BigInteger.valueOf(4); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("02" + //+ "7B6AA5D85E572983E6FB32A7CDEBC140")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "7B6AA5D85E572983E6FB32A7CDEBC140" + + "27B6916A894D3AEE7106FE805FC34B44")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp160k1 + */ + static X9ECParametersHolder secp160k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1 + BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"); + BigInteger a = ECConstants.ZERO; + BigInteger b = BigInteger.valueOf(7); + byte[] S = null; + BigInteger n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); +// ECPoint G = curve.decodePoint(Hex.decode("02" +// + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB" + + "938CF935318FDCED6BC28286531733C3F03C4FEE")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp160r1 + */ + static X9ECParametersHolder secp160r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^160 - 2^31 - 1 + BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"); + BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"); + BigInteger b = fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"); + byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345"); + BigInteger n = fromHex("0100000000000000000001F4C8F927AED3CA752257"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("02" + //+ "4A96B5688EF573284664698968C38BB913CBFC82")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "4A96B5688EF573284664698968C38BB913CBFC82" + + "23A628553168947D59DCC912042351377AC5FB32")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp160r2 + */ + static X9ECParametersHolder secp160r2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1 + BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"); + BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70"); + BigInteger b = fromHex("B4E134D3FB59EB8BAB57274904664D5AF50388BA"); + byte[] S = Hex.decode("B99B99B099B323E02709A4D696E6768756151751"); + BigInteger n = fromHex("0100000000000000000000351EE786A818F3A1A16B"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("02" + //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "52DCB034293A117E1F4FF11B30F7199D3144CE6D" + + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp192k1 + */ + static X9ECParametersHolder secp192k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1 + BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"); + BigInteger a = ECConstants.ZERO; + BigInteger b = BigInteger.valueOf(3); + byte[] S = null; + BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D" + + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp192r1 + */ + static X9ECParametersHolder secp192r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^192 - 2^64 - 1 + BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"); + BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"); + BigInteger b = fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"); + byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5"); + BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" + + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp224k1 + */ + static X9ECParametersHolder secp224k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1 + BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D"); + BigInteger a = ECConstants.ZERO; + BigInteger b = BigInteger.valueOf(5); + byte[] S = null; + BigInteger n = fromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C" + + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp224r1 + */ + static X9ECParametersHolder secp224r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^224 - 2^96 + 1 + BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"); + BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"); + BigInteger b = fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"); + byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5"); + BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("02" + //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" + + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp256k1 + */ + static X9ECParametersHolder secp256k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 + BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"); + BigInteger a = ECConstants.ZERO; + BigInteger b = BigInteger.valueOf(7); + byte[] S = null; + BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("02" + //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" + + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp256r1 + */ + static X9ECParametersHolder secp256r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1 + BigInteger p = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"); + BigInteger a = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"); + BigInteger b = fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"); + byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90"); + BigInteger n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp384r1 + */ + static X9ECParametersHolder secp384r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^384 - 2^128 - 2^96 + 2^32 - 1 + BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"); + BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC"); + BigInteger b = fromHex("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF"); + byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73"); + BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7" + + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * secp521r1 + */ + static X9ECParametersHolder secp521r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + // p = 2^521 - 1 + BigInteger p = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); + BigInteger a = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"); + BigInteger b = fromHex("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"); + byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA"); + BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"); + BigInteger h = BigInteger.valueOf(1); + + ECCurve curve = new ECCurve.Fp(p, a, b); + //ECPoint G = curve.decodePoint(Hex.decode("02" + //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" + + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect113r1 + */ + static X9ECParametersHolder sect113r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 113; + int k = 9; + + BigInteger a = fromHex("003088250CA6E7C7FE649CE85820F7"); + BigInteger b = fromHex("00E8BEE4D3E2260744188BE0E9C723"); + byte[] S = Hex.decode("10E723AB14D696E6768756151756FEBF8FCB49A9"); + BigInteger n = fromHex("0100000000000000D9CCEC8A39E56F"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "009D73616F35F4AB1407D73562C10F")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "009D73616F35F4AB1407D73562C10F" + + "00A52830277958EE84D1315ED31886")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect113r2 + */ + static X9ECParametersHolder sect113r2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 113; + int k = 9; + + BigInteger a = fromHex("00689918DBEC7E5A0DD6DFC0AA55C7"); + BigInteger b = fromHex("0095E9A9EC9B297BD4BF36E059184F"); + byte[] S = Hex.decode("10C0FB15760860DEF1EEF4D696E676875615175D"); + BigInteger n = fromHex("010000000000000108789B2496AF93"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "01A57A6A7B26CA5EF52FCDB8164797")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "01A57A6A7B26CA5EF52FCDB8164797" + + "00B3ADC94ED1FE674C06E695BABA1D")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect131r1 + */ + static X9ECParametersHolder sect131r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 131; + int k1 = 2; + int k2 = 3; + int k3 = 8; + + BigInteger a = fromHex("07A11B09A76B562144418FF3FF8C2570B8"); + BigInteger b = fromHex("0217C05610884B63B9C6C7291678F9D341"); + byte[] S = Hex.decode("4D696E676875615175985BD3ADBADA21B43A97E2"); + BigInteger n = fromHex("0400000000000000023123953A9464B54D"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = 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" + + "0081BAF91FDF9833C40F9C181343638399" + + "078C6E7EA38C001F73C8134B1B4EF9E150")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect131r2 + */ + static X9ECParametersHolder sect131r2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 131; + int k1 = 2; + int k2 = 3; + int k3 = 8; + + BigInteger a = fromHex("03E5A88919D7CAFCBF415F07C2176573B2"); + BigInteger b = fromHex("04B8266A46C55657AC734CE38F018F2192"); + byte[] S = Hex.decode("985BD3ADBAD4D696E676875615175A21B43A97E3"); + BigInteger n = fromHex("0400000000000000016954A233049BA98F"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = 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" + + "0356DCD8F2F95031AD652D23951BB366A8" + + "0648F06D867940A5366D9E265DE9EB240F")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect163k1 + */ + static X9ECParametersHolder sect163k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 163; + int k1 = 3; + int k2 = 6; + int k3 = 7; + + BigInteger a = BigInteger.valueOf(1); + BigInteger b = BigInteger.valueOf(1); + byte[] S = null; + BigInteger n = fromHex("04000000000000000000020108A2E0CC0D99F8A5EF"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = 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" + + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8" + + "0289070FB05D38FF58321F2E800536D538CCDAA3D9")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect163r1 + */ + static X9ECParametersHolder sect163r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 163; + int k1 = 3; + int k2 = 6; + int k3 = 7; + + BigInteger a = fromHex("07B6882CAAEFA84F9554FF8428BD88E246D2782AE2"); + BigInteger b = fromHex("0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9"); + byte[] S = Hex.decode("24B7B137C8A14D696E6768756151756FD0DA2E5C"); + BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = 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" + + "0369979697AB43897789566789567F787A7876A654" + + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect163r2 + */ + static X9ECParametersHolder sect163r2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 163; + int k1 = 3; + int k2 = 6; + int k3 = 7; + + BigInteger a = BigInteger.valueOf(1); + BigInteger b = fromHex("020A601907B8C953CA1481EB10512F78744A3205FD"); + byte[] S = Hex.decode("85E25BFE5C86226CDB12016F7553F9D0E693A268"); + BigInteger n = fromHex("040000000000000000000292FE77E70C12A4234C33"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = 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" + + "03F0EBA16286A2D57EA0991168D4994637E8343E36" + + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect193r1 + */ + static X9ECParametersHolder sect193r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 193; + int k = 15; + + BigInteger a = fromHex("0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01"); + BigInteger b = fromHex("00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814"); + byte[] S = Hex.decode("103FAEC74D696E676875615175777FC5B191EF30"); + BigInteger n = fromHex("01000000000000000000000000C7F34A778F443ACC920EBA49"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1" + + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect193r2 + */ + static X9ECParametersHolder sect193r2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 193; + int k = 15; + + BigInteger a = fromHex("0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B"); + BigInteger b = fromHex("00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE"); + byte[] S = Hex.decode("10B7B4D696E676875615175137C8A16FD0DA2211"); + BigInteger n = fromHex("010000000000000000000000015AAB561B005413CCD4EE99D5"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F" + + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect233k1 + */ + static X9ECParametersHolder sect233k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 233; + int k = 74; + + BigInteger a = ECConstants.ZERO; + BigInteger b = BigInteger.valueOf(1); + byte[] S = null; + BigInteger n = fromHex("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF"); + BigInteger h = BigInteger.valueOf(4); + + ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h); + //ECPoint G = curve.decodePoint(Hex.decode("02" + //+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126" + + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect233r1 + */ + static X9ECParametersHolder sect233r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 233; + int k = 74; + + BigInteger a = BigInteger.valueOf(1); + BigInteger b = fromHex("0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD"); + byte[] S = Hex.decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3"); + BigInteger n = fromHex("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B" + + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect239k1 + */ + static X9ECParametersHolder sect239k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 239; + int k = 158; + + BigInteger a = ECConstants.ZERO; + BigInteger b = BigInteger.valueOf(1); + byte[] S = null; + BigInteger n = fromHex("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5"); + BigInteger h = BigInteger.valueOf(4); + + ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC" + + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect283k1 + */ + static X9ECParametersHolder sect283k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 283; + int k1 = 5; + int k2 = 7; + int k3 = 12; + + BigInteger a = ECConstants.ZERO; + BigInteger b = BigInteger.valueOf(1); + byte[] S = null; + BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61"); + BigInteger h = BigInteger.valueOf(4); + + ECCurve curve = 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" + + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836" + + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect283r1 + */ + static X9ECParametersHolder sect283r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 283; + int k1 = 5; + int k2 = 7; + int k3 = 12; + + BigInteger a = BigInteger.valueOf(1); + BigInteger b = fromHex("027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5"); + byte[] S = Hex.decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE"); + BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = 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" + + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053" + + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect409k1 + */ + static X9ECParametersHolder sect409k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 409; + int k = 87; + + BigInteger a = ECConstants.ZERO; + BigInteger b = BigInteger.valueOf(1); + byte[] S = null; + BigInteger n = fromHex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF"); + BigInteger h = BigInteger.valueOf(4); + + ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746" + + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect409r1 + */ + static X9ECParametersHolder sect409r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 409; + int k = 87; + + BigInteger a = BigInteger.valueOf(1); + BigInteger b = fromHex("0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F"); + byte[] S = Hex.decode("4099B5A457F9D69F79213D094C4BCD4D4262210B"); + BigInteger n = fromHex("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h); + //ECPoint G = curve.decodePoint(Hex.decode("03" + //+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7")); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7" + + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect571k1 + */ + static X9ECParametersHolder sect571k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 571; + int k1 = 2; + int k2 = 5; + int k3 = 10; + + BigInteger a = ECConstants.ZERO; + BigInteger b = BigInteger.valueOf(1); + byte[] S = null; + BigInteger n = fromHex("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001"); + BigInteger h = BigInteger.valueOf(4); + + ECCurve curve = 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" + + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972" + + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + /* + * sect571r1 + */ + static X9ECParametersHolder sect571r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + int m = 571; + int k1 = 2; + int k2 = 5; + int k3 = 10; + + BigInteger a = BigInteger.valueOf(1); + BigInteger b = fromHex("02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A"); + byte[] S = Hex.decode("2AA058F73A0E33AB486B0F610410C53A7F132310"); + BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47"); + BigInteger h = BigInteger.valueOf(2); + + ECCurve curve = 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" + + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19" + + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B")); + + return new X9ECParameters(curve, G, n, h, S); + } + }; + + + static final Hashtable objIds = new Hashtable(); + static final Hashtable curves = new Hashtable(); + static final Hashtable names = new Hashtable(); + + static void defineCurve(String name, DERObjectIdentifier oid, X9ECParametersHolder holder) + { + objIds.put(name, oid); + names.put(oid, name); + curves.put(oid, holder); + } + + static + { + defineCurve("secp112r1", SECObjectIdentifiers.secp112r1, secp112r1); + defineCurve("secp112r2", SECObjectIdentifiers.secp112r2, secp112r2); + defineCurve("secp128r1", SECObjectIdentifiers.secp128r1, secp128r1); + defineCurve("secp128r2", SECObjectIdentifiers.secp128r2, secp128r2); + defineCurve("secp160k1", SECObjectIdentifiers.secp160k1, secp160k1); + defineCurve("secp160r1", SECObjectIdentifiers.secp160r1, secp160r1); + defineCurve("secp160r2", SECObjectIdentifiers.secp160r2, secp160r2); + defineCurve("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1); + defineCurve("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1); + defineCurve("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1); + defineCurve("secp224r1", SECObjectIdentifiers.secp224r1, secp224r1); + defineCurve("secp256k1", SECObjectIdentifiers.secp256k1, secp256k1); + defineCurve("secp256r1", SECObjectIdentifiers.secp256r1, secp256r1); + defineCurve("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1); + defineCurve("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1); + + defineCurve("sect113r1", SECObjectIdentifiers.sect113r1, sect113r1); + defineCurve("sect113r2", SECObjectIdentifiers.sect113r2, sect113r2); + defineCurve("sect131r1", SECObjectIdentifiers.sect131r1, sect131r1); + defineCurve("sect131r2", SECObjectIdentifiers.sect131r2, sect131r2); + defineCurve("sect163k1", SECObjectIdentifiers.sect163k1, sect163k1); + defineCurve("sect163r1", SECObjectIdentifiers.sect163r1, sect163r1); + defineCurve("sect163r2", SECObjectIdentifiers.sect163r2, sect163r2); + defineCurve("sect193r1", SECObjectIdentifiers.sect193r1, sect193r1); + defineCurve("sect193r2", SECObjectIdentifiers.sect193r2, sect193r2); + defineCurve("sect233k1", SECObjectIdentifiers.sect233k1, sect233k1); + defineCurve("sect233r1", SECObjectIdentifiers.sect233r1, sect233r1); + defineCurve("sect239k1", SECObjectIdentifiers.sect239k1, sect239k1); + defineCurve("sect283k1", SECObjectIdentifiers.sect283k1, sect283k1); + defineCurve("sect283r1", SECObjectIdentifiers.sect283r1, sect283r1); + defineCurve("sect409k1", SECObjectIdentifiers.sect409k1, sect409k1); + defineCurve("sect409r1", SECObjectIdentifiers.sect409r1, sect409r1); + defineCurve("sect571k1", SECObjectIdentifiers.sect571k1, sect571k1); + defineCurve("sect571r1", SECObjectIdentifiers.sect571r1, sect571r1); + } + + public static X9ECParameters getByName( + String name) + { + DERObjectIdentifier oid = (DERObjectIdentifier)objIds.get(Strings.toLowerCase(name)); + + if (oid != null) + { + return getByOID(oid); + } + + return null; + } + + /** + * return the X9ECParameters object for the named curve represented by + * the passed in object identifier. Null if the curve isn't present. + * + * @param oid an object identifier representing a named curve, if present. + */ + public static X9ECParameters getByOID( + DERObjectIdentifier oid) + { + X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid); + + if (holder != null) + { + return holder.getParameters(); + } + + return null; + } + + /** + * return the object identifier signified by the passed in name. Null + * if there is no object identifier associated with name. + * + * @return the object identifier associated with name, if present. + */ + public static DERObjectIdentifier getOID( + String name) + { + return (DERObjectIdentifier)objIds.get(Strings.toLowerCase(name)); + } + + /** + * return the named curve name represented by the given object identifier. + */ + public static String getName( + DERObjectIdentifier oid) + { + return (String)names.get(oid); + } + + /** + * returns an enumeration containing the name strings for curves + * contained in this structure. + */ + public static Enumeration getNames() + { + return objIds.keys(); + } +} diff --git a/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java b/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java new file mode 100644 index 00000000..fe066f11 --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java @@ -0,0 +1,50 @@ +package org.bouncycastle.asn1.sec; + +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; + +public interface SECObjectIdentifiers +{ + /** + * ellipticCurve OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) + * } + */ + static final DERObjectIdentifier ellipticCurve = new DERObjectIdentifier("1.3.132.0"); + + static final DERObjectIdentifier sect163k1 = new DERObjectIdentifier(ellipticCurve + ".1"); + static final DERObjectIdentifier sect163r1 = new DERObjectIdentifier(ellipticCurve + ".2"); + static final DERObjectIdentifier sect239k1 = new DERObjectIdentifier(ellipticCurve + ".3"); + static final DERObjectIdentifier sect113r1 = new DERObjectIdentifier(ellipticCurve + ".4"); + static final DERObjectIdentifier sect113r2 = new DERObjectIdentifier(ellipticCurve + ".5"); + static final DERObjectIdentifier secp112r1 = new DERObjectIdentifier(ellipticCurve + ".6"); + static final DERObjectIdentifier secp112r2 = new DERObjectIdentifier(ellipticCurve + ".7"); + static final DERObjectIdentifier secp160r1 = new DERObjectIdentifier(ellipticCurve + ".8"); + static final DERObjectIdentifier secp160k1 = new DERObjectIdentifier(ellipticCurve + ".9"); + static final DERObjectIdentifier secp256k1 = new DERObjectIdentifier(ellipticCurve + ".10"); + static final DERObjectIdentifier sect163r2 = new DERObjectIdentifier(ellipticCurve + ".15"); + static final DERObjectIdentifier sect283k1 = new DERObjectIdentifier(ellipticCurve + ".16"); + static final DERObjectIdentifier sect283r1 = new DERObjectIdentifier(ellipticCurve + ".17"); + static final DERObjectIdentifier sect131r1 = new DERObjectIdentifier(ellipticCurve + ".22"); + static final DERObjectIdentifier sect131r2 = new DERObjectIdentifier(ellipticCurve + ".23"); + static final DERObjectIdentifier sect193r1 = new DERObjectIdentifier(ellipticCurve + ".24"); + static final DERObjectIdentifier sect193r2 = new DERObjectIdentifier(ellipticCurve + ".25"); + static final DERObjectIdentifier sect233k1 = new DERObjectIdentifier(ellipticCurve + ".26"); + static final DERObjectIdentifier sect233r1 = new DERObjectIdentifier(ellipticCurve + ".27"); + static final DERObjectIdentifier secp128r1 = new DERObjectIdentifier(ellipticCurve + ".28"); + static final DERObjectIdentifier secp128r2 = new DERObjectIdentifier(ellipticCurve + ".29"); + static final DERObjectIdentifier secp160r2 = new DERObjectIdentifier(ellipticCurve + ".30"); + static final DERObjectIdentifier secp192k1 = new DERObjectIdentifier(ellipticCurve + ".31"); + static final DERObjectIdentifier secp224k1 = new DERObjectIdentifier(ellipticCurve + ".32"); + static final DERObjectIdentifier secp224r1 = new DERObjectIdentifier(ellipticCurve + ".33"); + static final DERObjectIdentifier secp384r1 = new DERObjectIdentifier(ellipticCurve + ".34"); + static final DERObjectIdentifier secp521r1 = new DERObjectIdentifier(ellipticCurve + ".35"); + static final DERObjectIdentifier sect409k1 = new DERObjectIdentifier(ellipticCurve + ".36"); + static final DERObjectIdentifier sect409r1 = new DERObjectIdentifier(ellipticCurve + ".37"); + static final DERObjectIdentifier sect571k1 = new DERObjectIdentifier(ellipticCurve + ".38"); + static final DERObjectIdentifier sect571r1 = new DERObjectIdentifier(ellipticCurve + ".39"); + + static final DERObjectIdentifier secp192r1 = X9ObjectIdentifiers.prime192v1; + static final DERObjectIdentifier secp256r1 = X9ObjectIdentifiers.prime256v1; + +} diff --git a/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java b/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java new file mode 100644 index 00000000..bda8dad3 --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java @@ -0,0 +1,621 @@ +package org.bouncycastle.asn1.x9; + +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.util.Strings; +import org.bouncycastle.util.encoders.Hex; + +import java.math.BigInteger; +import java.util.Enumeration; +import java.util.Hashtable; + + +/** + * table of the current named curves defined in X.962 EC-DSA. + */ +public class X962NamedCurves +{ + static X9ECParametersHolder prime192v1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + ECCurve cFp192v1 = new ECCurve.Fp( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), + new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); + + return new X9ECParameters( + cFp192v1, + cFp192v1.decodePoint( + Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), + new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16), + BigInteger.valueOf(1), + Hex.decode("3045AE6FC8422f64ED579528D38120EAE12196D5")); + } + }; + + static X9ECParametersHolder prime192v2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + ECCurve cFp192v2 = new ECCurve.Fp( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), + new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16)); + + return new X9ECParameters( + cFp192v2, + cFp192v2.decodePoint( + Hex.decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")), + new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16), + BigInteger.valueOf(1), + Hex.decode("31a92ee2029fd10d901b113e990710f0d21ac6b6")); + } + }; + + static X9ECParametersHolder prime192v3 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + ECCurve cFp192v3 = new ECCurve.Fp( + new BigInteger("6277101735386680763835789423207666416083908700390324961279"), + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), + new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16)); + + return new X9ECParameters( + cFp192v3, + cFp192v3.decodePoint( + Hex.decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")), + new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16), + BigInteger.valueOf(1), + Hex.decode("c469684435deb378c4b65ca9591e2a5763059a2e")); + } + }; + + static X9ECParametersHolder prime239v1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + ECCurve cFp239v1 = new ECCurve.Fp( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); + + return new X9ECParameters( + cFp239v1, + cFp239v1.decodePoint( + Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), + new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16), + BigInteger.valueOf(1), + Hex.decode("e43bb460f0b80cc0c0b075798e948060f8321b7d")); + } + }; + + static X9ECParametersHolder prime239v2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + ECCurve cFp239v2 = new ECCurve.Fp( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), + new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16)); + + return new X9ECParameters( + cFp239v2, + cFp239v2.decodePoint( + Hex.decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")), + new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16), + BigInteger.valueOf(1), + Hex.decode("e8b4011604095303ca3b8099982be09fcb9ae616")); + } + }; + + static X9ECParametersHolder prime239v3 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + ECCurve cFp239v3 = new ECCurve.Fp( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), + new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16)); + + return new X9ECParameters( + cFp239v3, + cFp239v3.decodePoint( + Hex.decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")), + new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16), + BigInteger.valueOf(1), + Hex.decode("7d7374168ffe3471b60a857686a19475d3bfa2ff")); + } + }; + + static X9ECParametersHolder prime256v1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + ECCurve cFp256v1 = new ECCurve.Fp( + new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)); + + return new X9ECParameters( + cFp256v1, + cFp256v1.decodePoint( + Hex.decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + BigInteger.valueOf(1), + Hex.decode("c49d360886e704936a6678e1139d26b7819f7e90")); + } + }; + + /* + * F2m Curves + */ + static X9ECParametersHolder c2pnb163v1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m163v1n = new BigInteger("0400000000000000000001E60FC8821CC74DAEAFC1", 16); + BigInteger c2m163v1h = BigInteger.valueOf(2); + + ECCurve c2m163v1 = new ECCurve.F2m( + 163, + 1, 2, 8, + new BigInteger("072546B5435234A422E0789675F432C89435DE5242", 16), + new BigInteger("00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", 16), + c2m163v1n, c2m163v1h); + + return new X9ECParameters( + c2m163v1, + c2m163v1.decodePoint( + Hex.decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")), + c2m163v1n, c2m163v1h, + Hex.decode("D2COFB15760860DEF1EEF4D696E6768756151754")); + } + }; + + static X9ECParametersHolder c2pnb163v2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m163v2n = new BigInteger("03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 16); + BigInteger c2m163v2h = BigInteger.valueOf(2); + + ECCurve c2m163v2 = new ECCurve.F2m( + 163, + 1, 2, 8, + new BigInteger("0108B39E77C4B108BED981ED0E890E117C511CF072", 16), + new BigInteger("0667ACEB38AF4E488C407433FFAE4F1C811638DF20", 16), + c2m163v2n, c2m163v2h); + + return new X9ECParameters( + c2m163v2, + c2m163v2.decodePoint( + Hex.decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")), + c2m163v2n, c2m163v2h, + null); + } + }; + + static X9ECParametersHolder c2pnb163v3 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m163v3n = new BigInteger("03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 16); + BigInteger c2m163v3h = BigInteger.valueOf(2); + + ECCurve c2m163v3 = new ECCurve.F2m( + 163, + 1, 2, 8, + new BigInteger("07A526C63D3E25A256A007699F5447E32AE456B50E", 16), + new BigInteger("03F7061798EB99E238FD6F1BF95B48FEEB4854252B", 16), + c2m163v3n, c2m163v3h); + + return new X9ECParameters( + c2m163v3, + c2m163v3.decodePoint( + Hex.decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")), + c2m163v3n, c2m163v3h, + null); + } + }; + + static X9ECParametersHolder c2pnb176w1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m176w1n = new BigInteger("010092537397ECA4F6145799D62B0A19CE06FE26AD", 16); + BigInteger c2m176w1h = BigInteger.valueOf(0xFF6E); + + ECCurve c2m176w1 = new ECCurve.F2m( + 176, + 1, 2, 43, + new BigInteger("00E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", 16), + new BigInteger("005DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", 16), + c2m176w1n, c2m176w1h); + + return new X9ECParameters( + c2m176w1, + c2m176w1.decodePoint( + Hex.decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")), + c2m176w1n, c2m176w1h, + null); + } + }; + + static X9ECParametersHolder c2tnb191v1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m191v1n = new BigInteger("40000000000000000000000004A20E90C39067C893BBB9A5", 16); + BigInteger c2m191v1h = BigInteger.valueOf(2); + + ECCurve c2m191v1 = new ECCurve.F2m( + 191, + 9, + new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16), + new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16), + c2m191v1n, c2m191v1h); + + return new X9ECParameters( + c2m191v1, + c2m191v1.decodePoint( + Hex.decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")), + c2m191v1n, c2m191v1h, + Hex.decode("4E13CA542744D696E67687561517552F279A8C84")); + } + }; + + static X9ECParametersHolder c2tnb191v2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m191v2n = new BigInteger("20000000000000000000000050508CB89F652824E06B8173", 16); + BigInteger c2m191v2h = BigInteger.valueOf(4); + + ECCurve c2m191v2 = new ECCurve.F2m( + 191, + 9, + new BigInteger("401028774D7777C7B7666D1366EA432071274F89FF01E718", 16), + new BigInteger("0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", 16), + c2m191v2n, c2m191v2h); + + return new X9ECParameters( + c2m191v2, + c2m191v2.decodePoint( + Hex.decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")), + c2m191v2n, c2m191v2h, + null); + } + }; + + static X9ECParametersHolder c2tnb191v3 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m191v3n = new BigInteger("155555555555555555555555610C0B196812BFB6288A3EA3", 16); + BigInteger c2m191v3h = BigInteger.valueOf(6); + + ECCurve c2m191v3 = new ECCurve.F2m( + 191, + 9, + new BigInteger("6C01074756099122221056911C77D77E77A777E7E7E77FCB", 16), + new BigInteger("71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", 16), + c2m191v3n, c2m191v3h); + + return new X9ECParameters( + c2m191v3, + c2m191v3.decodePoint( + Hex.decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")), + c2m191v3n, c2m191v3h, + null); + } + }; + + static X9ECParametersHolder c2pnb208w1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m208w1n = new BigInteger("0101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 16); + BigInteger c2m208w1h = BigInteger.valueOf(0xFE48); + + ECCurve c2m208w1 = new ECCurve.F2m( + 208, + 1, 2, 83, + new BigInteger("0", 16), + new BigInteger("00C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", 16), + c2m208w1n, c2m208w1h); + + return new X9ECParameters( + c2m208w1, + c2m208w1.decodePoint( + Hex.decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")), + c2m208w1n, c2m208w1h, + null); + } + }; + + static X9ECParametersHolder c2tnb239v1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m239v1n = new BigInteger("2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 16); + BigInteger c2m239v1h = BigInteger.valueOf(4); + + ECCurve c2m239v1 = new ECCurve.F2m( + 239, + 36, + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16), + c2m239v1n, c2m239v1h); + + return new X9ECParameters( + c2m239v1, + c2m239v1.decodePoint( + Hex.decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")), + c2m239v1n, c2m239v1h, + null); + } + }; + + static X9ECParametersHolder c2tnb239v2 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m239v2n = new BigInteger("1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 16); + BigInteger c2m239v2h = BigInteger.valueOf(6); + + ECCurve c2m239v2 = new ECCurve.F2m( + 239, + 36, + new BigInteger("4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", 16), + new BigInteger("5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", 16), + c2m239v2n, c2m239v2h); + + return new X9ECParameters( + c2m239v2, + c2m239v2.decodePoint( + Hex.decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")), + c2m239v2n, c2m239v2h, + null); + } + }; + + static X9ECParametersHolder c2tnb239v3 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m239v3n = new BigInteger("0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 16); + BigInteger c2m239v3h = BigInteger.valueOf(10); + + ECCurve c2m239v3 = new ECCurve.F2m( + 239, + 36, + new BigInteger("01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", 16), + new BigInteger("6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", 16), + c2m239v3n, c2m239v3h); + + return new X9ECParameters( + c2m239v3, + c2m239v3.decodePoint( + Hex.decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")), + c2m239v3n, c2m239v3h, + null); + } + }; + + static X9ECParametersHolder c2pnb272w1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m272w1n = new BigInteger("0100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", 16); + BigInteger c2m272w1h = BigInteger.valueOf(0xFF06); + + ECCurve c2m272w1 = new ECCurve.F2m( + 272, + 1, 3, 56, + new BigInteger("0091A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", 16), + new BigInteger("7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", 16), + c2m272w1n, c2m272w1h); + + return new X9ECParameters( + c2m272w1, + c2m272w1.decodePoint( + Hex.decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")), + c2m272w1n, c2m272w1h, + null); + } + }; + + static X9ECParametersHolder c2pnb304w1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m304w1n = new BigInteger("0101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 16); + BigInteger c2m304w1h = BigInteger.valueOf(0xFE2E); + + ECCurve c2m304w1 = new ECCurve.F2m( + 304, + 1, 2, 11, + new BigInteger("00FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", 16), + new BigInteger("00BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", 16), + c2m304w1n, c2m304w1h); + + return new X9ECParameters( + c2m304w1, + c2m304w1.decodePoint( + Hex.decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")), + c2m304w1n, c2m304w1h, + null); + } + }; + + static X9ECParametersHolder c2tnb359v1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m359v1n = new BigInteger("01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 16); + BigInteger c2m359v1h = BigInteger.valueOf(0x4C); + + ECCurve c2m359v1 = new ECCurve.F2m( + 359, + 68, + new BigInteger("5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", 16), + new BigInteger("2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", 16), + c2m359v1n, c2m359v1h); + + return new X9ECParameters( + c2m359v1, + c2m359v1.decodePoint( + Hex.decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")), + c2m359v1n, c2m359v1h, + null); + } + }; + + static X9ECParametersHolder c2pnb368w1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m368w1n = new BigInteger("010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 16); + BigInteger c2m368w1h = BigInteger.valueOf(0xFF70); + + ECCurve c2m368w1 = new ECCurve.F2m( + 368, + 1, 2, 85, + new BigInteger("00E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", 16), + new BigInteger("00FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", 16), + c2m368w1n, c2m368w1h); + + return new X9ECParameters( + c2m368w1, + c2m368w1.decodePoint( + Hex.decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")), + c2m368w1n, c2m368w1h, + null); + } + }; + + static X9ECParametersHolder c2tnb431r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + BigInteger c2m431r1n = new BigInteger("0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 16); + BigInteger c2m431r1h = BigInteger.valueOf(0x2760); + + ECCurve c2m431r1 = new ECCurve.F2m( + 431, + 120, + new BigInteger("1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", 16), + new BigInteger("10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", 16), + c2m431r1n, c2m431r1h); + + return new X9ECParameters( + c2m431r1, + c2m431r1.decodePoint( + Hex.decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")), + c2m431r1n, c2m431r1h, + null); + } + }; + + static final Hashtable objIds = new Hashtable(); + static final Hashtable curves = new Hashtable(); + static final Hashtable names = new Hashtable(); + + static void defineCurve(String name, DERObjectIdentifier oid, X9ECParametersHolder holder) + { + objIds.put(name, oid); + names.put(oid, name); + curves.put(oid, holder); + } + + static + { + defineCurve("prime192v1", X9ObjectIdentifiers.prime192v1, prime192v1); + defineCurve("prime192v2", X9ObjectIdentifiers.prime192v2, prime192v2); + defineCurve("prime192v3", X9ObjectIdentifiers.prime192v3, prime192v3); + defineCurve("prime239v1", X9ObjectIdentifiers.prime239v1, prime239v1); + defineCurve("prime239v2", X9ObjectIdentifiers.prime239v2, prime239v2); + defineCurve("prime239v3", X9ObjectIdentifiers.prime239v3, prime239v3); + defineCurve("prime256v1", X9ObjectIdentifiers.prime256v1, prime256v1); + defineCurve("c2pnb163v1", X9ObjectIdentifiers.c2pnb163v1, c2pnb163v1); + defineCurve("c2pnb163v2", X9ObjectIdentifiers.c2pnb163v2, c2pnb163v2); + defineCurve("c2pnb163v3", X9ObjectIdentifiers.c2pnb163v3, c2pnb163v3); + defineCurve("c2pnb176w1", X9ObjectIdentifiers.c2pnb176w1, c2pnb176w1); + defineCurve("c2tnb191v1", X9ObjectIdentifiers.c2tnb191v1, c2tnb191v1); + defineCurve("c2tnb191v2", X9ObjectIdentifiers.c2tnb191v2, c2tnb191v2); + defineCurve("c2tnb191v3", X9ObjectIdentifiers.c2tnb191v3, c2tnb191v3); + defineCurve("c2pnb208w1", X9ObjectIdentifiers.c2pnb208w1, c2pnb208w1); + defineCurve("c2tnb239v1", X9ObjectIdentifiers.c2tnb239v1, c2tnb239v1); + defineCurve("c2tnb239v2", X9ObjectIdentifiers.c2tnb239v2, c2tnb239v2); + defineCurve("c2tnb239v3", X9ObjectIdentifiers.c2tnb239v3, c2tnb239v3); + defineCurve("c2pnb272w1", X9ObjectIdentifiers.c2pnb272w1, c2pnb272w1); + defineCurve("c2pnb304w1", X9ObjectIdentifiers.c2pnb304w1, c2pnb304w1); + defineCurve("c2tnb359v1", X9ObjectIdentifiers.c2tnb359v1, c2tnb359v1); + defineCurve("c2pnb368w1", X9ObjectIdentifiers.c2pnb368w1, c2pnb368w1); + defineCurve("c2tnb431r1", X9ObjectIdentifiers.c2tnb431r1, c2tnb431r1); + } + + public static X9ECParameters getByName( + String name) + { + DERObjectIdentifier oid = (DERObjectIdentifier)objIds.get(Strings.toLowerCase(name)); + + if (oid != null) + { + return getByOID(oid); + } + + return null; + } + + /** + * return the X9ECParameters object for the named curve represented by + * the passed in object identifier. Null if the curve isn't present. + * + * @param oid an object identifier representing a named curve, if present. + */ + public static X9ECParameters getByOID( + DERObjectIdentifier oid) + { + X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid); + + if (holder != null) + { + return holder.getParameters(); + } + + return null; + } + + /** + * return the object identifier signified by the passed in name. Null + * if there is no object identifier associated with name. + * + * @return the object identifier associated with name, if present. + */ + public static DERObjectIdentifier getOID( + String name) + { + return (DERObjectIdentifier)objIds.get(Strings.toLowerCase(name)); + } + + /** + * return the named curve name represented by the given object identifier. + */ + public static String getName( + DERObjectIdentifier oid) + { + return (String)names.get(oid); + } + + /** + * returns an enumeration containing the name strings for curves + * contained in this structure. + */ + public static Enumeration getNames() + { + return objIds.keys(); + } +} diff --git a/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java b/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java new file mode 100644 index 00000000..de35186a --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java @@ -0,0 +1,86 @@ +package org.bouncycastle.asn1.x9; + +import org.bouncycastle.asn1.ASN1Choice; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Null; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; + +public class X962Parameters + extends ASN1Encodable + implements ASN1Choice +{ + private DERObject params = null; + + public static X962Parameters getInstance( + Object obj) + { + if (obj == null || obj instanceof X962Parameters) + { + return (X962Parameters)obj; + } + + if (obj instanceof DERObject) + { + return new X962Parameters((DERObject)obj); + } + + throw new IllegalArgumentException("unknown object in getInstance()"); + } + + public static X962Parameters getInstance( + ASN1TaggedObject obj, + boolean explicit) + { + return getInstance(obj.getObject()); // must be explicitly tagged + } + + public X962Parameters( + X9ECParameters ecParameters) + { + this.params = ecParameters.getDERObject(); + } + + public X962Parameters( + DERObjectIdentifier namedCurve) + { + this.params = namedCurve; + } + + public X962Parameters( + DERObject obj) + { + this.params = obj; + } + + public boolean isNamedCurve() + { + return (params instanceof DERObjectIdentifier); + } + + public boolean isImplicitlyCA() + { + return (params instanceof ASN1Null); + } + + public DERObject getParameters() + { + return params; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + * <pre> + * Parameters ::= CHOICE { + * ecParameters ECParameters, + * namedCurve CURVES.&id({CurveNames}), + * implicitlyCA NULL + * } + * </pre> + */ + public DERObject toASN1Object() + { + return params; + } +} diff --git a/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java b/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java new file mode 100644 index 00000000..8f46c075 --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java @@ -0,0 +1,161 @@ +package org.bouncycastle.asn1.x9; + +import java.math.BigInteger; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.math.ec.ECCurve; + +/** + * ASN.1 def for Elliptic-Curve Curve structure. See + * X9.62, for further details. + */ +public class X9Curve + extends ASN1Encodable + implements X9ObjectIdentifiers +{ + private ECCurve curve; + private byte[] seed; + private DERObjectIdentifier fieldIdentifier = null; + + public X9Curve( + ECCurve curve) + { + this.curve = curve; + this.seed = null; + setFieldIdentifier(); + } + + public X9Curve( + ECCurve curve, + byte[] seed) + { + this.curve = curve; + this.seed = seed; + setFieldIdentifier(); + } + + public X9Curve( + X9FieldID fieldID, + ASN1Sequence seq) + { + fieldIdentifier = fieldID.getIdentifier(); + if (fieldIdentifier.equals(prime_field)) + { + BigInteger p = ((DERInteger)fieldID.getParameters()).getValue(); + X9FieldElement x9A = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(0)); + X9FieldElement x9B = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(1)); + curve = new ECCurve.Fp(p, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger()); + } + else + { + if (fieldIdentifier.equals(characteristic_two_field)) + { + // Characteristic two field + DERSequence parameters = (DERSequence)fieldID.getParameters(); + int m = ((DERInteger)parameters.getObjectAt(0)).getValue(). + intValue(); + DERObjectIdentifier representation + = (DERObjectIdentifier)parameters.getObjectAt(1); + + int k1 = 0; + int k2 = 0; + int k3 = 0; + if (representation.equals(tpBasis)) + { + // Trinomial basis representation + k1 = ((DERInteger)parameters.getObjectAt(2)).getValue(). + intValue(); + } + else + { + // Pentanomial basis representation + DERSequence pentanomial + = (DERSequence)parameters.getObjectAt(2); + k1 = ((DERInteger)pentanomial.getObjectAt(0)).getValue(). + intValue(); + k2 = ((DERInteger)pentanomial.getObjectAt(1)).getValue(). + intValue(); + k3 = ((DERInteger)pentanomial.getObjectAt(2)).getValue(). + intValue(); + } + X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0)); + X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1)); + // TODO Is it possible to get the order (n) and cofactor(h) too? + curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger()); + } + } + + if (seq.size() == 3) + { + seed = ((DERBitString)seq.getObjectAt(2)).getBytes(); + } + } + + private void setFieldIdentifier() + { + if (curve instanceof ECCurve.Fp) + { + fieldIdentifier = prime_field; + } + else if (curve instanceof ECCurve.F2m) + { + fieldIdentifier = characteristic_two_field; + } + else + { + throw new IllegalArgumentException("This type of ECCurve is not " + + "implemented"); + } + } + + public ECCurve getCurve() + { + return curve; + } + + public byte[] getSeed() + { + return seed; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + * <pre> + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * } + * </pre> + */ + public DERObject toASN1Object() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + if (fieldIdentifier.equals(prime_field)) + { + v.add(new X9FieldElement(curve.getA()).getDERObject()); + v.add(new X9FieldElement(curve.getB()).getDERObject()); + } + else if (fieldIdentifier.equals(characteristic_two_field)) + { + v.add(new X9FieldElement(curve.getA()).getDERObject()); + v.add(new X9FieldElement(curve.getB()).getDERObject()); + } + + if (seed != null) + { + v.add(new DERBitString(seed)); + } + + return new DERSequence(v); + } +} diff --git a/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java b/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java new file mode 100644 index 00000000..c3b0d66b --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java @@ -0,0 +1,161 @@ +package org.bouncycastle.asn1.x9; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECPoint; + +import java.math.BigInteger; + +/** + * ASN.1 def for Elliptic-Curve ECParameters structure. See + * X9.62, for further details. + */ +public class X9ECParameters + extends ASN1Encodable + implements X9ObjectIdentifiers +{ + private static final BigInteger ONE = BigInteger.valueOf(1); + + private X9FieldID fieldID; + private ECCurve curve; + private ECPoint g; + private BigInteger n; + private BigInteger h; + private byte[] seed; + + public X9ECParameters( + ASN1Sequence seq) + { + if (!(seq.getObjectAt(0) instanceof DERInteger) + || !((DERInteger)seq.getObjectAt(0)).getValue().equals(ONE)) + { + throw new IllegalArgumentException("bad version in X9ECParameters"); + } + + X9Curve x9c = new X9Curve( + new X9FieldID((ASN1Sequence)seq.getObjectAt(1)), + (ASN1Sequence)seq.getObjectAt(2)); + + this.curve = x9c.getCurve(); + this.g = new X9ECPoint(curve, (ASN1OctetString)seq.getObjectAt(3)).getPoint(); + this.n = ((DERInteger)seq.getObjectAt(4)).getValue(); + this.seed = x9c.getSeed(); + + if (seq.size() == 6) + { + this.h = ((DERInteger)seq.getObjectAt(5)).getValue(); + } + } + + public X9ECParameters( + ECCurve curve, + ECPoint g, + BigInteger n) + { + this(curve, g, n, ONE, null); + } + + public X9ECParameters( + ECCurve curve, + ECPoint g, + BigInteger n, + BigInteger h) + { + this(curve, g, n, h, null); + } + + public X9ECParameters( + ECCurve curve, + ECPoint g, + BigInteger n, + BigInteger h, + byte[] seed) + { + this.curve = curve; + this.g = g; + this.n = n; + this.h = h; + this.seed = seed; + + if (curve instanceof ECCurve.Fp) + { + this.fieldID = new X9FieldID(((ECCurve.Fp)curve).getQ()); + } + else + { + if (curve instanceof ECCurve.F2m) + { + ECCurve.F2m curveF2m = (ECCurve.F2m)curve; + this.fieldID = new X9FieldID(curveF2m.getM(), curveF2m.getK1(), + curveF2m.getK2(), curveF2m.getK3()); + } + } + } + + public ECCurve getCurve() + { + return curve; + } + + public ECPoint getG() + { + return g; + } + + public BigInteger getN() + { + return n; + } + + public BigInteger getH() + { + if (h == null) + { + return ONE; // TODO - this should be calculated, it will cause issues with custom curves. + } + + return h; + } + + public byte[] getSeed() + { + return seed; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + * <pre> + * ECParameters ::= SEQUENCE { + * version INTEGER { ecpVer1(1) } (ecpVer1), + * fieldID FieldID {{FieldTypes}}, + * curve X9Curve, + * base X9ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL + * } + * </pre> + */ + public DERObject toASN1Object() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(new DERInteger(1)); + v.add(fieldID); + v.add(new X9Curve(curve, seed)); + v.add(new X9ECPoint(g)); + v.add(new DERInteger(n)); + + if (h != null) + { + v.add(new DERInteger(h)); + } + + return new DERSequence(v); + } +} diff --git a/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java b/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java new file mode 100644 index 00000000..47361f89 --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java @@ -0,0 +1,18 @@ +package org.bouncycastle.asn1.x9; + +public abstract class X9ECParametersHolder +{ + private X9ECParameters params; + + public X9ECParameters getParameters() + { + if (params == null) + { + params = createParameters(); + } + + return params; + } + + protected abstract X9ECParameters createParameters(); +} diff --git a/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java b/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java new file mode 100644 index 00000000..470b3d61 --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java @@ -0,0 +1,48 @@ +package org.bouncycastle.asn1.x9; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECPoint; + +/** + * class for describing an ECPoint as a DER object. + */ +public class X9ECPoint + extends ASN1Encodable +{ + ECPoint p; + + public X9ECPoint( + ECPoint p) + { + this.p = p; + } + + public X9ECPoint( + ECCurve c, + ASN1OctetString s) + { + this.p = c.decodePoint(s.getOctets()); + } + + public ECPoint getPoint() + { + return p; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + * <pre> + * ECPoint ::= OCTET STRING + * </pre> + * <p> + * Octet string produced using ECPoint.getEncoded(). + */ + public DERObject toASN1Object() + { + return new DEROctetString(p.getEncoded()); + } +} diff --git a/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java b/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java new file mode 100644 index 00000000..2173d2ae --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java @@ -0,0 +1,64 @@ +package org.bouncycastle.asn1.x9; + +import java.math.BigInteger; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.math.ec.ECFieldElement; + +/** + * class for processing an FieldElement as a DER object. + */ +public class X9FieldElement + extends ASN1Encodable +{ + protected ECFieldElement f; + + private static X9IntegerConverter converter = new X9IntegerConverter(); + + public X9FieldElement(ECFieldElement f) + { + this.f = f; + } + + public X9FieldElement(BigInteger p, ASN1OctetString s) + { + this(new ECFieldElement.Fp(p, new BigInteger(1, s.getOctets()))); + } + + public X9FieldElement(int m, int k1, int k2, int k3, ASN1OctetString s) + { + this(new ECFieldElement.F2m(m, k1, k2, k3, new BigInteger(1, s.getOctets()))); + } + + public ECFieldElement getValue() + { + return f; + } + + /** + * Produce an object suitable for an ASN1OutputStream. + * <pre> + * FieldElement ::= OCTET STRING + * </pre> + * <p> + * <ol> + * <li> if <i>q</i> is an odd prime then the field element is + * processed as an Integer and converted to an octet string + * according to x 9.62 4.3.1.</li> + * <li> if <i>q</i> is 2<sup>m</sup> then the bit string + * contained in the field element is converted into an octet + * string with the same ordering padded at the front if necessary. + * </li> + * </ol> + */ + public DERObject toASN1Object() + { + int byteCount = converter.getByteLength(f); + byte[] paddedBigInteger = converter.integerToBytes(f.toBigInteger(), byteCount); + + return new DEROctetString(paddedBigInteger); + } +} diff --git a/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java b/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java new file mode 100644 index 00000000..c2c2ef9f --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java @@ -0,0 +1,109 @@ +package org.bouncycastle.asn1.x9; + +import java.math.BigInteger; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; + +/** + * ASN.1 def for Elliptic-Curve Field ID structure. See + * X9.62, for further details. + */ +public class X9FieldID + extends ASN1Encodable + implements X9ObjectIdentifiers +{ + private DERObjectIdentifier id; + private DERObject parameters; + + /** + * Constructor for elliptic curves over prime fields + * <code>F<sub>2</sub></code>. + * @param primeP The prime <code>p</code> defining the prime field. + */ + public X9FieldID(BigInteger primeP) + { + this.id = prime_field; + this.parameters = new DERInteger(primeP); + } + + /** + * Constructor for elliptic curves over binary fields + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param m The exponent <code>m</code> of + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.. + */ + public X9FieldID(int m, int k1, int k2, int k3) + { + this.id = characteristic_two_field; + ASN1EncodableVector fieldIdParams = new ASN1EncodableVector(); + fieldIdParams.add(new DERInteger(m)); + + if (k2 == 0) + { + fieldIdParams.add(tpBasis); + fieldIdParams.add(new DERInteger(k1)); + } + else + { + fieldIdParams.add(ppBasis); + ASN1EncodableVector pentanomialParams = new ASN1EncodableVector(); + pentanomialParams.add(new DERInteger(k1)); + pentanomialParams.add(new DERInteger(k2)); + pentanomialParams.add(new DERInteger(k3)); + fieldIdParams.add(new DERSequence(pentanomialParams)); + } + + this.parameters = new DERSequence(fieldIdParams); + } + + public X9FieldID( + ASN1Sequence seq) + { + this.id = (DERObjectIdentifier)seq.getObjectAt(0); + this.parameters = (DERObject)seq.getObjectAt(1); + } + + public DERObjectIdentifier getIdentifier() + { + return id; + } + + public DERObject getParameters() + { + return parameters; + } + + /** + * Produce a DER encoding of the following structure. + * <pre> + * FieldID ::= SEQUENCE { + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + * </pre> + */ + public DERObject toASN1Object() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(this.id); + v.add(this.parameters); + + return new DERSequence(v); + } +} diff --git a/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java b/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java new file mode 100644 index 00000000..ae820abb --- /dev/null +++ b/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java @@ -0,0 +1,47 @@ +package org.bouncycastle.asn1.x9; + +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECFieldElement; + +import java.math.BigInteger; + +public class X9IntegerConverter +{ + public int getByteLength( + ECCurve c) + { + return (c.getFieldSize() + 7) / 8; + } + + public int getByteLength( + ECFieldElement fe) + { + return (fe.getFieldSize() + 7) / 8; + } + + public byte[] integerToBytes( + BigInteger s, + int qLength) + { + byte[] bytes = s.toByteArray(); + + if (qLength < bytes.length) + { + byte[] tmp = new byte[qLength]; + + System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length); + + return tmp; + } + else if (qLength > bytes.length) + { + byte[] tmp = new byte[qLength]; + + System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length); + + return tmp; + } + + return bytes; + } +} diff --git a/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java b/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java new file mode 100644 index 00000000..3ad3e1ca --- /dev/null +++ b/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java @@ -0,0 +1,47 @@ +package org.bouncycastle.crypto.agreement; + +import java.math.BigInteger; + +import org.bouncycastle.math.ec.ECPoint; + +import org.bouncycastle.crypto.BasicAgreement; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; + +/** + * P1363 7.2.1 ECSVDP-DH + * + * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive, + * Diffie-Hellman version. It is based on the work of [DH76], [Mil86], + * and [Kob87]. This primitive derives a shared secret value from one + * party's private key and another party's public key, where both have + * the same set of EC domain parameters. If two parties correctly + * execute this primitive, they will produce the same output. This + * primitive can be invoked by a scheme to derive a shared secret key; + * specifically, it may be used with the schemes ECKAS-DH1 and + * DL/ECKAS-DH2. It assumes that the input keys are valid (see also + * Section 7.2.2). + */ +public class ECDHBasicAgreement + implements BasicAgreement +{ + private ECPrivateKeyParameters key; + + public void init( + CipherParameters key) + { + this.key = (ECPrivateKeyParameters)key; + } + + public BigInteger calculateAgreement( + CipherParameters pubKey) + { + ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey; + ECPoint P = pub.getQ().multiply(key.getD()); + + // if (p.isInfinity()) throw new RuntimeException("d*Q == infinity"); + + return P.getX().toBigInteger(); + } +} diff --git a/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java b/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java new file mode 100644 index 00000000..d77bd747 --- /dev/null +++ b/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java @@ -0,0 +1,53 @@ +package org.bouncycastle.crypto.generators; + +import java.math.BigInteger; +import java.security.SecureRandom; + +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; +import org.bouncycastle.crypto.KeyGenerationParameters; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECKeyGenerationParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.math.ec.ECConstants; +import org.bouncycastle.math.ec.ECPoint; + +public class ECKeyPairGenerator + implements AsymmetricCipherKeyPairGenerator, ECConstants +{ + ECDomainParameters params; + SecureRandom random; + + public void init( + KeyGenerationParameters param) + { + ECKeyGenerationParameters ecP = (ECKeyGenerationParameters)param; + + this.random = ecP.getRandom(); + this.params = ecP.getDomainParameters(); + } + + /** + * Given the domain parameters this routine generates an EC key + * pair in accordance with X9.62 section 5.2.1 pages 26, 27. + */ + public AsymmetricCipherKeyPair generateKeyPair() + { + BigInteger n = params.getN(); + int nBitLength = n.bitLength(); + BigInteger d; + + do + { + d = new BigInteger(nBitLength, random); + } + while (d.equals(ZERO) || (d.compareTo(n) >= 0)); + + ECPoint Q = params.getG().multiply(d); + + return new AsymmetricCipherKeyPair( + new ECPublicKeyParameters(Q, params), + new ECPrivateKeyParameters(d, params)); + } +} diff --git a/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java b/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java new file mode 100644 index 00000000..95a3ec96 --- /dev/null +++ b/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java @@ -0,0 +1,81 @@ +package org.bouncycastle.crypto.params; + +import java.math.BigInteger; + +import org.bouncycastle.math.ec.ECConstants; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECPoint; + +public class ECDomainParameters + implements ECConstants +{ + ECCurve curve; + byte[] seed; + ECPoint G; + BigInteger n; + BigInteger h; + + public ECDomainParameters( + ECCurve curve, + ECPoint G, + BigInteger n) + { + this.curve = curve; + this.G = G; + this.n = n; + this.h = ONE; + this.seed = null; + } + + public ECDomainParameters( + ECCurve curve, + ECPoint G, + BigInteger n, + BigInteger h) + { + this.curve = curve; + this.G = G; + this.n = n; + this.h = h; + this.seed = null; + } + + public ECDomainParameters( + ECCurve curve, + ECPoint G, + BigInteger n, + BigInteger h, + byte[] seed) + { + this.curve = curve; + this.G = G; + this.n = n; + this.h = h; + this.seed = seed; + } + + public ECCurve getCurve() + { + return curve; + } + + public ECPoint getG() + { + return G; + } + + public BigInteger getN() + { + return n; + } + + public BigInteger getH() + { + return h; + } + + public byte[] getSeed() + { + return seed; + } +} diff --git a/src/main/java/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java b/src/main/java/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java new file mode 100644 index 00000000..be3f20f5 --- /dev/null +++ b/src/main/java/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java @@ -0,0 +1,25 @@ +package org.bouncycastle.crypto.params; + +import java.security.SecureRandom; + +import org.bouncycastle.crypto.KeyGenerationParameters; + +public class ECKeyGenerationParameters + extends KeyGenerationParameters +{ + private ECDomainParameters domainParams; + + public ECKeyGenerationParameters( + ECDomainParameters domainParams, + SecureRandom random) + { + super(random, domainParams.getN().bitLength()); + + this.domainParams = domainParams; + } + + public ECDomainParameters getDomainParameters() + { + return domainParams; + } +} diff --git a/src/main/java/org/bouncycastle/crypto/params/ECKeyParameters.java b/src/main/java/org/bouncycastle/crypto/params/ECKeyParameters.java new file mode 100644 index 00000000..19825c5b --- /dev/null +++ b/src/main/java/org/bouncycastle/crypto/params/ECKeyParameters.java @@ -0,0 +1,21 @@ +package org.bouncycastle.crypto.params; + +public class ECKeyParameters + extends AsymmetricKeyParameter +{ + ECDomainParameters params; + + protected ECKeyParameters( + boolean isPrivate, + ECDomainParameters params) + { + super(isPrivate); + + this.params = params; + } + + public ECDomainParameters getParameters() + { + return params; + } +} diff --git a/src/main/java/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java b/src/main/java/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java new file mode 100644 index 00000000..3e49983e --- /dev/null +++ b/src/main/java/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java @@ -0,0 +1,22 @@ +package org.bouncycastle.crypto.params; + +import java.math.BigInteger; + +public class ECPrivateKeyParameters + extends ECKeyParameters +{ + BigInteger d; + + public ECPrivateKeyParameters( + BigInteger d, + ECDomainParameters params) + { + super(true, params); + this.d = d; + } + + public BigInteger getD() + { + return d; + } +} diff --git a/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java b/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java new file mode 100644 index 00000000..5fbea19e --- /dev/null +++ b/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java @@ -0,0 +1,22 @@ +package org.bouncycastle.crypto.params; + +import org.bouncycastle.math.ec.ECPoint; + +public class ECPublicKeyParameters + extends ECKeyParameters +{ + ECPoint Q; + + public ECPublicKeyParameters( + ECPoint Q, + ECDomainParameters params) + { + super(false, params); + this.Q = Q; + } + + public ECPoint getQ() + { + return Q; + } +} diff --git a/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java b/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java new file mode 100644 index 00000000..0341227c --- /dev/null +++ b/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java @@ -0,0 +1,164 @@ +package org.bouncycastle.crypto.signers; + +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.DSA; +import org.bouncycastle.crypto.params.ECKeyParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +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.ECPoint; + +import java.math.BigInteger; +import java.security.SecureRandom; + +/** + * EC-DSA as described in X9.62 + */ +public class ECDSASigner + implements ECConstants, DSA +{ + ECKeyParameters key; + + SecureRandom random; + + public void init( + boolean forSigning, + CipherParameters param) + { + if (forSigning) + { + if (param instanceof ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)param; + + this.random = rParam.getRandom(); + this.key = (ECPrivateKeyParameters)rParam.getParameters(); + } + else + { + this.random = new SecureRandom(); + this.key = (ECPrivateKeyParameters)param; + } + } + else + { + this.key = (ECPublicKeyParameters)param; + } + } + + // 5.3 pg 28 + /** + * generate a signature for the given message using the key we were + * initialised with. For conventional DSA the message should be a SHA-1 + * hash of the message of interest. + * + * @param message the message that will be verified later. + */ + public BigInteger[] generateSignature( + byte[] message) + { + BigInteger n = key.getParameters().getN(); + BigInteger e = calculateE(n, message); + BigInteger r = null; + BigInteger s = null; + + // 5.3.2 + do // generate s + { + BigInteger k = null; + int nBitLength = n.bitLength(); + + do // generate r + { + do + { + k = new BigInteger(nBitLength, random); + } + while (k.equals(ZERO)); + + ECPoint p = key.getParameters().getG().multiply(k); + + // 5.3.3 + BigInteger x = p.getX().toBigInteger(); + + r = x.mod(n); + } + while (r.equals(ZERO)); + + BigInteger d = ((ECPrivateKeyParameters)key).getD(); + + s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n); + } + while (s.equals(ZERO)); + + BigInteger[] res = new BigInteger[2]; + + res[0] = r; + res[1] = s; + + return res; + } + + // 5.4 pg 29 + /** + * return true if the value r and s represent a DSA signature for + * the passed in message (for standard DSA the message should be + * a SHA-1 hash of the real message to be verified). + */ + public boolean verifySignature( + byte[] message, + BigInteger r, + BigInteger s) + { + BigInteger n = key.getParameters().getN(); + BigInteger e = calculateE(n, message); + + // r in the range [1,n-1] + if (r.compareTo(ONE) < 0 || r.compareTo(n) >= 0) + { + return false; + } + + // s in the range [1,n-1] + if (s.compareTo(ONE) < 0 || s.compareTo(n) >= 0) + { + return false; + } + + BigInteger c = s.modInverse(n); + + BigInteger u1 = e.multiply(c).mod(n); + BigInteger u2 = r.multiply(c).mod(n); + + ECPoint G = key.getParameters().getG(); + ECPoint Q = ((ECPublicKeyParameters)key).getQ(); + + ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2); + + BigInteger v = point.getX().toBigInteger().mod(n); + + return v.equals(r); + } + + private BigInteger calculateE(BigInteger n, byte[] message) + { + if (n.bitLength() > message.length * 8) + { + return new BigInteger(1, message); + } + else + { + int messageBitLength = message.length * 8; + BigInteger trunc = new BigInteger(1, message); + + if (messageBitLength - n.bitLength() > 0) + { + trunc = trunc.shiftRight(messageBitLength - n.bitLength()); + } + + return trunc; + } + } +} diff --git a/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java b/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java index 8f78e08c..94c82080 100644 --- a/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java +++ b/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java @@ -7,8 +7,8 @@ import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.nist.NISTNamedCurves; // BEGIN android-removed -// import org.bouncycastle.asn1.nist.NISTNamedCurves; // import org.bouncycastle.asn1.oiw.ElGamalParameter; // END android-removed import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; @@ -16,27 +16,25 @@ import org.bouncycastle.asn1.pkcs.DHParameter; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure; +import org.bouncycastle.asn1.sec.ECPrivateKeyStructure; +import org.bouncycastle.asn1.sec.SECNamedCurves; // BEGIN android-removed -// import org.bouncycastle.asn1.sec.ECPrivateKeyStructure; -// import org.bouncycastle.asn1.sec.SECNamedCurves; // import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; // END android-removed import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.DSAParameter; -// BEGIN android-removed -// import org.bouncycastle.asn1.x9.X962NamedCurves; -// import org.bouncycastle.asn1.x9.X962Parameters; -// import org.bouncycastle.asn1.x9.X9ECParameters; -// import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; -// END android-removed +import org.bouncycastle.asn1.x9.X962NamedCurves; +import org.bouncycastle.asn1.x9.X962Parameters; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.crypto.params.DHPrivateKeyParameters; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.crypto.params.DSAPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; // BEGIN android-removed -// import org.bouncycastle.crypto.params.ECDomainParameters; -// import org.bouncycastle.crypto.params.ECPrivateKeyParameters; // import org.bouncycastle.crypto.params.ElGamalParameters; // import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters; // END android-removed @@ -129,69 +127,71 @@ public class PrivateKeyFactory // // return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(params.getP(), params.getG())); // } - // else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa)) - // { - // DERInteger derX = (DERInteger)keyInfo.getPrivateKey(); - // DEREncodable de = keyInfo.getAlgorithmId().getParameters(); - // - // DSAParameters parameters = null; - // if (de != null) - // { - // DSAParameter params = DSAParameter.getInstance(de.getDERObject()); - // parameters = new DSAParameters(params.getP(), params.getQ(), params.getG()); - // } - // - // return new DSAPrivateKeyParameters(derX.getValue(), parameters); - // } - // else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) - // { - // X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); - // ECDomainParameters dParams = null; - // - // if (params.isNamedCurve()) - // { - // DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); - // X9ECParameters ecP = X962NamedCurves.getByOID(oid); - // - // if (ecP == null) - // { - // ecP = SECNamedCurves.getByOID(oid); - // - // if (ecP == null) - // { - // ecP = NISTNamedCurves.getByOID(oid); - // - // if (ecP == null) - // { - // ecP = TeleTrusTNamedCurves.getByOID(oid); - // } - // } - // } - // - // dParams = new ECDomainParameters( - // ecP.getCurve(), - // ecP.getG(), - // ecP.getN(), - // ecP.getH(), - // ecP.getSeed()); - // } - // else - // { - // X9ECParameters ecP = new X9ECParameters( - // (ASN1Sequence)params.getParameters()); - // dParams = new ECDomainParameters( - // ecP.getCurve(), - // ecP.getG(), - // ecP.getN(), - // ecP.getH(), - // ecP.getSeed()); - // } - // - // ECPrivateKeyStructure ec = new ECPrivateKeyStructure((ASN1Sequence)keyInfo.getPrivateKey()); - // - // return new ECPrivateKeyParameters(ec.getKey(), dParams); - // } // END android-removed + else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa)) + { + DERInteger derX = (DERInteger)keyInfo.getPrivateKey(); + DEREncodable de = keyInfo.getAlgorithmId().getParameters(); + + DSAParameters parameters = null; + if (de != null) + { + DSAParameter params = DSAParameter.getInstance(de.getDERObject()); + parameters = new DSAParameters(params.getP(), params.getQ(), params.getG()); + } + + return new DSAPrivateKeyParameters(derX.getValue(), parameters); + } + else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) + { + X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); + ECDomainParameters dParams = null; + + if (params.isNamedCurve()) + { + DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); + X9ECParameters ecP = X962NamedCurves.getByOID(oid); + + if (ecP == null) + { + ecP = SECNamedCurves.getByOID(oid); + + if (ecP == null) + { + ecP = NISTNamedCurves.getByOID(oid); + + // BEGIN android-removed + // if (ecP == null) + // { + // ecP = TeleTrusTNamedCurves.getByOID(oid); + // } + // END android-removed + } + } + + dParams = new ECDomainParameters( + ecP.getCurve(), + ecP.getG(), + ecP.getN(), + ecP.getH(), + ecP.getSeed()); + } + else + { + X9ECParameters ecP = new X9ECParameters( + (ASN1Sequence)params.getParameters()); + dParams = new ECDomainParameters( + ecP.getCurve(), + ecP.getG(), + ecP.getN(), + ecP.getH(), + ecP.getSeed()); + } + + ECPrivateKeyStructure ec = new ECPrivateKeyStructure((ASN1Sequence)keyInfo.getPrivateKey()); + + return new ECPrivateKeyParameters(ec.getKey(), dParams); + } else { throw new RuntimeException("algorithm identifier in key not recognised"); diff --git a/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java b/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java index c0672b5c..f28c964a 100644 --- a/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java +++ b/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java @@ -10,15 +10,15 @@ import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERObjectIdentifier; import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.nist.NISTNamedCurves; // BEGIN android-removed -// import org.bouncycastle.asn1.nist.NISTNamedCurves; // import org.bouncycastle.asn1.oiw.ElGamalParameter; // END android-removed import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.DHParameter; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.sec.SECNamedCurves; // BEGIN android-removed -// import org.bouncycastle.asn1.sec.SECNamedCurves; // import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; // END android-removed import org.bouncycastle.asn1.x509.AlgorithmIdentifier; @@ -26,21 +26,19 @@ import org.bouncycastle.asn1.x509.DSAParameter; import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; -// BEGIN android-removed -// import org.bouncycastle.asn1.x9.X962NamedCurves; -// import org.bouncycastle.asn1.x9.X962Parameters; -// import org.bouncycastle.asn1.x9.X9ECParameters; -// import org.bouncycastle.asn1.x9.X9ECPoint; -// END android-removed +import org.bouncycastle.asn1.x9.X962NamedCurves; +import org.bouncycastle.asn1.x9.X962Parameters; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.asn1.x9.X9ECPoint; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.crypto.params.DHPublicKeyParameters; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.crypto.params.DSAPublicKeyParameters; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; // BEGIN android-removed -// import org.bouncycastle.crypto.params.ECDomainParameters; -// import org.bouncycastle.crypto.params.ECPublicKeyParameters; // import org.bouncycastle.crypto.params.ElGamalParameters; // import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters; // END android-removed @@ -144,60 +142,60 @@ public class PublicKeyFactory return new DSAPublicKeyParameters(derY.getValue(), parameters); } - // BEGIN android-removed - // else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) - // { - // X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); - // ECDomainParameters dParams = null; - // - // if (params.isNamedCurve()) - // { - // DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); - // X9ECParameters ecP = X962NamedCurves.getByOID(oid); - // - // if (ecP == null) - // { - // ecP = SECNamedCurves.getByOID(oid); - // - // if (ecP == null) - // { - // ecP = NISTNamedCurves.getByOID(oid); - // - // if (ecP == null) - // { - // ecP = TeleTrusTNamedCurves.getByOID(oid); - // } - // } - // } - // - // dParams = new ECDomainParameters( - // ecP.getCurve(), - // ecP.getG(), - // ecP.getN(), - // ecP.getH(), - // ecP.getSeed()); - // } - // else - // { - // X9ECParameters ecP = new X9ECParameters( - // (ASN1Sequence)params.getParameters()); - // dParams = new ECDomainParameters( - // ecP.getCurve(), - // ecP.getG(), - // ecP.getN(), - // ecP.getH(), - // ecP.getSeed()); - // } - // - // DERBitString bits = keyInfo.getPublicKeyData(); - // byte[] data = bits.getBytes(); - // ASN1OctetString key = new DEROctetString(data); - // - // X9ECPoint derQ = new X9ECPoint(dParams.getCurve(), key); - // - // return new ECPublicKeyParameters(derQ.getPoint(), dParams); - // } - // END android-removed + else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey)) + { + X962Parameters params = new X962Parameters((DERObject)keyInfo.getAlgorithmId().getParameters()); + ECDomainParameters dParams = null; + + if (params.isNamedCurve()) + { + DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); + X9ECParameters ecP = X962NamedCurves.getByOID(oid); + + if (ecP == null) + { + ecP = SECNamedCurves.getByOID(oid); + + if (ecP == null) + { + ecP = NISTNamedCurves.getByOID(oid); + + // BEGIN android-removed + // if (ecP == null) + // { + // ecP = TeleTrusTNamedCurves.getByOID(oid); + // } + // END android-removed + } + } + + dParams = new ECDomainParameters( + ecP.getCurve(), + ecP.getG(), + ecP.getN(), + ecP.getH(), + ecP.getSeed()); + } + else + { + X9ECParameters ecP = new X9ECParameters( + (ASN1Sequence)params.getParameters()); + dParams = new ECDomainParameters( + ecP.getCurve(), + ecP.getG(), + ecP.getN(), + ecP.getH(), + ecP.getSeed()); + } + + DERBitString bits = keyInfo.getPublicKeyData(); + byte[] data = bits.getBytes(); + ASN1OctetString key = new DEROctetString(data); + + X9ECPoint derQ = new X9ECPoint(dParams.getCurve(), key); + + return new ECPublicKeyParameters(derQ.getPoint(), dParams); + } else { throw new RuntimeException("algorithm identifier in key not recognised"); diff --git a/src/main/java/org/bouncycastle/jce/interfaces/ECKey.java b/src/main/java/org/bouncycastle/jce/interfaces/ECKey.java new file mode 100644 index 00000000..0812c128 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/interfaces/ECKey.java @@ -0,0 +1,15 @@ +package org.bouncycastle.jce.interfaces; + +import org.bouncycastle.jce.spec.ECParameterSpec; + +/** + * generic interface for an Elliptic Curve Key. + */ +public interface ECKey +{ + /** + * return a parameter specification representing the EC domain parameters + * for the key. + */ + public ECParameterSpec getParameters(); +} diff --git a/src/main/java/org/bouncycastle/jce/interfaces/ECPointEncoder.java b/src/main/java/org/bouncycastle/jce/interfaces/ECPointEncoder.java new file mode 100644 index 00000000..001dab3e --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/interfaces/ECPointEncoder.java @@ -0,0 +1,20 @@ +package org.bouncycastle.jce.interfaces; + +/** + * All BC elliptic curve keys implement this interface. You need to + * cast the key to get access to it. + * <p> + * By default BC keys produce encodings without point compression, + * to turn this on call setPointFormat() with "COMPRESSED". + */ +public interface ECPointEncoder +{ + /** + * Set the formatting for encoding of points. If the String "UNCOMPRESSED" is passed + * in point compression will not be used. If the String "COMPRESSED" is passed point + * compression will be used. The default is "UNCOMPRESSED". + * + * @param style the style to use. + */ + public void setPointFormat(String style); +} diff --git a/src/main/java/org/bouncycastle/jce/interfaces/ECPrivateKey.java b/src/main/java/org/bouncycastle/jce/interfaces/ECPrivateKey.java new file mode 100644 index 00000000..39d80c3c --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/interfaces/ECPrivateKey.java @@ -0,0 +1,16 @@ +package org.bouncycastle.jce.interfaces; + +import java.math.BigInteger; +import java.security.PrivateKey; + +/** + * interface for Elliptic Curve Private keys. + */ +public interface ECPrivateKey + extends ECKey, PrivateKey +{ + /** + * return the private value D. + */ + public BigInteger getD(); +} diff --git a/src/main/java/org/bouncycastle/jce/interfaces/ECPublicKey.java b/src/main/java/org/bouncycastle/jce/interfaces/ECPublicKey.java new file mode 100644 index 00000000..db2ecdce --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/interfaces/ECPublicKey.java @@ -0,0 +1,17 @@ +package org.bouncycastle.jce.interfaces; + +import java.security.PublicKey; + +import org.bouncycastle.math.ec.ECPoint; + +/** + * interface for elliptic curve public keys. + */ +public interface ECPublicKey + extends ECKey, PublicKey +{ + /** + * return the public point Q + */ + public ECPoint getQ(); +} diff --git a/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java b/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java index db7f6e4e..b0143121 100644 --- a/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java +++ b/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java @@ -70,9 +70,7 @@ public final class BouncyCastleProvider extends Provider private static final String ASYMMETRIC_CIPHER_PACKAGE = "org.bouncycastle.jce.provider.asymmetric."; private static final String[] ASYMMETRIC_CIPHERS = { - // BEGIN android-removed - // "EC" - // END android-removed + "EC" }; /** diff --git a/src/main/java/org/bouncycastle/jce/provider/DSABase.java b/src/main/java/org/bouncycastle/jce/provider/DSABase.java new file mode 100644 index 00000000..b30c11e4 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/DSABase.java @@ -0,0 +1,121 @@ +package org.bouncycastle.jce.provider; + +import java.math.BigInteger; +import java.security.SignatureException; +import java.security.SignatureSpi; +import java.security.PrivateKey; +import java.security.InvalidKeyException; +import java.security.spec.AlgorithmParameterSpec; + +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; +import org.bouncycastle.crypto.DSA; +import org.bouncycastle.crypto.Digest; + +public abstract class DSABase + extends SignatureSpi + implements PKCSObjectIdentifiers, X509ObjectIdentifiers +{ + protected Digest digest; + protected DSA signer; + protected DSAEncoder encoder; + + protected DSABase( + Digest digest, + DSA signer, + DSAEncoder encoder) + { + this.digest = digest; + this.signer = signer; + this.encoder = encoder; + } + + protected void engineInitSign( + PrivateKey privateKey) + throws InvalidKeyException + { + engineInitSign(privateKey, null); + } + + protected void engineUpdate( + byte b) + throws SignatureException + { + digest.update(b); + } + + protected void engineUpdate( + byte[] b, + int off, + int len) + throws SignatureException + { + digest.update(b, off, len); + } + + protected byte[] engineSign() + throws SignatureException + { + byte[] hash = new byte[digest.getDigestSize()]; + + digest.doFinal(hash, 0); + + try + { + BigInteger[] sig = signer.generateSignature(hash); + + return encoder.encode(sig[0], sig[1]); + } + catch (Exception e) + { + throw new SignatureException(e.toString()); + } + } + + protected boolean engineVerify( + byte[] sigBytes) + throws SignatureException + { + byte[] hash = new byte[digest.getDigestSize()]; + + digest.doFinal(hash, 0); + + BigInteger[] sig; + + try + { + sig = encoder.decode(sigBytes); + } + catch (Exception e) + { + throw new SignatureException("error decoding signature bytes."); + } + + return signer.verifySignature(hash, sig[0], sig[1]); + } + + protected void engineSetParameter( + AlgorithmParameterSpec params) + { + throw new UnsupportedOperationException("engineSetParameter unsupported"); + } + + /** + * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)"> + */ + protected void engineSetParameter( + String param, + Object value) + { + throw new UnsupportedOperationException("engineSetParameter unsupported"); + } + + /** + * @deprecated + */ + protected Object engineGetParameter( + String param) + { + throw new UnsupportedOperationException("engineSetParameter unsupported"); + } +} diff --git a/src/main/java/org/bouncycastle/jce/provider/DSAEncoder.java b/src/main/java/org/bouncycastle/jce/provider/DSAEncoder.java new file mode 100644 index 00000000..e0dc92ba --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/DSAEncoder.java @@ -0,0 +1,13 @@ +package org.bouncycastle.jce.provider; + +import java.math.BigInteger; +import java.io.IOException; + +public interface DSAEncoder +{ + byte[] encode(BigInteger r, BigInteger s) + throws IOException; + + BigInteger[] decode(byte[] sig) + throws IOException; +} diff --git a/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java b/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java new file mode 100644 index 00000000..4a121244 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java @@ -0,0 +1,469 @@ +package org.bouncycastle.jce.provider; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.security.interfaces.ECPrivateKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.EllipticCurve; +import java.util.Enumeration; + +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +// BEGIN android-removed +// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; +// END android-removed +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.sec.ECPrivateKeyStructure; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.asn1.x9.X962Parameters; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.jce.interfaces.ECPointEncoder; +import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; +import org.bouncycastle.jce.provider.asymmetric.ec.EC5Util; +import org.bouncycastle.jce.provider.asymmetric.ec.ECUtil; +import org.bouncycastle.jce.spec.ECNamedCurveSpec; +import org.bouncycastle.math.ec.ECCurve; + +public class JCEECPrivateKey + implements ECPrivateKey, org.bouncycastle.jce.interfaces.ECPrivateKey, PKCS12BagAttributeCarrier, ECPointEncoder +{ + private String algorithm = "EC"; + private BigInteger d; + private ECParameterSpec ecSpec; + private boolean withCompression; + + private DERBitString publicKey; + + private PKCS12BagAttributeCarrierImpl attrCarrier = new PKCS12BagAttributeCarrierImpl(); + + protected JCEECPrivateKey() + { + } + + public JCEECPrivateKey( + ECPrivateKey key) + { + this.d = key.getS(); + this.algorithm = key.getAlgorithm(); + this.ecSpec = key.getParams(); + } + + public JCEECPrivateKey( + String algorithm, + org.bouncycastle.jce.spec.ECPrivateKeySpec spec) + { + this.algorithm = algorithm; + this.d = spec.getD(); + + if (spec.getParams() != null) // can be null if implicitlyCA + { + ECCurve curve = spec.getParams().getCurve(); + EllipticCurve ellipticCurve; + + ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed()); + + this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams()); + } + else + { + this.ecSpec = null; + } + } + + + public JCEECPrivateKey( + String algorithm, + ECPrivateKeySpec spec) + { + this.algorithm = algorithm; + this.d = spec.getS(); + this.ecSpec = spec.getParams(); + } + + public JCEECPrivateKey( + String algorithm, + JCEECPrivateKey key) + { + this.algorithm = algorithm; + this.d = key.d; + this.ecSpec = key.ecSpec; + this.withCompression = key.withCompression; + this.attrCarrier = key.attrCarrier; + this.publicKey = key.publicKey; + } + + public JCEECPrivateKey( + String algorithm, + ECPrivateKeyParameters params, + JCEECPublicKey pubKey, + ECParameterSpec spec) + { + ECDomainParameters dp = params.getParameters(); + + this.algorithm = algorithm; + this.d = params.getD(); + + if (spec == null) + { + EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed()); + + this.ecSpec = new ECParameterSpec( + ellipticCurve, + new ECPoint( + dp.getG().getX().toBigInteger(), + dp.getG().getY().toBigInteger()), + dp.getN(), + dp.getH().intValue()); + } + else + { + this.ecSpec = spec; + } + + publicKey = getPublicKeyDetails(pubKey); + } + + public JCEECPrivateKey( + String algorithm, + ECPrivateKeyParameters params, + JCEECPublicKey pubKey, + org.bouncycastle.jce.spec.ECParameterSpec spec) + { + ECDomainParameters dp = params.getParameters(); + + this.algorithm = algorithm; + this.d = params.getD(); + + if (spec == null) + { + EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed()); + + this.ecSpec = new ECParameterSpec( + ellipticCurve, + new ECPoint( + dp.getG().getX().toBigInteger(), + dp.getG().getY().toBigInteger()), + dp.getN(), + dp.getH().intValue()); + } + else + { + EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed()); + + this.ecSpec = new ECParameterSpec( + ellipticCurve, + new ECPoint( + spec.getG().getX().toBigInteger(), + spec.getG().getY().toBigInteger()), + spec.getN(), + spec.getH().intValue()); + } + + publicKey = getPublicKeyDetails(pubKey); + } + + public JCEECPrivateKey( + String algorithm, + ECPrivateKeyParameters params) + { + this.algorithm = algorithm; + this.d = params.getD(); + this.ecSpec = null; + } + + JCEECPrivateKey( + PrivateKeyInfo info) + { + populateFromPrivKeyInfo(info); + } + + private void populateFromPrivKeyInfo(PrivateKeyInfo info) + { + X962Parameters params = new X962Parameters((DERObject)info.getAlgorithmId().getParameters()); + + if (params.isNamedCurve()) + { + DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters(); + X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); + + // BEGIN android-removed + // if (ecP == null) // GOST Curve + // { + // ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid); + // EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed()); + // + // ecSpec = new ECNamedCurveSpec( + // ECGOST3410NamedCurves.getName(oid), + // ellipticCurve, + // new ECPoint( + // gParam.getG().getX().toBigInteger(), + // gParam.getG().getY().toBigInteger()), + // gParam.getN(), + // gParam.getH()); + // } + // else + // END android-removed + { + EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed()); + + ecSpec = new ECNamedCurveSpec( + ECUtil.getCurveName(oid), + ellipticCurve, + new ECPoint( + ecP.getG().getX().toBigInteger(), + ecP.getG().getY().toBigInteger()), + ecP.getN(), + ecP.getH()); + } + } + else if (params.isImplicitlyCA()) + { + ecSpec = null; + } + else + { + X9ECParameters ecP = new X9ECParameters((ASN1Sequence)params.getParameters()); + EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed()); + + this.ecSpec = new ECParameterSpec( + ellipticCurve, + new ECPoint( + ecP.getG().getX().toBigInteger(), + ecP.getG().getY().toBigInteger()), + ecP.getN(), + ecP.getH().intValue()); + } + + if (info.getPrivateKey() instanceof DERInteger) + { + DERInteger derD = (DERInteger)info.getPrivateKey(); + + this.d = derD.getValue(); + } + else + { + ECPrivateKeyStructure ec = new ECPrivateKeyStructure((ASN1Sequence)info.getPrivateKey()); + + this.d = ec.getKey(); + this.publicKey = ec.getPublicKey(); + } + } + + public String getAlgorithm() + { + return algorithm; + } + + /** + * return the encoding format we produce in getEncoded(). + * + * @return the string "PKCS#8" + */ + public String getFormat() + { + return "PKCS#8"; + } + + /** + * Return a PKCS8 representation of the key. The sequence returned + * represents a full PrivateKeyInfo object. + * + * @return a PKCS8 representation of the key. + */ + public byte[] getEncoded() + { + X962Parameters params; + + if (ecSpec instanceof ECNamedCurveSpec) + { + DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); + + params = new X962Parameters(curveOid); + } + else if (ecSpec == null) + { + params = new X962Parameters(DERNull.INSTANCE); + } + else + { + ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); + + X9ECParameters ecP = new X9ECParameters( + curve, + EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), + ecSpec.getOrder(), + BigInteger.valueOf(ecSpec.getCofactor()), + ecSpec.getCurve().getSeed()); + + params = new X962Parameters(ecP); + } + + PrivateKeyInfo info; + ECPrivateKeyStructure keyStructure; + + if (publicKey != null) + { + keyStructure = new ECPrivateKeyStructure(this.getS(), publicKey, params); + } + else + { + keyStructure = new ECPrivateKeyStructure(this.getS(), params); + } + + // BEGIN android-removed + // if (algorithm.equals("ECGOST3410")) + // { + // info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.getDERObject()), keyStructure.getDERObject()); + // } + // else + // END android-removed + { + + info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.getDERObject()), keyStructure.getDERObject()); + } + + return info.getDEREncoded(); + } + + public ECParameterSpec getParams() + { + return ecSpec; + } + + public org.bouncycastle.jce.spec.ECParameterSpec getParameters() + { + if (ecSpec == null) + { + return null; + } + + return EC5Util.convertSpec(ecSpec, withCompression); + } + + org.bouncycastle.jce.spec.ECParameterSpec engineGetSpec() + { + if (ecSpec != null) + { + return EC5Util.convertSpec(ecSpec, withCompression); + } + + return ProviderUtil.getEcImplicitlyCa(); + } + + public BigInteger getS() + { + return d; + } + + public BigInteger getD() + { + return d; + } + + public void setBagAttribute( + DERObjectIdentifier oid, + DEREncodable attribute) + { + attrCarrier.setBagAttribute(oid, attribute); + } + + public DEREncodable getBagAttribute( + DERObjectIdentifier oid) + { + return attrCarrier.getBagAttribute(oid); + } + + public Enumeration getBagAttributeKeys() + { + return attrCarrier.getBagAttributeKeys(); + } + + public void setPointFormat(String style) + { + withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style)); + } + + public boolean equals(Object o) + { + if (!(o instanceof JCEECPrivateKey)) + { + return false; + } + + JCEECPrivateKey other = (JCEECPrivateKey)o; + + return getD().equals(other.getD()) && (engineGetSpec().equals(other.engineGetSpec())); + } + + public int hashCode() + { + return getD().hashCode() ^ engineGetSpec().hashCode(); + } + + public String toString() + { + StringBuffer buf = new StringBuffer(); + String nl = System.getProperty("line.separator"); + + buf.append("EC Private Key").append(nl); + buf.append(" S: ").append(this.d.toString(16)).append(nl); + + return buf.toString(); + + } + + private DERBitString getPublicKeyDetails(JCEECPublicKey pub) + { + try + { + SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(ASN1Object.fromByteArray(pub.getEncoded())); + + return info.getPublicKeyData(); + } + catch (IOException e) + { // should never happen + return null; + } + } + + private void readObject( + ObjectInputStream in) + throws IOException, ClassNotFoundException + { + byte[] enc = (byte[])in.readObject(); + + populateFromPrivKeyInfo(PrivateKeyInfo.getInstance(ASN1Object.fromByteArray(enc))); + + this.algorithm = (String)in.readObject(); + this.withCompression = in.readBoolean(); + this.attrCarrier = new PKCS12BagAttributeCarrierImpl(); + + attrCarrier.readObject(in); + } + + private void writeObject( + ObjectOutputStream out) + throws IOException + { + out.writeObject(this.getEncoded()); + out.writeObject(algorithm); + out.writeBoolean(withCompression); + + attrCarrier.writeObject(out); + } +} diff --git a/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java b/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java new file mode 100644 index 00000000..92b478a9 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java @@ -0,0 +1,528 @@ +package org.bouncycastle.jce.provider; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.EllipticCurve; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +// BEGIN android-removed +// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; +// import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters; +// END android-removed +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.asn1.x9.X962Parameters; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.asn1.x9.X9ECPoint; +import org.bouncycastle.asn1.x9.X9IntegerConverter; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +// BEGIN android-removed +// import org.bouncycastle.jce.ECGOST3410NamedCurveTable; +// END android-removed +import org.bouncycastle.jce.interfaces.ECPointEncoder; +import org.bouncycastle.jce.provider.asymmetric.ec.EC5Util; +import org.bouncycastle.jce.provider.asymmetric.ec.ECUtil; +// BEGIN android-removed +// import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; +// END android-removed +import org.bouncycastle.jce.spec.ECNamedCurveSpec; +import org.bouncycastle.math.ec.ECCurve; + +public class JCEECPublicKey + implements ECPublicKey, org.bouncycastle.jce.interfaces.ECPublicKey, ECPointEncoder +{ + private String algorithm = "EC"; + private org.bouncycastle.math.ec.ECPoint q; + private ECParameterSpec ecSpec; + private boolean withCompression; + // BEGIN android-removed + // private GOST3410PublicKeyAlgParameters gostParams; + // END android-removed + + public JCEECPublicKey( + String algorithm, + JCEECPublicKey key) + { + this.algorithm = algorithm; + this.q = key.q; + this.ecSpec = key.ecSpec; + this.withCompression = key.withCompression; + // BEGIN android-removed + // this.gostParams = key.gostParams; + // END android-removed + } + + public JCEECPublicKey( + String algorithm, + ECPublicKeySpec spec) + { + this.algorithm = algorithm; + this.ecSpec = spec.getParams(); + this.q = EC5Util.convertPoint(ecSpec, spec.getW(), false); + } + + public JCEECPublicKey( + String algorithm, + org.bouncycastle.jce.spec.ECPublicKeySpec spec) + { + this.algorithm = algorithm; + this.q = spec.getQ(); + + if (spec.getParams() != null) // can be null if implictlyCa + { + ECCurve curve = spec.getParams().getCurve(); + EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed()); + + this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams()); + } + else + { + if (q.getCurve() == null) + { + org.bouncycastle.jce.spec.ECParameterSpec s = ProviderUtil.getEcImplicitlyCa(); + + q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger(), false); + } + this.ecSpec = null; + } + } + + public JCEECPublicKey( + String algorithm, + ECPublicKeyParameters params, + ECParameterSpec spec) + { + ECDomainParameters dp = params.getParameters(); + + this.algorithm = algorithm; + this.q = params.getQ(); + + if (spec == null) + { + EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed()); + + this.ecSpec = createSpec(ellipticCurve, dp); + } + else + { + this.ecSpec = spec; + } + } + + public JCEECPublicKey( + String algorithm, + ECPublicKeyParameters params, + org.bouncycastle.jce.spec.ECParameterSpec spec) + { + ECDomainParameters dp = params.getParameters(); + + this.algorithm = algorithm; + this.q = params.getQ(); + + if (spec == null) + { + EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed()); + + this.ecSpec = createSpec(ellipticCurve, dp); + } + else + { + EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed()); + + this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec); + } + } + + /* + * called for implicitCA + */ + public JCEECPublicKey( + String algorithm, + ECPublicKeyParameters params) + { + this.algorithm = algorithm; + this.q = params.getQ(); + this.ecSpec = null; + } + + private ECParameterSpec createSpec(EllipticCurve ellipticCurve, ECDomainParameters dp) + { + return new ECParameterSpec( + ellipticCurve, + new ECPoint( + dp.getG().getX().toBigInteger(), + dp.getG().getY().toBigInteger()), + dp.getN(), + dp.getH().intValue()); + } + + public JCEECPublicKey( + ECPublicKey key) + { + this.algorithm = key.getAlgorithm(); + this.ecSpec = key.getParams(); + this.q = EC5Util.convertPoint(this.ecSpec, key.getW(), false); + } + + JCEECPublicKey( + SubjectPublicKeyInfo info) + { + populateFromPubKeyInfo(info); + } + + private void populateFromPubKeyInfo(SubjectPublicKeyInfo info) + { + // BEGIN android-removed + // if (info.getAlgorithmId().getObjectId().equals(CryptoProObjectIdentifiers.gostR3410_2001)) + // { + // DERBitString bits = info.getPublicKeyData(); + // ASN1OctetString key; + // this.algorithm = "ECGOST3410"; + // + // try + // { + // key = (ASN1OctetString) ASN1Object.fromByteArray(bits.getBytes()); + // } + // catch (IOException ex) + // { + // throw new IllegalArgumentException("error recovering public key"); + // } + // + // byte[] keyEnc = key.getOctets(); + // byte[] x = new byte[32]; + // byte[] y = new byte[32]; + // + // for (int i = 0; i != x.length; i++) + // { + // x[i] = keyEnc[32 - 1 - i]; + // } + // + // for (int i = 0; i != y.length; i++) + // { + // y[i] = keyEnc[64 - 1 - i]; + // } + // + // gostParams = new GOST3410PublicKeyAlgParameters((ASN1Sequence)info.getAlgorithmId().getParameters()); + // + // ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet())); + // + // ECCurve curve = spec.getCurve(); + // EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed()); + // + // this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y), false); + // + // ecSpec = new ECNamedCurveSpec( + // ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()), + // ellipticCurve, + // new ECPoint( + // spec.getG().getX().toBigInteger(), + // spec.getG().getY().toBigInteger()), + // spec.getN(), spec.getH()); + // + // } + // else + // END android-removed + { + X962Parameters params = new X962Parameters((DERObject)info.getAlgorithmId().getParameters()); + ECCurve curve; + EllipticCurve ellipticCurve; + + if (params.isNamedCurve()) + { + DERObjectIdentifier oid = (DERObjectIdentifier)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().getX().toBigInteger(), + ecP.getG().getY().toBigInteger()), + ecP.getN(), + ecP.getH()); + } + else if (params.isImplicitlyCA()) + { + ecSpec = null; + curve = ProviderUtil.getEcImplicitlyCa().getCurve(); + } + else + { + X9ECParameters ecP = new X9ECParameters((ASN1Sequence)params.getParameters()); + + curve = ecP.getCurve(); + ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); + + this.ecSpec = new ECParameterSpec( + ellipticCurve, + new ECPoint( + ecP.getG().getX().toBigInteger(), + ecP.getG().getY().toBigInteger()), + ecP.getN(), + ecP.getH().intValue()); + } + + DERBitString bits = info.getPublicKeyData(); + byte[] data = bits.getBytes(); + ASN1OctetString key = new DEROctetString(data); + + // + // extra octet string - one of our old certs... + // + if (data[0] == 0x04 && data[1] == data.length - 2 + && (data[2] == 0x02 || data[2] == 0x03)) + { + int qLength = new X9IntegerConverter().getByteLength(curve); + + if (qLength >= data.length - 3) + { + try + { + key = (ASN1OctetString) ASN1Object.fromByteArray(data); + } + catch (IOException ex) + { + throw new IllegalArgumentException("error recovering public key"); + } + } + } + X9ECPoint derQ = new X9ECPoint(curve, key); + + this.q = derQ.getPoint(); + } + } + + public String getAlgorithm() + { + return algorithm; + } + + public String getFormat() + { + return "X.509"; + } + + public byte[] getEncoded() + { + ASN1Encodable params; + SubjectPublicKeyInfo info; + + // BEGIN android-removed + // if (algorithm.equals("ECGOST3410")) + // { + // if (gostParams != null) + // { + // params = gostParams; + // } + // else + // { + // if (ecSpec instanceof ECNamedCurveSpec) + // { + // params = new GOST3410PublicKeyAlgParameters( + // ECGOST3410NamedCurves.getOID(((ECNamedCurveSpec)ecSpec).getName()), + // CryptoProObjectIdentifiers.gostR3411_94_CryptoProParamSet); + // } + // else + // { // strictly speaking this may not be applicable... + // ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); + // + // X9ECParameters ecP = new X9ECParameters( + // curve, + // EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), + // ecSpec.getOrder(), + // BigInteger.valueOf(ecSpec.getCofactor()), + // ecSpec.getCurve().getSeed()); + // + // params = new X962Parameters(ecP); + // } + // } + // + // BigInteger bX = this.q.getX().toBigInteger(); + // BigInteger bY = this.q.getY().toBigInteger(); + // byte[] encKey = new byte[64]; + // + // extractBytes(encKey, 0, bX); + // extractBytes(encKey, 32, bY); + // + // info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.getDERObject()), new DEROctetString(encKey)); + // } + // else + // END android-removed + { + if (ecSpec instanceof ECNamedCurveSpec) + { + DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); + + params = new X962Parameters(curveOid); + } + else if (ecSpec == null) + { + params = new X962Parameters(DERNull.INSTANCE); + } + else + { + ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); + + X9ECParameters ecP = new X9ECParameters( + curve, + EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), + ecSpec.getOrder(), + BigInteger.valueOf(ecSpec.getCofactor()), + ecSpec.getCurve().getSeed()); + + params = new X962Parameters(ecP); + } + + ECCurve curve = this.engineGetQ().getCurve(); + ASN1OctetString p = (ASN1OctetString) + new X9ECPoint(curve.createPoint(this.getQ().getX().toBigInteger(), this.getQ().getY().toBigInteger(), withCompression)).getDERObject(); + + info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.getDERObject()), p.getOctets()); + } + + return info.getDEREncoded(); + } + + private void extractBytes(byte[] encKey, int offSet, BigInteger bI) + { + byte[] val = bI.toByteArray(); + if (val.length < 32) + { + byte[] tmp = new byte[32]; + System.arraycopy(val, 0, tmp, tmp.length - val.length, val.length); + } + + for (int i = 0; i != 32; i++) + { + encKey[offSet + i] = val[val.length - 1 - i]; + } + } + + public ECParameterSpec getParams() + { + return ecSpec; + } + + public org.bouncycastle.jce.spec.ECParameterSpec getParameters() + { + if (ecSpec == null) // implictlyCA + { + return null; + } + + return EC5Util.convertSpec(ecSpec, withCompression); + } + + public ECPoint getW() + { + return new ECPoint(q.getX().toBigInteger(), q.getY().toBigInteger()); + } + + public org.bouncycastle.math.ec.ECPoint getQ() + { + if (ecSpec == null) + { + if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp) + { + return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getX(), q.getY()); + } + else + { + return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getX(), q.getY()); + } + } + + return q; + } + + public org.bouncycastle.math.ec.ECPoint engineGetQ() + { + return q; + } + + org.bouncycastle.jce.spec.ECParameterSpec engineGetSpec() + { + if (ecSpec != null) + { + return EC5Util.convertSpec(ecSpec, withCompression); + } + + return ProviderUtil.getEcImplicitlyCa(); + } + + public String toString() + { + StringBuffer buf = new StringBuffer(); + String nl = System.getProperty("line.separator"); + + buf.append("EC Public Key").append(nl); + buf.append(" X: ").append(this.q.getX().toBigInteger().toString(16)).append(nl); + buf.append(" Y: ").append(this.q.getY().toBigInteger().toString(16)).append(nl); + + return buf.toString(); + + } + + public void setPointFormat(String style) + { + withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style)); + } + + public boolean equals(Object o) + { + if (!(o instanceof JCEECPublicKey)) + { + return false; + } + + JCEECPublicKey other = (JCEECPublicKey)o; + + return engineGetQ().equals(other.engineGetQ()) && (engineGetSpec().equals(other.engineGetSpec())); + } + + public int hashCode() + { + return engineGetQ().hashCode() ^ engineGetSpec().hashCode(); + } + + private void readObject( + ObjectInputStream in) + throws IOException, ClassNotFoundException + { + byte[] enc = (byte[])in.readObject(); + + populateFromPubKeyInfo(SubjectPublicKeyInfo.getInstance(ASN1Object.fromByteArray(enc))); + + this.algorithm = (String)in.readObject(); + this.withCompression = in.readBoolean(); + } + + private void writeObject( + ObjectOutputStream out) + throws IOException + { + out.writeObject(this.getEncoded()); + out.writeObject(algorithm); + out.writeBoolean(withCompression); + } +} diff --git a/src/main/java/org/bouncycastle/jce/provider/JDKKeyFactory.java b/src/main/java/org/bouncycastle/jce/provider/JDKKeyFactory.java index 8ee9a646..7ac56c2f 100644 --- a/src/main/java/org/bouncycastle/jce/provider/JDKKeyFactory.java +++ b/src/main/java/org/bouncycastle/jce/provider/JDKKeyFactory.java @@ -261,11 +261,11 @@ public abstract class JDKKeyFactory { return new JDKDSAPublicKey(info); } + else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey)) + { + return new JCEECPublicKey(info); + } // BEGIN android-removed - // else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey)) - // { - // return new JCEECPublicKey(info); - // } // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94)) // { // return new JDKGOST3410PublicKey(info); @@ -317,11 +317,11 @@ public abstract class JDKKeyFactory { return new JDKDSAPrivateKey(info); } + else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey)) + { + return new JCEECPrivateKey(info); + } // BEGIN android-removed - // else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey)) - // { - // return new JCEECPrivateKey(info); - // } // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94)) // { // return new JDKGOST3410PrivateKey(info); diff --git a/src/main/java/org/bouncycastle/jce/provider/ProviderUtil.java b/src/main/java/org/bouncycastle/jce/provider/ProviderUtil.java index b4f700dd..880437d9 100644 --- a/src/main/java/org/bouncycastle/jce/provider/ProviderUtil.java +++ b/src/main/java/org/bouncycastle/jce/provider/ProviderUtil.java @@ -1,13 +1,9 @@ package org.bouncycastle.jce.provider; import org.bouncycastle.jce.ProviderConfigurationPermission; -// BEGIN android-removed -// import org.bouncycastle.jce.provider.asymmetric.ec.EC5Util; -// END android-removed +import org.bouncycastle.jce.provider.asymmetric.ec.EC5Util; import org.bouncycastle.jce.interfaces.ConfigurableProvider; -// BEGIN android-removed -// import org.bouncycastle.jce.spec.ECParameterSpec; -// END android-removed +import org.bouncycastle.jce.spec.ECParameterSpec; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -24,74 +20,68 @@ public class ProviderUtil "BC", ConfigurableProvider.EC_IMPLICITLY_CA); private static ThreadLocal threadSpec = new ThreadLocal(); - // BEGIN android-removed - // private static volatile ECParameterSpec ecImplicitCaParams; - // END android-removed + private static volatile ECParameterSpec ecImplicitCaParams; static void setParameter(String parameterName, Object parameter) { SecurityManager securityManager = System.getSecurityManager(); - // BEGIN android-removed - // if (parameterName.equals(ConfigurableProvider.THREAD_LOCAL_EC_IMPLICITLY_CA)) - // { - // ECParameterSpec curveSpec; - // - // if (securityManager != null) - // { - // securityManager.checkPermission(BC_EC_LOCAL_PERMISSION); - // } - // - // if (parameter instanceof ECParameterSpec || parameter == null) - // { - // curveSpec = (ECParameterSpec)parameter; - // } - // else // assume java.security.spec - // { - // curveSpec = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false); - // } - // - // if (curveSpec == null) - // { - // threadSpec.remove(); - // } - // else - // { - // threadSpec.set(curveSpec); - // } - // } - // else if (parameterName.equals(ConfigurableProvider.EC_IMPLICITLY_CA)) - // { - // if (securityManager != null) - // { - // securityManager.checkPermission(BC_EC_PERMISSION); - // } - // - // if (parameter instanceof ECParameterSpec || parameter == null) - // { - // ecImplicitCaParams = (ECParameterSpec)parameter; - // } - // else // assume java.security.spec - // { - // ecImplicitCaParams = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false); - // } - // } - // END android-removed + if (parameterName.equals(ConfigurableProvider.THREAD_LOCAL_EC_IMPLICITLY_CA)) + { + ECParameterSpec curveSpec; + + if (securityManager != null) + { + securityManager.checkPermission(BC_EC_LOCAL_PERMISSION); + } + + if (parameter instanceof ECParameterSpec || parameter == null) + { + curveSpec = (ECParameterSpec)parameter; + } + else // assume java.security.spec + { + curveSpec = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false); + } + + if (curveSpec == null) + { + threadSpec.remove(); + } + else + { + threadSpec.set(curveSpec); + } + } + else if (parameterName.equals(ConfigurableProvider.EC_IMPLICITLY_CA)) + { + if (securityManager != null) + { + securityManager.checkPermission(BC_EC_PERMISSION); + } + + if (parameter instanceof ECParameterSpec || parameter == null) + { + ecImplicitCaParams = (ECParameterSpec)parameter; + } + else // assume java.security.spec + { + ecImplicitCaParams = EC5Util.convertSpec((java.security.spec.ECParameterSpec)parameter, false); + } + } } - // BEGIN android-removed - // public static ECParameterSpec getEcImplicitlyCa() - // { - // ECParameterSpec spec = (ECParameterSpec)threadSpec.get(); - // - // if (spec != null) - // { - // return spec; - // } - // - // return ecImplicitCaParams; - // } - // END android-removed + public static ECParameterSpec getEcImplicitlyCa() + { + ECParameterSpec spec = (ECParameterSpec)threadSpec.get(); + + if (spec != null) + { + return spec; + } + + return ecImplicitCaParams; + } static int getReadLimit(InputStream in) throws IOException diff --git a/src/main/java/org/bouncycastle/jce/provider/WrapCipherSpi.java b/src/main/java/org/bouncycastle/jce/provider/WrapCipherSpi.java index aa504069..7b78f82b 100644 --- a/src/main/java/org/bouncycastle/jce/provider/WrapCipherSpi.java +++ b/src/main/java/org/bouncycastle/jce/provider/WrapCipherSpi.java @@ -368,20 +368,17 @@ public abstract class WrapCipherSpi extends CipherSpi DERObjectIdentifier oid = in.getAlgorithmId().getObjectId(); + if (oid.equals(X9ObjectIdentifiers.id_ecPublicKey)) + { + privKey = new JCEECPrivateKey(in); + } // BEGIN android-removed - // if (oid.equals(X9ObjectIdentifiers.id_ecPublicKey)) - // { - // privKey = new JCEECPrivateKey(in); - // } // else if (oid.equals(CryptoProObjectIdentifiers.gostR3410_94)) // { // privKey = new JDKGOST3410PrivateKey(in); // } - // else if (oid.equals(X9ObjectIdentifiers.id_dsa)) // END android-removed - // BEGIN android-added - if (oid.equals(X9ObjectIdentifiers.id_dsa)) - // END android-added + else if (oid.equals(X9ObjectIdentifiers.id_dsa)) { privKey = new JDKDSAPrivateKey(in); } diff --git a/src/main/java/org/bouncycastle/jce/provider/asymmetric/ECMappings.java b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ECMappings.java new file mode 100644 index 00000000..4294d144 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ECMappings.java @@ -0,0 +1,114 @@ +package org.bouncycastle.jce.provider.asymmetric; + +import java.util.HashMap; + +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +// BEGIN android-removed +// import org.bouncycastle.asn1.eac.EACObjectIdentifiers; +// import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; +// END android-removed +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; + +public class ECMappings + extends HashMap +{ + public ECMappings() + { + put("KeyAgreement.ECDH", "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$DH"); + // BEGIN android-removed + // put("KeyAgreement.ECDHC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$DHC"); + // put("KeyAgreement.ECMQV", "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$MQV"); + // put("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$DHwithSHA1KDF"); + // put("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "org.bouncycastle.jce.provider.asymmetric.ec.KeyAgreement$MQVwithSHA1KDF"); + // END android-removed + + put("KeyFactory.EC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$EC"); + // BEGIN android-removed + // put("KeyFactory.ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECDSA"); + // put("KeyFactory.ECDH", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECDH"); + // put("KeyFactory.ECDHC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECDHC"); + // put("KeyFactory.ECMQV", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECMQV"); + // END android-removed + put("Alg.Alias.KeyFactory." + X9ObjectIdentifiers.id_ecPublicKey, "EC"); + // TODO Should this be an alias for ECDH? + put("Alg.Alias.KeyFactory." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC"); + // BEGIN android-removed + // put("Alg.Alias.KeyFactory." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV"); + + // put("KeyFactory.ECGOST3410", "org.bouncycastle.jce.provider.asymmetric.ec.KeyFactory$ECGOST3410"); + // put("Alg.Alias.KeyFactory.GOST-3410-2001", "ECGOST3410"); + // put("Alg.Alias.KeyFactory.ECGOST-3410", "ECGOST3410"); + // put("Alg.Alias.KeyFactory." + CryptoProObjectIdentifiers.gostR3410_2001, "ECGOST3410"); + // END android-removed + + put("KeyPairGenerator.EC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$EC"); + // BEGIN android-removed + // put("KeyPairGenerator.ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDSA"); + // put("KeyPairGenerator.ECDH", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDH"); + // put("KeyPairGenerator.ECDHC", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDHC"); + // put("KeyPairGenerator.ECIES", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECDH"); + // put("KeyPairGenerator.ECMQV", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECMQV"); + // END android-removed + // TODO Should this be an alias for ECDH? + put("Alg.Alias.KeyPairGenerator." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC"); + // BEGIN android-removed + // put("Alg.Alias.KeyPairGenerator." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV"); + + // put("KeyPairGenerator.ECGOST3410", "org.bouncycastle.jce.provider.asymmetric.ec.KeyPairGenerator$ECGOST3410"); + // put("Alg.Alias.KeyPairGenerator.ECGOST-3410", "ECGOST3410"); + // put("Alg.Alias.KeyPairGenerator.GOST-3410-2001", "ECGOST3410"); + // END android-removed + + put("Signature.ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA"); + put("Signature.NONEwithECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSAnone"); + + put("Alg.Alias.Signature.SHA1withECDSA", "ECDSA"); + put("Alg.Alias.Signature.ECDSAwithSHA1", "ECDSA"); + put("Alg.Alias.Signature.SHA1WITHECDSA", "ECDSA"); + put("Alg.Alias.Signature.ECDSAWITHSHA1", "ECDSA"); + put("Alg.Alias.Signature.SHA1WithECDSA", "ECDSA"); + put("Alg.Alias.Signature.ECDSAWithSHA1", "ECDSA"); + put("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA"); + // BEGIN android-removed + // put("Alg.Alias.Signature." + TeleTrusTObjectIdentifiers.ecSignWithSha1, "ECDSA"); + + // addSignatureAlgorithm("SHA224", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA224", X9ObjectIdentifiers.ecdsa_with_SHA224); + // END android-removed + addSignatureAlgorithm("SHA256", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA256", X9ObjectIdentifiers.ecdsa_with_SHA256); + addSignatureAlgorithm("SHA384", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA384", X9ObjectIdentifiers.ecdsa_with_SHA384); + addSignatureAlgorithm("SHA512", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSA512", X9ObjectIdentifiers.ecdsa_with_SHA512); + // BEGIN android-removed + // addSignatureAlgorithm("RIPEMD160", "ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecDSARipeMD160",TeleTrusTObjectIdentifiers.ecSignWithRipemd160); + + // put("Signature.SHA1WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR"); + // put("Signature.SHA224WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR224"); + // put("Signature.SHA256WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR256"); + // put("Signature.SHA384WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR384"); + // put("Signature.SHA512WITHECNR", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecNR512"); + + // addSignatureAlgorithm("SHA1", "CVC-ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecCVCDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1); + // addSignatureAlgorithm("SHA224", "CVC-ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecCVCDSA224", EACObjectIdentifiers.id_TA_ECDSA_SHA_224); + // addSignatureAlgorithm("SHA256", "CVC-ECDSA", "org.bouncycastle.jce.provider.asymmetric.ec.Signature$ecCVCDSA256", EACObjectIdentifiers.id_TA_ECDSA_SHA_256); + // END android-removed + } + + private void addSignatureAlgorithm( + String digest, + String algorithm, + String className, + DERObjectIdentifier oid) + { + String mainName = digest + "WITH" + algorithm; + String jdk11Variation1 = digest + "with" + algorithm; + String jdk11Variation2 = digest + "With" + algorithm; + String alias = digest + "/" + algorithm; + + put("Signature." + mainName, className); + put("Alg.Alias.Signature." + jdk11Variation1, mainName); + put("Alg.Alias.Signature." + jdk11Variation2, mainName); + put("Alg.Alias.Signature." + alias, mainName); + put("Alg.Alias.Signature." + oid, mainName); + put("Alg.Alias.Signature.OID." + oid, mainName); + } +} diff --git a/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/EC5Util.java b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/EC5Util.java new file mode 100644 index 00000000..b6936134 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/EC5Util.java @@ -0,0 +1,123 @@ +package org.bouncycastle.jce.provider.asymmetric.ec; + +import java.math.BigInteger; +import java.security.spec.ECField; +import java.security.spec.ECFieldF2m; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.EllipticCurve; + +import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; +import org.bouncycastle.jce.spec.ECNamedCurveSpec; +import org.bouncycastle.math.ec.ECCurve; + +public class EC5Util +{ + public static EllipticCurve convertCurve( + ECCurve curve, + byte[] seed) + { + // 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 (curve instanceof ECCurve.Fp) + { + return new EllipticCurve(new ECFieldFp(((ECCurve.Fp)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null); + } + else + { + 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(), null); + } + 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); + } + } + } + + public static ECCurve convertCurve( + EllipticCurve ec) + { + ECField field = ec.getField(); + BigInteger a = ec.getA(); + BigInteger b = ec.getB(); + + if (field instanceof ECFieldFp) + { + return new ECCurve.Fp(((ECFieldFp)field).getP(), a, b); + } + else + { + ECFieldF2m fieldF2m = (ECFieldF2m)field; + int m = fieldF2m.getM(); + int ks[] = ECUtil.convertMidTerms(fieldF2m.getMidTermsOfReductionPolynomial()); + return new ECCurve.F2m(m, ks[0], ks[1], ks[2], a, b); + } + } + + public static ECParameterSpec convertSpec( + EllipticCurve ellipticCurve, + org.bouncycastle.jce.spec.ECParameterSpec spec) + { + if (spec instanceof ECNamedCurveParameterSpec) + { + return new ECNamedCurveSpec( + ((ECNamedCurveParameterSpec)spec).getName(), + ellipticCurve, + new ECPoint( + spec.getG().getX().toBigInteger(), + spec.getG().getY().toBigInteger()), + spec.getN(), + spec.getH()); + } + else + { + return new ECParameterSpec( + ellipticCurve, + new ECPoint( + spec.getG().getX().toBigInteger(), + spec.getG().getY().toBigInteger()), + spec.getN(), + spec.getH().intValue()); + } + } + + public static org.bouncycastle.jce.spec.ECParameterSpec convertSpec( + ECParameterSpec ecSpec, + boolean withCompression) + { + ECCurve curve = convertCurve(ecSpec.getCurve()); + + return new org.bouncycastle.jce.spec.ECParameterSpec( + curve, + convertPoint(curve, ecSpec.getGenerator(), withCompression), + ecSpec.getOrder(), + BigInteger.valueOf(ecSpec.getCofactor()), + ecSpec.getCurve().getSeed()); + } + + public static org.bouncycastle.math.ec.ECPoint convertPoint( + ECParameterSpec ecSpec, + ECPoint point, + boolean withCompression) + { + return convertPoint(convertCurve(ecSpec.getCurve()), point, withCompression); + } + + public static org.bouncycastle.math.ec.ECPoint convertPoint( + ECCurve curve, + ECPoint point, + boolean withCompression) + { + return curve.createPoint(point.getAffineX(), point.getAffineY(), withCompression); + } +} diff --git a/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/ECUtil.java b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/ECUtil.java new file mode 100644 index 00000000..088dfad3 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/ECUtil.java @@ -0,0 +1,238 @@ +package org.bouncycastle.jce.provider.asymmetric.ec; + +import org.bouncycastle.asn1.DERObjectIdentifier; +// BEGIN android-removed +// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; +// END android-removed +import org.bouncycastle.asn1.nist.NISTNamedCurves; +import org.bouncycastle.asn1.sec.SECNamedCurves; +// BEGIN android-removed +// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; +// END android-removed +import org.bouncycastle.asn1.x9.X962NamedCurves; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.jce.interfaces.ECPrivateKey; +import org.bouncycastle.jce.interfaces.ECPublicKey; +import org.bouncycastle.jce.spec.ECParameterSpec; +import org.bouncycastle.jce.provider.ProviderUtil; +import org.bouncycastle.jce.provider.JCEECPublicKey; + +import java.security.InvalidKeyException; +import java.security.PrivateKey; +import java.security.PublicKey; + +/** + * utility class for converting jce/jca ECDSA, ECDH, and ECDHC + * objects into their org.bouncycastle.crypto counterparts. + */ +public class ECUtil +{ + /** + * Returns a sorted array of middle terms of the reduction polynomial. + * @param k The unsorted array of middle terms of the reduction polynomial + * of length 1 or 3. + * @return the sorted array of middle terms of the reduction polynomial. + * This array always has length 3. + */ + static int[] convertMidTerms( + int[] k) + { + int[] res = new int[3]; + + if (k.length == 1) + { + res[0] = k[0]; + } + else + { + if (k.length != 3) + { + throw new IllegalArgumentException("Only Trinomials and pentanomials supported"); + } + + if (k[0] < k[1] && k[0] < k[2]) + { + res[0] = k[0]; + if (k[1] < k[2]) + { + res[1] = k[1]; + res[2] = k[2]; + } + else + { + res[1] = k[2]; + res[2] = k[1]; + } + } + else if (k[1] < k[2]) + { + res[0] = k[1]; + if (k[0] < k[2]) + { + res[1] = k[0]; + res[2] = k[2]; + } + else + { + res[1] = k[2]; + res[2] = k[0]; + } + } + else + { + res[0] = k[2]; + if (k[0] < k[1]) + { + res[1] = k[0]; + res[2] = k[1]; + } + else + { + res[1] = k[1]; + res[2] = k[0]; + } + } + } + + return res; + } + + public static AsymmetricKeyParameter generatePublicKeyParameter( + PublicKey key) + throws InvalidKeyException + { + if (key instanceof ECPublicKey) + { + ECPublicKey k = (ECPublicKey)key; + ECParameterSpec s = k.getParameters(); + + if (s == null) + { + s = ProviderUtil.getEcImplicitlyCa(); + + return new ECPublicKeyParameters( + ((JCEECPublicKey)k).engineGetQ(), + new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); + } + else + { + return new ECPublicKeyParameters( + k.getQ(), + new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); + } + } + else if (key instanceof java.security.interfaces.ECPublicKey) + { + java.security.interfaces.ECPublicKey pubKey = (java.security.interfaces.ECPublicKey)key; + ECParameterSpec s = EC5Util.convertSpec(pubKey.getParams(), false); + return new ECPublicKeyParameters( + EC5Util.convertPoint(pubKey.getParams(), pubKey.getW(), false), + new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); + } + + throw new InvalidKeyException("cannot identify EC public key."); + } + + public static AsymmetricKeyParameter generatePrivateKeyParameter( + PrivateKey key) + throws InvalidKeyException + { + if (key instanceof ECPrivateKey) + { + ECPrivateKey k = (ECPrivateKey)key; + ECParameterSpec s = k.getParameters(); + + if (s == null) + { + s = ProviderUtil.getEcImplicitlyCa(); + } + + return new ECPrivateKeyParameters( + k.getD(), + new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); + } + + throw new InvalidKeyException("can't identify EC private key."); + } + + public static DERObjectIdentifier getNamedCurveOid( + String name) + { + DERObjectIdentifier oid = X962NamedCurves.getOID(name); + + if (oid == null) + { + 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 = ECGOST3410NamedCurves.getOID(name); + // } + // END android-removed + } + + return oid; + } + + public static X9ECParameters getNamedCurveByOid( + DERObjectIdentifier oid) + { + X9ECParameters params = X962NamedCurves.getByOID(oid); + + if (params == null) + { + params = SECNamedCurves.getByOID(oid); + if (params == null) + { + params = NISTNamedCurves.getByOID(oid); + } + // BEGIN android-removed + // if (params == null) + // { + // params = TeleTrusTNamedCurves.getByOID(oid); + // } + // END android-removed + } + + return params; + } + + public static String getCurveName( + DERObjectIdentifier oid) + { + String name = X962NamedCurves.getName(oid); + + if (name == null) + { + name = SECNamedCurves.getName(oid); + if (name == null) + { + name = NISTNamedCurves.getName(oid); + } + // BEGIN android-removed + // if (name == null) + // { + // name = TeleTrusTNamedCurves.getName(oid); + // } + // if (name == null) + // { + // name = ECGOST3410NamedCurves.getName(oid); + // } + // END android-removed + } + + return name; + } +} diff --git a/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/KeyAgreement.java b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/KeyAgreement.java new file mode 100644 index 00000000..d2fa69e5 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/KeyAgreement.java @@ -0,0 +1,336 @@ +package org.bouncycastle.jce.provider.asymmetric.ec; + +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.KeyAgreementSpi; +import javax.crypto.SecretKey; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x9.X9IntegerConverter; +import org.bouncycastle.crypto.BasicAgreement; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.DerivationFunction; +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; +// END android-removed +import org.bouncycastle.crypto.digests.SHA1Digest; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +// BEGIN android-removed +// import org.bouncycastle.crypto.params.MQVPrivateParameters; +// import org.bouncycastle.crypto.params.MQVPublicParameters; +// END android-removed +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 + +/** + * Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363 + * both the simple one, and the simple one with cofactors are supported. + * + * Also, MQV key agreement per SEC-1 + */ +public class KeyAgreement + extends KeyAgreementSpi +{ + private static final X9IntegerConverter converter = new X9IntegerConverter(); + private static final Hashtable algorithms = new Hashtable(); + + static + { + Integer i128 = new Integer(128); + Integer i192 = new Integer(192); + Integer i256 = new Integer(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); + } + + private String kaAlgorithm; + private BigInteger result; + private ECDomainParameters parameters; + private BasicAgreement agreement; + // BEGIN android-removed + // private DerivationFunction kdf; + // END android-removed + + private byte[] bigIntToBytes( + BigInteger r) + { + return converter.integerToBytes(r, converter.getByteLength(parameters.getG().getX())); + } + + protected KeyAgreement( + String kaAlgorithm, + BasicAgreement agreement, + DerivationFunction kdf) + { + this.kaAlgorithm = kaAlgorithm; + this.agreement = agreement; + // BEGIN android-removed + // this.kdf = kdf; + // END android-removed + } + + protected Key engineDoPhase( + Key key, + boolean lastPhase) + throws InvalidKeyException, IllegalStateException + { + if (parameters == null) + { + throw new IllegalStateException(kaAlgorithm + " not initialised."); + } + + if (!lastPhase) + { + throw new IllegalStateException(kaAlgorithm + " can only be between two parties."); + } + + CipherParameters pubKey; + // BEGIN android-removed + // if (agreement instanceof ECMQVBasicAgreement) + // { + // if (!(key instanceof MQVPublicKey)) + // { + // throw new InvalidKeyException(kaAlgorithm + " key agreement requires " + // + getSimpleName(MQVPublicKey.class) + " for doPhase"); + // } + // + // MQVPublicKey mqvPubKey = (MQVPublicKey)key; + // ECPublicKeyParameters staticKey = (ECPublicKeyParameters) + // ECUtil.generatePublicKeyParameter(mqvPubKey.getStaticKey()); + // ECPublicKeyParameters ephemKey = (ECPublicKeyParameters) + // ECUtil.generatePublicKeyParameter(mqvPubKey.getEphemeralKey()); + // + // pubKey = new MQVPublicParameters(staticKey, ephemKey); + // + // // TODO Validate that all the keys are using the same parameters? + // } + // else + // END android-removed + { + if (!(key instanceof ECPublicKey)) + { + throw new InvalidKeyException(kaAlgorithm + " key agreement requires " + + getSimpleName(ECPublicKey.class) + " for doPhase"); + } + + pubKey = ECUtil.generatePublicKeyParameter((PublicKey)key); + + // TODO Validate that all the keys are using the same parameters? + } + + result = agreement.calculateAgreement(pubKey); + + 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); + + // BEGIN android-removed + // if (kdf != null) + // { + // if (!algorithms.containsKey(algorithm)) + // { + // throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm); + // } + // + // int keySize = ((Integer)algorithms.get(algorithm)).intValue(); + // + // DHKDFParameters params = new DHKDFParameters(new DERObjectIdentifier(algorithm), keySize, secret); + // + // byte[] keyBytes = new byte[keySize / 8]; + // kdf.init(params); + // kdf.generateBytes(keyBytes, 0, keyBytes.length); + // secret = keyBytes; + // } + // else + // END android-removed + { + // TODO Should we be ensuring the key is the right length? + } + + return new SecretKeySpec(secret, algorithm); + } + + protected void engineInit( + Key key, + AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + initFromKey(key); + } + + protected void engineInit( + Key key, + SecureRandom random) + throws InvalidKeyException + { + initFromKey(key); + } + + private void initFromKey(Key key) + throws InvalidKeyException + { + // BEGIN android-removed + // if (agreement instanceof ECMQVBasicAgreement) + // { + // if (!(key instanceof MQVPrivateKey)) + // { + // throw new InvalidKeyException(kaAlgorithm + " key agreement requires " + // + getSimpleName(MQVPrivateKey.class) + " for initialisation"); + // } + // + // MQVPrivateKey mqvPrivKey = (MQVPrivateKey)key; + // ECPrivateKeyParameters staticPrivKey = (ECPrivateKeyParameters) + // ECUtil.generatePrivateKeyParameter(mqvPrivKey.getStaticPrivateKey()); + // ECPrivateKeyParameters ephemPrivKey = (ECPrivateKeyParameters) + // ECUtil.generatePrivateKeyParameter(mqvPrivKey.getEphemeralPrivateKey()); + // + // ECPublicKeyParameters ephemPubKey = null; + // if (mqvPrivKey.getEphemeralPublicKey() != null) + // { + // ephemPubKey = (ECPublicKeyParameters) + // ECUtil.generatePublicKeyParameter(mqvPrivKey.getEphemeralPublicKey()); + // } + // + // MQVPrivateParameters localParams = new MQVPrivateParameters(staticPrivKey, ephemPrivKey, ephemPubKey); + // this.parameters = staticPrivKey.getParameters(); + // + // // TODO Validate that all the keys are using the same parameters? + // + // agreement.init(localParams); + // } + // else + // END android-removed + { + if (!(key instanceof ECPrivateKey)) + { + throw new InvalidKeyException(kaAlgorithm + " key agreement requires " + + getSimpleName(ECPrivateKey.class) + " for initialisation"); + } + + ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)ECUtil.generatePrivateKeyParameter((PrivateKey)key); + this.parameters = privKey.getParameters(); + + agreement.init(privKey); + } + } + + private static String getSimpleName(Class clazz) + { + String fullName = clazz.getName(); + + return fullName.substring(fullName.lastIndexOf('.') + 1); + } + + public static class DH + extends KeyAgreement + { + public DH() + { + super("ECDH", new ECDHBasicAgreement(), null); + } + } + + // BEGIN android-removed + // public static class DHC + // extends KeyAgreement + // { + // public DHC() + // { + // super("ECDHC", new ECDHCBasicAgreement(), null); + // } + // } + // + // public static class MQV + // extends KeyAgreement + // { + // public MQV() + // { + // super("ECMQV", new ECMQVBasicAgreement(), null); + // } + // } + // + // public static class DHwithSHA1KDF + // extends KeyAgreement + // { + // public DHwithSHA1KDF() + // { + // super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest())); + // } + // } + // + // public static class MQVwithSHA1KDF + // extends KeyAgreement + // { + // public MQVwithSHA1KDF() + // { + // super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new ECDHKEKGenerator(new SHA1Digest())); + // } + // } + // END android-removed +} diff --git a/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/KeyFactory.java b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/KeyFactory.java new file mode 100644 index 00000000..630d2c73 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/KeyFactory.java @@ -0,0 +1,208 @@ +package org.bouncycastle.jce.provider.asymmetric.ec; + +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import org.bouncycastle.jce.provider.JCEECPrivateKey; +import org.bouncycastle.jce.provider.JCEECPublicKey; +import org.bouncycastle.jce.provider.JDKKeyFactory; +import org.bouncycastle.jce.provider.ProviderUtil; +import org.bouncycastle.jce.spec.ECPrivateKeySpec; +import org.bouncycastle.jce.spec.ECPublicKeySpec; +import org.bouncycastle.jce.spec.ECParameterSpec; + +public class KeyFactory + extends JDKKeyFactory +{ + String algorithm; + + KeyFactory( + String algorithm) + { + this.algorithm = algorithm; + } + + protected Key engineTranslateKey( + Key key) + throws InvalidKeyException + { + if (key instanceof ECPublicKey) + { + return new JCEECPublicKey((ECPublicKey)key); + } + else if (key instanceof ECPrivateKey) + { + return new JCEECPrivateKey((ECPrivateKey)key); + } + + throw new InvalidKeyException("key type unknown"); + } + + protected KeySpec engineGetKeySpec( + Key key, + Class spec) + throws InvalidKeySpecException + { + if (spec.isAssignableFrom(PKCS8EncodedKeySpec.class) && key.getFormat().equals("PKCS#8")) + { + return new PKCS8EncodedKeySpec(key.getEncoded()); + } + else if (spec.isAssignableFrom(X509EncodedKeySpec.class) && key.getFormat().equals("X.509")) + { + return new X509EncodedKeySpec(key.getEncoded()); + } + else if (spec.isAssignableFrom(java.security.spec.ECPublicKeySpec.class) && key instanceof ECPublicKey) + { + ECPublicKey k = (ECPublicKey)key; + if (k.getParams() != null) + { + return new java.security.spec.ECPublicKeySpec(k.getW(), k.getParams()); + } + else + { + ECParameterSpec implicitSpec = ProviderUtil.getEcImplicitlyCa(); + + return new java.security.spec.ECPublicKeySpec(k.getW(), EC5Util.convertSpec(EC5Util.convertCurve(implicitSpec.getCurve(), implicitSpec.getSeed()), implicitSpec)); + } + } + else if (spec.isAssignableFrom(java.security.spec.ECPrivateKeySpec.class) && key instanceof ECPrivateKey) + { + ECPrivateKey k = (ECPrivateKey)key; + + if (k.getParams() != null) + { + return new java.security.spec.ECPrivateKeySpec(k.getS(), k.getParams()); + } + else + { + ECParameterSpec implicitSpec = ProviderUtil.getEcImplicitlyCa(); + + return new java.security.spec.ECPrivateKeySpec(k.getS(), EC5Util.convertSpec(EC5Util.convertCurve(implicitSpec.getCurve(), implicitSpec.getSeed()), implicitSpec)); + } + } + + throw new RuntimeException("not implemented yet " + key + " " + spec); + } + + protected PrivateKey engineGeneratePrivate( + KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof PKCS8EncodedKeySpec) + { + try + { + JCEECPrivateKey key = (JCEECPrivateKey)JDKKeyFactory.createPrivateKeyFromDERStream( + ((PKCS8EncodedKeySpec)keySpec).getEncoded()); + + return new JCEECPrivateKey(algorithm, key); + } + catch (Exception e) + { + throw new InvalidKeySpecException(e.toString()); + } + } + else if (keySpec instanceof ECPrivateKeySpec) + { + return new JCEECPrivateKey(algorithm, (ECPrivateKeySpec)keySpec); + } + else if (keySpec instanceof java.security.spec.ECPrivateKeySpec) + { + return new JCEECPrivateKey(algorithm, (java.security.spec.ECPrivateKeySpec)keySpec); + } + + throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName()); + } + + protected PublicKey engineGeneratePublic( + KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof X509EncodedKeySpec) + { + try + { + JCEECPublicKey key = (JCEECPublicKey)JDKKeyFactory.createPublicKeyFromDERStream( + ((X509EncodedKeySpec)keySpec).getEncoded()); + + return new JCEECPublicKey(algorithm, key); + } + catch (Exception e) + { + throw new InvalidKeySpecException(e.toString()); + } + } + else if (keySpec instanceof ECPublicKeySpec) + { + return new JCEECPublicKey(algorithm, (ECPublicKeySpec)keySpec); + } + else if (keySpec instanceof java.security.spec.ECPublicKeySpec) + { + return new JCEECPublicKey(algorithm, (java.security.spec.ECPublicKeySpec)keySpec); + } + + throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName()); + } + + public static class EC + extends KeyFactory + { + public EC() + { + super("EC"); + } + } + + public static class ECDSA + extends KeyFactory + { + public ECDSA() + { + super("ECDSA"); + } + } + + public static class ECGOST3410 + extends KeyFactory + { + public ECGOST3410() + { + super("ECGOST3410"); + } + } + + public static class ECDH + extends KeyFactory + { + public ECDH() + { + super("ECDH"); + } + } + + public static class ECDHC + extends KeyFactory + { + public ECDHC() + { + super("ECDHC"); + } + } + + public static class ECMQV + extends KeyFactory + { + public ECMQV() + { + super("ECMQV"); + } + } +}
\ No newline at end of file diff --git a/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/KeyPairGenerator.java b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/KeyPairGenerator.java new file mode 100644 index 00000000..88228d54 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/KeyPairGenerator.java @@ -0,0 +1,348 @@ +package org.bouncycastle.jce.provider.asymmetric.ec; + +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.ECGenParameterSpec; +import java.util.Hashtable; + +import org.bouncycastle.asn1.DERObjectIdentifier; +// BEGIN android-removed +// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; +// END android-removed +import org.bouncycastle.asn1.nist.NISTNamedCurves; +import org.bouncycastle.asn1.sec.SECNamedCurves; +// BEGIN android-removed +// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; +// END android-removed +import org.bouncycastle.asn1.x9.X962NamedCurves; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.generators.ECKeyPairGenerator; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECKeyGenerationParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.jce.provider.JCEECPrivateKey; +import org.bouncycastle.jce.provider.JCEECPublicKey; +import org.bouncycastle.jce.provider.JDKKeyPairGenerator; +import org.bouncycastle.jce.provider.ProviderUtil; +import org.bouncycastle.jce.spec.ECNamedCurveSpec; +import org.bouncycastle.jce.spec.ECParameterSpec; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECPoint; + +public abstract class KeyPairGenerator + extends JDKKeyPairGenerator +{ + public KeyPairGenerator(String algorithmName) + { + super(algorithmName); + } + + public static class EC + extends KeyPairGenerator + { + ECKeyGenerationParameters param; + ECKeyPairGenerator engine = new ECKeyPairGenerator(); + Object ecParams = null; + int strength = 239; + int certainty = 50; + SecureRandom random = new SecureRandom(); + boolean initialised = false; + String algorithm; + + static private Hashtable ecParameters; + + static { + ecParameters = new Hashtable(); + + ecParameters.put(new Integer(192), new ECGenParameterSpec("prime192v1")); // a.k.a P-192 + ecParameters.put(new Integer(239), new ECGenParameterSpec("prime239v1")); + ecParameters.put(new Integer(256), new ECGenParameterSpec("prime256v1")); // a.k.a P-256 + + ecParameters.put(new Integer(224), new ECGenParameterSpec("P-224")); + ecParameters.put(new Integer(384), new ECGenParameterSpec("P-384")); + ecParameters.put(new Integer(521), new ECGenParameterSpec("P-521")); + } + + public EC() + { + super("EC"); + this.algorithm = "EC"; + } + + public EC( + String algorithm) + { + super(algorithm); + this.algorithm = algorithm; + } + + public void initialize( + int strength, + SecureRandom random) + { + this.strength = strength; + // BEGIN android-added + if (random != null) { + // END android-added + this.random = random; + // BEGIN android-added + } + // END android-added + this.ecParams = ecParameters.get(new Integer(strength)); + + if (ecParams != null) + { + try + { + initialize((ECGenParameterSpec)ecParams, random); + } + catch (InvalidAlgorithmParameterException e) + { + throw new InvalidParameterException("key size not configurable."); + } + } + else + { + throw new InvalidParameterException("unknown key size."); + } + } + + public void initialize( + AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException + { + // BEGIN android-added + if (random == null) { + random = this.random; + } + // END android-added + if (params instanceof ECParameterSpec) + { + ECParameterSpec p = (ECParameterSpec)params; + this.ecParams = params; + + param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); + + engine.init(param); + initialised = true; + } + else if (params instanceof java.security.spec.ECParameterSpec) + { + java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)params; + this.ecParams = params; + + ECCurve curve = EC5Util.convertCurve(p.getCurve()); + ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false); + + param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random); + + engine.init(param); + initialised = true; + } + else if (params instanceof ECGenParameterSpec) + { + final String curveName = ((ECGenParameterSpec)params).getName(); + + // BEGIN android-removed + // if (this.algorithm.equals("ECGOST3410")) + // { + // ECDomainParameters ecP = ECGOST3410NamedCurves.getByName(curveName); + // if (ecP == null) + // { + // throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); + // } + // + // this.ecParams = new ECNamedCurveSpec( + // curveName, + // ecP.getCurve(), + // ecP.getG(), + // ecP.getN(), + // ecP.getH(), + // ecP.getSeed()); + // } + // else + // END android-removed + { + X9ECParameters ecP = X962NamedCurves.getByName(curveName); + if (ecP == null) + { + ecP = SECNamedCurves.getByName(curveName); + if (ecP == null) + { + ecP = NISTNamedCurves.getByName(curveName); + } + // BEGIN android-removed + // if (ecP == null) + // { + // ecP = TeleTrusTNamedCurves.getByName(curveName); + // } + // END android-removed + if (ecP == null) + { + // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug) + try + { + DERObjectIdentifier oid = new DERObjectIdentifier(curveName); + ecP = X962NamedCurves.getByOID(oid); + if (ecP == null) + { + ecP = SECNamedCurves.getByOID(oid); + } + if (ecP == null) + { + ecP = NISTNamedCurves.getByOID(oid); + } + // BEGIN android-removed + // if (ecP == null) + // { + // ecP = TeleTrusTNamedCurves.getByOID(oid); + // } + // END android-removed + if (ecP == null) + { + throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName); + } + } + catch (IllegalArgumentException ex) + { + throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); + } + } + } + + this.ecParams = new ECNamedCurveSpec( + curveName, + ecP.getCurve(), + ecP.getG(), + ecP.getN(), + ecP.getH(), + null); // ecP.getSeed()); Work-around JDK bug -- it won't look up named curves properly if seed is present + } + + java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams; + + ECCurve curve = EC5Util.convertCurve(p.getCurve()); + ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false); + + param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random); + + engine.init(param); + initialised = true; + } + else if (params == null && ProviderUtil.getEcImplicitlyCa() != null) + { + ECParameterSpec p = ProviderUtil.getEcImplicitlyCa(); + this.ecParams = params; + + param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); + + engine.init(param); + initialised = true; + } + else if (params == null && ProviderUtil.getEcImplicitlyCa() == null) + { + throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set"); + } + else + { + throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec"); + } + } + + public KeyPair generateKeyPair() + { + if (!initialised) + { + // BEGIN android-removed + // throw new IllegalStateException("EC Key Pair Generator not initialised"); + // END android-removed + // BEGIN android-added + /* + * KeyPairGenerator documentation says that a default initialization must be provided + */ + initialize(192, random); + // END android-added + } + + AsymmetricCipherKeyPair pair = engine.generateKeyPair(); + ECPublicKeyParameters pub = (ECPublicKeyParameters)pair.getPublic(); + ECPrivateKeyParameters priv = (ECPrivateKeyParameters)pair.getPrivate(); + + if (ecParams instanceof ECParameterSpec) + { + ECParameterSpec p = (ECParameterSpec)ecParams; + + JCEECPublicKey pubKey = new JCEECPublicKey(algorithm, pub, p); + return new KeyPair(pubKey, + new JCEECPrivateKey(algorithm, priv, pubKey, p)); + } + else if (ecParams == null) + { + return new KeyPair(new JCEECPublicKey(algorithm, pub), + new JCEECPrivateKey(algorithm, priv)); + } + else + { + java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams; + + JCEECPublicKey pubKey = new JCEECPublicKey(algorithm, pub, p); + + return new KeyPair(pubKey, new JCEECPrivateKey(algorithm, priv, pubKey, p)); + } + } + } + + public static class ECDSA + extends EC + { + public ECDSA() + { + super("ECDSA"); + } + } + + // BEGIN android-removed + // public static class ECGOST3410 + // extends EC + // { + // public ECGOST3410() + // { + // super("ECGOST3410"); + // } + // } + // END android-removed + + public static class ECDH + extends EC + { + public ECDH() + { + super("ECDH"); + } + } + + public static class ECDHC + extends EC + { + public ECDHC() + { + super("ECDHC"); + } + } + + public static class ECMQV + extends EC + { + public ECMQV() + { + super("ECMQV"); + } + } +} diff --git a/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/Signature.java b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/Signature.java new file mode 100644 index 00000000..13a868c8 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/provider/asymmetric/ec/Signature.java @@ -0,0 +1,345 @@ +package org.bouncycastle.jce.provider.asymmetric.ec; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.interfaces.ECPublicKey; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.DSA; +import org.bouncycastle.crypto.Digest; +// BEGIN android-removed +// import org.bouncycastle.crypto.digests.RIPEMD160Digest; +// END android-removed +import org.bouncycastle.crypto.digests.SHA1Digest; +// BEGIN android-removed +// import org.bouncycastle.crypto.digests.SHA224Digest; +// END android-removed +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.digests.SHA384Digest; +import org.bouncycastle.crypto.digests.SHA512Digest; +import org.bouncycastle.crypto.params.ParametersWithRandom; +import org.bouncycastle.crypto.signers.ECDSASigner; +// BEGIN android-removed +// import org.bouncycastle.crypto.signers.ECNRSigner; +// END android-removed +import org.bouncycastle.jce.interfaces.ECKey; +import org.bouncycastle.jce.provider.DSABase; +import org.bouncycastle.jce.provider.DSAEncoder; +import org.bouncycastle.jce.provider.JDKKeyFactory; +import org.bouncycastle.jce.provider.util.NullDigest; + +public class Signature + extends DSABase +{ + Signature(Digest digest, DSA signer, DSAEncoder encoder) + { + super(digest, signer, encoder); + } + + protected void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException + { + CipherParameters param; + + if (publicKey instanceof ECPublicKey) + { + param = ECUtil.generatePublicKeyParameter(publicKey); + } + else + { + try + { + byte[] bytes = publicKey.getEncoded(); + + publicKey = JDKKeyFactory.createPublicKeyFromDERStream(bytes); + + if (publicKey instanceof ECPublicKey) + { + param = ECUtil.generatePublicKeyParameter(publicKey); + } + else + { + throw new InvalidKeyException("can't recognise key type in ECDSA based signer"); + } + } + catch (Exception e) + { + throw new InvalidKeyException("can't recognise key type in ECDSA based signer"); + } + } + + digest.reset(); + signer.init(false, param); + } + + protected void engineInitSign( + PrivateKey privateKey, + SecureRandom random) + throws InvalidKeyException + { + CipherParameters param; + + if (privateKey instanceof ECKey) + { + param = ECUtil.generatePrivateKeyParameter(privateKey); + } + else + { + throw new InvalidKeyException("can't recognise key type in ECDSA based signer"); + } + + digest.reset(); + + if (random != null) + { + signer.init(true, new ParametersWithRandom(param, random)); + } + else + { + signer.init(true, param); + } + } + + static public class ecDSA + extends Signature + { + public ecDSA() + { + super(new SHA1Digest(), new ECDSASigner(), new StdDSAEncoder()); + } + } + + static public class ecDSAnone + extends Signature + { + public ecDSAnone() + { + super(new NullDigest(), new ECDSASigner(), new StdDSAEncoder()); + } + } + + // BEGIN android-removed + // static public class ecDSA224 + // extends Signature + // { + // public ecDSA224() + // { + // super(new SHA224Digest(), new ECDSASigner(), new StdDSAEncoder()); + // } + // } + // END android-removed + + static public class ecDSA256 + extends Signature + { + public ecDSA256() + { + super(new SHA256Digest(), new ECDSASigner(), new StdDSAEncoder()); + } + } + + static public class ecDSA384 + extends Signature + { + public ecDSA384() + { + super(new SHA384Digest(), new ECDSASigner(), new StdDSAEncoder()); + } + } + + static public class ecDSA512 + extends Signature + { + public ecDSA512() + { + super(new SHA512Digest(), new ECDSASigner(), new StdDSAEncoder()); + } + } + + // BEGIN android-removed + // static public class ecDSARipeMD160 + // extends Signature + // { + // public ecDSARipeMD160() + // { + // super(new RIPEMD160Digest(), new ECDSASigner(), new StdDSAEncoder()); + // } + // } + // + // static public class ecNR + // extends Signature + // { + // public ecNR() + // { + // super(new SHA1Digest(), new ECNRSigner(), new StdDSAEncoder()); + // } + // } + // + // static public class ecNR224 + // extends Signature + // { + // public ecNR224() + // { + // super(new SHA224Digest(), new ECNRSigner(), new StdDSAEncoder()); + // } + // } + // + // static public class ecNR256 + // extends Signature + // { + // public ecNR256() + // { + // super(new SHA256Digest(), new ECNRSigner(), new StdDSAEncoder()); + // } + // } + // + // static public class ecNR384 + // extends Signature + // { + // public ecNR384() + // { + // super(new SHA384Digest(), new ECNRSigner(), new StdDSAEncoder()); + // } + // } + // + // static public class ecNR512 + // extends Signature + // { + // public ecNR512() + // { + // super(new SHA512Digest(), new ECNRSigner(), new StdDSAEncoder()); + // } + // } + // + // static public class ecCVCDSA + // extends Signature + // { + // public ecCVCDSA() + // { + // super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder()); + // } + // } + // + // static public class ecCVCDSA224 + // extends Signature + // { + // public ecCVCDSA224() + // { + // super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder()); + // } + // } + // + // static public class ecCVCDSA256 + // extends Signature + // { + // public ecCVCDSA256() + // { + // super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder()); + // } + // } + // END android-removed + + private static class StdDSAEncoder + implements DSAEncoder + { + public byte[] encode( + BigInteger r, + BigInteger s) + throws IOException + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(new DERInteger(r)); + v.add(new DERInteger(s)); + + return new DERSequence(v).getEncoded(ASN1Encodable.DER); + } + + public BigInteger[] decode( + byte[] encoding) + throws IOException + { + ASN1Sequence s = (ASN1Sequence)ASN1Object.fromByteArray(encoding); + BigInteger[] sig = new BigInteger[2]; + + sig[0] = ((DERInteger)s.getObjectAt(0)).getValue(); + sig[1] = ((DERInteger)s.getObjectAt(1)).getValue(); + + return sig; + } + } + + private static class CVCDSAEncoder + implements DSAEncoder + { + public byte[] encode( + BigInteger r, + BigInteger s) + throws IOException + { + byte[] first = makeUnsigned(r); + byte[] second = makeUnsigned(s); + byte[] res; + + if (first.length > second.length) + { + res = new byte[first.length * 2]; + } + else + { + res = new byte[second.length * 2]; + } + + System.arraycopy(first, 0, res, res.length / 2 - first.length, first.length); + System.arraycopy(second, 0, res, res.length - second.length, second.length); + + return res; + } + + + private byte[] makeUnsigned(BigInteger val) + { + byte[] res = val.toByteArray(); + + if (res[0] == 0) + { + byte[] tmp = new byte[res.length - 1]; + + System.arraycopy(res, 1, tmp, 0, tmp.length); + + return tmp; + } + + return res; + } + + public BigInteger[] decode( + byte[] encoding) + throws IOException + { + BigInteger[] sig = new BigInteger[2]; + + byte[] first = new byte[encoding.length / 2]; + byte[] second = new byte[encoding.length / 2]; + + System.arraycopy(encoding, 0, first, 0, first.length); + System.arraycopy(encoding, first.length, second, 0, second.length); + + sig[0] = new BigInteger(1, first); + sig[1] = new BigInteger(1, second); + + return sig; + } + } +} diff --git a/src/main/java/org/bouncycastle/jce/spec/ECKeySpec.java b/src/main/java/org/bouncycastle/jce/spec/ECKeySpec.java new file mode 100644 index 00000000..12157844 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/spec/ECKeySpec.java @@ -0,0 +1,26 @@ +package org.bouncycastle.jce.spec; + +import java.security.spec.KeySpec; + +/** + * base class for an Elliptic Curve Key Spec + */ +public class ECKeySpec + implements KeySpec +{ + private ECParameterSpec spec; + + protected ECKeySpec( + ECParameterSpec spec) + { + this.spec = spec; + } + + /** + * return the domain parameters for the curve + */ + public ECParameterSpec getParams() + { + return spec; + } +} diff --git a/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java b/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java new file mode 100644 index 00000000..47416a22 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java @@ -0,0 +1,62 @@ +package org.bouncycastle.jce.spec; + +import java.math.BigInteger; + +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECPoint; + +/** + * specification signifying that the curve parameters can also be + * refered to by name. + * <p> + * If you are using JDK 1.5 you should be looking at ECNamedCurveSpec. + */ +public class ECNamedCurveParameterSpec + extends ECParameterSpec +{ + private String name; + + public ECNamedCurveParameterSpec( + String name, + ECCurve curve, + ECPoint G, + BigInteger n) + { + super(curve, G, n); + + this.name = name; + } + + public ECNamedCurveParameterSpec( + String name, + ECCurve curve, + ECPoint G, + BigInteger n, + BigInteger h) + { + super(curve, G, n, h); + + this.name = name; + } + + public ECNamedCurveParameterSpec( + String name, + ECCurve curve, + ECPoint G, + BigInteger n, + BigInteger h, + byte[] seed) + { + super(curve, G, n, h, seed); + + this.name = name; + } + + /** + * return the name of the curve the EC domain parameters belong to. + */ + public String getName() + { + return name; + } +} diff --git a/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java b/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java new file mode 100644 index 00000000..84ebf70a --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java @@ -0,0 +1,121 @@ +package org.bouncycastle.jce.spec; + +import java.math.BigInteger; +import java.security.spec.ECFieldF2m; +import java.security.spec.ECFieldFp; +import java.security.spec.ECPoint; +import java.security.spec.EllipticCurve; + +import org.bouncycastle.math.ec.ECCurve; + +/** + * specification signifying that the curve parameters can also be + * referred to by name. + */ +public class ECNamedCurveSpec + extends java.security.spec.ECParameterSpec +{ + private String name; + + private static EllipticCurve convertCurve( + ECCurve curve, + byte[] seed) + { + if (curve instanceof ECCurve.Fp) + { + return new EllipticCurve(new ECFieldFp(((ECCurve.Fp)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), seed); + } + else + { + 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); + } + } + + } + + private static ECPoint convertPoint( + org.bouncycastle.math.ec.ECPoint g) + { + return new ECPoint(g.getX().toBigInteger(), g.getY().toBigInteger()); + } + + public ECNamedCurveSpec( + String name, + ECCurve curve, + org.bouncycastle.math.ec.ECPoint g, + BigInteger n) + { + super(convertCurve(curve, null), convertPoint(g), n, 1); + + this.name = name; + } + + public ECNamedCurveSpec( + String name, + EllipticCurve curve, + ECPoint g, + BigInteger n) + { + super(curve, g, n, 1); + + this.name = name; + } + + public ECNamedCurveSpec( + String name, + ECCurve curve, + org.bouncycastle.math.ec.ECPoint g, + BigInteger n, + BigInteger h) + { + super(convertCurve(curve, null), convertPoint(g), n, h.intValue()); + + this.name = name; + } + + public ECNamedCurveSpec( + String name, + EllipticCurve curve, + ECPoint g, + BigInteger n, + BigInteger h) + { + super(curve, g, n, h.intValue()); + + this.name = name; + } + + public ECNamedCurveSpec( + String name, + ECCurve curve, + org.bouncycastle.math.ec.ECPoint g, + BigInteger n, + BigInteger h, + byte[] seed) + { + super(convertCurve(curve, seed), convertPoint(g), n, h.intValue()); + + this.name = name; + } + + /** + * return the name of the curve the EC domain parameters belong to. + */ + public String getName() + { + return name; + } +} diff --git a/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java b/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java new file mode 100644 index 00000000..e774a11e --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java @@ -0,0 +1,121 @@ +package org.bouncycastle.jce.spec; + +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECPoint; + +import java.math.BigInteger; +import java.security.spec.AlgorithmParameterSpec; + +/** + * basic domain parameters for an Elliptic Curve public or private key. + */ +public class ECParameterSpec + implements AlgorithmParameterSpec +{ + private ECCurve curve; + private byte[] seed; + private ECPoint G; + private BigInteger n; + private BigInteger h; + + public ECParameterSpec( + ECCurve curve, + ECPoint G, + BigInteger n) + { + this.curve = curve; + this.G = G; + this.n = n; + this.h = BigInteger.valueOf(1); + this.seed = null; + } + + public ECParameterSpec( + ECCurve curve, + ECPoint G, + BigInteger n, + BigInteger h) + { + this.curve = curve; + this.G = G; + this.n = n; + this.h = h; + this.seed = null; + } + + public ECParameterSpec( + ECCurve curve, + ECPoint G, + BigInteger n, + BigInteger h, + byte[] seed) + { + this.curve = curve; + this.G = G; + this.n = n; + this.h = h; + this.seed = seed; + } + + /** + * return the curve along which the base point lies. + * @return the curve + */ + public ECCurve getCurve() + { + return curve; + } + + /** + * return the base point we are using for these domain parameters. + * @return the base point. + */ + public ECPoint getG() + { + return G; + } + + /** + * return the order N of G + * @return the order + */ + public BigInteger getN() + { + return n; + } + + /** + * return the cofactor H to the order of G. + * @return the cofactor + */ + public BigInteger getH() + { + return h; + } + + /** + * return the seed used to generate this curve (if available). + * @return the random seed + */ + public byte[] getSeed() + { + return seed; + } + + public boolean equals(Object o) + { + if (!(o instanceof ECParameterSpec)) + { + return false; + } + + ECParameterSpec other = (ECParameterSpec)o; + + return this.getCurve().equals(other.getCurve()) && this.getG().equals(other.getG()); + } + + public int hashCode() + { + return this.getCurve().hashCode() ^ this.getG().hashCode(); + } +} diff --git a/src/main/java/org/bouncycastle/jce/spec/ECPrivateKeySpec.java b/src/main/java/org/bouncycastle/jce/spec/ECPrivateKeySpec.java new file mode 100644 index 00000000..27885c40 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/spec/ECPrivateKeySpec.java @@ -0,0 +1,35 @@ +package org.bouncycastle.jce.spec; + +import java.math.BigInteger; + +/** + * Elliptic Curve private key specification. + */ +public class ECPrivateKeySpec + extends ECKeySpec +{ + private BigInteger d; + + /** + * base constructor + * + * @param d the private number for the key. + * @param spec the domain parameters for the curve being used. + */ + public ECPrivateKeySpec( + BigInteger d, + ECParameterSpec spec) + { + super(spec); + + this.d = d; + } + + /** + * return the private number D + */ + public BigInteger getD() + { + return d; + } +} diff --git a/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java b/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java new file mode 100644 index 00000000..debab004 --- /dev/null +++ b/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java @@ -0,0 +1,35 @@ +package org.bouncycastle.jce.spec; + +import org.bouncycastle.math.ec.ECPoint; + +/** + * Elliptic Curve public key specification + */ +public class ECPublicKeySpec + extends ECKeySpec +{ + private ECPoint q; + + /** + * base constructor + * + * @param q the public point on the curve. + * @param spec the domain parameters for the curve. + */ + public ECPublicKeySpec( + ECPoint q, + ECParameterSpec spec) + { + super(spec); + + this.q = q; + } + + /** + * return the public point q + */ + public ECPoint getQ() + { + return q; + } +} diff --git a/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java b/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java new file mode 100644 index 00000000..a5b268e0 --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java @@ -0,0 +1,93 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; + +public class ECAlgorithms +{ + public static ECPoint sumOfTwoMultiplies(ECPoint P, BigInteger a, + ECPoint Q, BigInteger b) + { + ECCurve c = P.getCurve(); + if (!c.equals(Q.getCurve())) + { + throw new IllegalArgumentException("P and Q must be on same curve"); + } + + // TODO Add special case back in when WTNAF is enabled +// // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick +// if (c instanceof ECCurve.F2m) +// { +// ECCurve.F2m f2mCurve = (ECCurve.F2m) c; +// if (f2mCurve.isKoblitz()) +// { +// return P.multiply(a).add(Q.multiply(b)); +// } +// } + + return implShamirsTrick(P, a, Q, b); + } + + /* + * "Shamir's Trick", originally due to E. G. Straus + * (Addition chains of vectors. American Mathematical Monthly, + * 71(7):806-808, Aug./Sept. 1964) + * <pre> + * Input: The points P, Q, scalar k = (km?, ... , k1, k0) + * and scalar l = (lm?, ... , l1, l0). + * Output: R = k * P + l * Q. + * 1: Z <- P + Q + * 2: R <- O + * 3: for i from m-1 down to 0 do + * 4: R <- R + R {point doubling} + * 5: if (ki = 1) and (li = 0) then R <- R + P end if + * 6: if (ki = 0) and (li = 1) then R <- R + Q end if + * 7: if (ki = 1) and (li = 1) then R <- R + Z end if + * 8: end for + * 9: return R + * </pre> + */ + public static ECPoint shamirsTrick(ECPoint P, BigInteger k, + ECPoint Q, BigInteger l) + { + if (!P.getCurve().equals(Q.getCurve())) + { + throw new IllegalArgumentException("P and Q must be on same curve"); + } + + return implShamirsTrick(P, k, Q, l); + } + + private static ECPoint implShamirsTrick(ECPoint P, BigInteger k, + ECPoint Q, BigInteger l) + { + int m = Math.max(k.bitLength(), l.bitLength()); + ECPoint Z = P.add(Q); + ECPoint R = P.getCurve().getInfinity(); + + for (int i = m - 1; i >= 0; --i) + { + R = R.twice(); + + if (k.testBit(i)) + { + if (l.testBit(i)) + { + R = R.add(Z); + } + else + { + R = R.add(P); + } + } + else + { + if (l.testBit(i)) + { + R = R.add(Q); + } + } + } + + return R; + } +} diff --git a/src/main/java/org/bouncycastle/math/ec/ECConstants.java b/src/main/java/org/bouncycastle/math/ec/ECConstants.java new file mode 100644 index 00000000..864f746d --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/ECConstants.java @@ -0,0 +1,12 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; + +public interface ECConstants +{ + public static final BigInteger ZERO = BigInteger.valueOf(0); + public static final BigInteger ONE = BigInteger.valueOf(1); + public static final BigInteger TWO = BigInteger.valueOf(2); + public static final BigInteger THREE = BigInteger.valueOf(3); + public static final BigInteger FOUR = BigInteger.valueOf(4); +} diff --git a/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/src/main/java/org/bouncycastle/math/ec/ECCurve.java new file mode 100644 index 00000000..4db07d50 --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/ECCurve.java @@ -0,0 +1,660 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; +import java.util.Random; + +/** + * base class for an elliptic curve + */ +public abstract class ECCurve +{ + ECFieldElement a, b; + + public abstract int getFieldSize(); + + public abstract ECFieldElement fromBigInteger(BigInteger x); + + public abstract ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression); + + public abstract ECPoint decodePoint(byte[] encoded); + + public abstract ECPoint getInfinity(); + + public ECFieldElement getA() + { + return a; + } + + public ECFieldElement getB() + { + return b; + } + + /** + * Elliptic curve over Fp + */ + public static class Fp extends ECCurve + { + BigInteger q; + ECPoint.Fp infinity; + + public Fp(BigInteger q, BigInteger a, BigInteger b) + { + this.q = q; + this.a = fromBigInteger(a); + this.b = fromBigInteger(b); + this.infinity = new ECPoint.Fp(this, null, null); + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new ECFieldElement.Fp(this.q, x); + } + + public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) + { + return new ECPoint.Fp(this, fromBigInteger(x), fromBigInteger(y), withCompression); + } + + /** + * Decode a point on this curve from its ASN.1 encoding. The different + * encodings are taken account of, including point compression for + * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17). + * @return The decoded point. + */ + public ECPoint decodePoint(byte[] encoded) + { + ECPoint p = null; + + switch (encoded[0]) + { + // infinity + case 0x00: + p = getInfinity(); + break; + // compressed + case 0x02: + case 0x03: + int ytilde = encoded[0] & 1; + byte[] i = new byte[encoded.length - 1]; + + System.arraycopy(encoded, 1, i, 0, i.length); + + ECFieldElement x = new ECFieldElement.Fp(this.q, new BigInteger(1, i)); + ECFieldElement alpha = x.multiply(x.square().add(a)).add(b); + ECFieldElement beta = alpha.sqrt(); + + // + // if we can't find a sqrt we haven't got a point on the + // curve - run! + // + if (beta == null) + { + throw new RuntimeException("Invalid point compression"); + } + + int bit0 = (beta.toBigInteger().testBit(0) ? 1 : 0); + + if (bit0 == ytilde) + { + p = new ECPoint.Fp(this, x, beta, true); + } + else + { + p = new ECPoint.Fp(this, x, + new ECFieldElement.Fp(this.q, q.subtract(beta.toBigInteger())), true); + } + break; + // uncompressed + case 0x04: + // hybrid + case 0x06: + case 0x07: + byte[] xEnc = new byte[(encoded.length - 1) / 2]; + byte[] yEnc = new byte[(encoded.length - 1) / 2]; + + System.arraycopy(encoded, 1, xEnc, 0, xEnc.length); + System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length); + + p = new ECPoint.Fp(this, + new ECFieldElement.Fp(this.q, new BigInteger(1, xEnc)), + new ECFieldElement.Fp(this.q, new BigInteger(1, yEnc))); + break; + default: + throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); + } + + return p; + } + + public ECPoint getInfinity() + { + return infinity; + } + + public boolean equals( + Object anObject) + { + if (anObject == this) + { + return true; + } + + if (!(anObject instanceof ECCurve.Fp)) + { + return false; + } + + ECCurve.Fp other = (ECCurve.Fp) anObject; + + return this.q.equals(other.q) + && a.equals(other.a) && b.equals(other.b); + } + + public int hashCode() + { + return a.hashCode() ^ b.hashCode() ^ q.hashCode(); + } + } + + /** + * Elliptic curves over F2m. The Weierstrass equation is given by + * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>. + */ + public static class F2m extends ECCurve + { + /** + * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. + */ + private int m; // can't be final - JDK 1.1 + + /** + * TPB: The integer <code>k</code> where <code>x<sup>m</sup> + + * x<sup>k</sup> + 1</code> represents the reduction polynomial + * <code>f(z)</code>.<br> + * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.<br> + */ + private int k1; // can't be final - JDK 1.1 + + /** + * TPB: Always set to <code>0</code><br> + * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.<br> + */ + private int k2; // can't be final - JDK 1.1 + + /** + * TPB: Always set to <code>0</code><br> + * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.<br> + */ + private int k3; // can't be final - JDK 1.1 + + /** + * The order of the base point of the curve. + */ + private BigInteger n; // can't be final - JDK 1.1 + + /** + * The cofactor of the curve. + */ + private BigInteger h; // can't be final - JDK 1.1 + + /** + * The point at infinity on this curve. + */ + 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>. + * @param k The integer <code>k</code> where <code>x<sup>m</sup> + + * x<sup>k</sup> + 1</code> represents the reduction + * polynomial <code>f(z)</code>. + * @param a The coefficient <code>a</code> in the Weierstrass equation + * for non-supersingular elliptic curves over + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param b The coefficient <code>b</code> in the Weierstrass equation + * for non-supersingular elliptic curves over + * <code>F<sub>2<sup>m</sup></sub></code>. + */ + public F2m( + int m, + int k, + BigInteger a, + BigInteger b) + { + this(m, k, 0, 0, a, b, null, null); + } + + /** + * Constructor for Trinomial Polynomial Basis (TPB). + * @param m The exponent <code>m</code> of + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param k The integer <code>k</code> where <code>x<sup>m</sup> + + * x<sup>k</sup> + 1</code> represents the reduction + * polynomial <code>f(z)</code>. + * @param a The coefficient <code>a</code> in the Weierstrass equation + * for non-supersingular elliptic curves over + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param b The coefficient <code>b</code> in the Weierstrass equation + * for non-supersingular elliptic curves over + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param n The order of the main subgroup of the elliptic curve. + * @param h The cofactor of the elliptic curve, i.e. + * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>. + */ + public F2m( + int m, + int k, + BigInteger a, + BigInteger b, + BigInteger n, + BigInteger h) + { + this(m, k, 0, 0, a, b, n, h); + } + + /** + * Constructor for Pentanomial Polynomial Basis (PPB). + * @param m The exponent <code>m</code> of + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param a The coefficient <code>a</code> in the Weierstrass equation + * for non-supersingular elliptic curves over + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param b The coefficient <code>b</code> in the Weierstrass equation + * for non-supersingular elliptic curves over + * <code>F<sub>2<sup>m</sup></sub></code>. + */ + public F2m( + int m, + int k1, + int k2, + int k3, + BigInteger a, + BigInteger b) + { + this(m, k1, k2, k3, a, b, null, null); + } + + /** + * Constructor for Pentanomial Polynomial Basis (PPB). + * @param m The exponent <code>m</code> of + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param a The coefficient <code>a</code> in the Weierstrass equation + * for non-supersingular elliptic curves over + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param b The coefficient <code>b</code> in the Weierstrass equation + * for non-supersingular elliptic curves over + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param n The order of the main subgroup of the elliptic curve. + * @param h The cofactor of the elliptic curve, i.e. + * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>. + */ + public F2m( + int m, + int k1, + int k2, + int k3, + BigInteger a, + BigInteger b, + BigInteger n, + BigInteger h) + { + this.m = m; + this.k1 = k1; + this.k2 = k2; + this.k3 = k3; + this.n = n; + this.h = h; + + if (k1 == 0) + { + throw new IllegalArgumentException("k1 must be > 0"); + } + + if (k2 == 0) + { + if (k3 != 0) + { + throw new IllegalArgumentException("k3 must be 0 if k2 == 0"); + } + } + else + { + if (k2 <= k1) + { + throw new IllegalArgumentException("k2 must be > k1"); + } + + if (k3 <= k2) + { + throw new IllegalArgumentException("k3 must be > k2"); + } + } + + this.a = fromBigInteger(a); + this.b = fromBigInteger(b); + this.infinity = new ECPoint.F2m(this, null, null); + } + + public int getFieldSize() + { + return m; + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x); + } + + public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) + { + return new ECPoint.F2m(this, fromBigInteger(x), fromBigInteger(y), withCompression); + } + + /* (non-Javadoc) + * @see org.bouncycastle.math.ec.ECCurve#decodePoint(byte[]) + */ + public ECPoint decodePoint(byte[] encoded) + { + ECPoint p = null; + + switch (encoded[0]) + { + // infinity + case 0x00: + p = getInfinity(); + break; + // compressed + case 0x02: + case 0x03: + byte[] enc = new byte[encoded.length - 1]; + System.arraycopy(encoded, 1, enc, 0, enc.length); + if (encoded[0] == 0x02) + { + p = decompressPoint(enc, 0); + } + else + { + p = decompressPoint(enc, 1); + } + break; + // uncompressed + case 0x04: + // hybrid + case 0x06: + case 0x07: + byte[] xEnc = new byte[(encoded.length - 1) / 2]; + byte[] yEnc = new byte[(encoded.length - 1) / 2]; + + System.arraycopy(encoded, 1, xEnc, 0, xEnc.length); + System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length); + + p = new ECPoint.F2m(this, + new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, + new BigInteger(1, xEnc)), + new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, + new BigInteger(1, yEnc)), false); + break; + + default: + throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); + } + + return p; + } + + public ECPoint getInfinity() + { + 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 ((n != null) && (h != null) && + ((a.toBigInteger().equals(ECConstants.ZERO)) || + (a.toBigInteger().equals(ECConstants.ONE))) && + (b.toBigInteger().equals(ECConstants.ONE))); + } + + /** + * 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 xEnc + * The encoding of field element xp. + * @param ypBit + * ~yp, an indication bit for the decompression of yp. + * @return the decompressed point. + */ + private ECPoint decompressPoint( + byte[] xEnc, + int ypBit) + { + ECFieldElement xp = new ECFieldElement.F2m( + this.m, this.k1, this.k2, this.k3, new BigInteger(1, xEnc)); + ECFieldElement yp = null; + if (xp.toBigInteger().equals(ECConstants.ZERO)) + { + yp = (ECFieldElement.F2m)b; + for (int i = 0; i < m - 1; i++) + { + yp = yp.square(); + } + } + else + { + ECFieldElement beta = xp.add(a).add( + b.multiply(xp.square().invert())); + ECFieldElement z = solveQuadradicEquation(beta); + if (z == null) + { + throw new RuntimeException("Invalid point compression"); + } + int zBit = 0; + if (z.toBigInteger().testBit(0)) + { + zBit = 1; + } + if (zBit != ypBit) + { + z = z.add(new ECFieldElement.F2m(this.m, this.k1, this.k2, + this.k3, ECConstants.ONE)); + } + yp = xp.multiply(z); + } + + return new ECPoint.F2m(this, xp, yp); + } + + /** + * 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 qradratic equation for. + * @return the solution for <code>z<sup>2</sup> + z = beta</code> or + * <code>null</code> if no solution exists. + */ + private ECFieldElement solveQuadradicEquation(ECFieldElement beta) + { + ECFieldElement zeroElement = new ECFieldElement.F2m( + this.m, this.k1, this.k2, this.k3, ECConstants.ZERO); + + if (beta.toBigInteger().equals(ECConstants.ZERO)) + { + return zeroElement; + } + + ECFieldElement z = null; + ECFieldElement gamma = zeroElement; + + Random rand = new Random(); + do + { + ECFieldElement t = new ECFieldElement.F2m(this.m, this.k1, + this.k2, this.k3, 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.toBigInteger().equals(ECConstants.ZERO)) + { + return null; + } + gamma = z.square().add(z); + } + while (gamma.toBigInteger().equals(ECConstants.ZERO)); + + return z; + } + + public boolean equals( + Object anObject) + { + if (anObject == this) + { + return true; + } + + if (!(anObject instanceof ECCurve.F2m)) + { + return false; + } + + ECCurve.F2m other = (ECCurve.F2m)anObject; + + return (this.m == other.m) && (this.k1 == other.k1) + && (this.k2 == other.k2) && (this.k3 == other.k3) + && a.equals(other.a) && b.equals(other.b); + } + + public int hashCode() + { + return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3; + } + + public int getM() + { + return m; + } + + /** + * Return true if curve uses a Trinomial basis. + * + * @return true if curve Trinomial, false otherwise. + */ + public boolean isTrinomial() + { + return k2 == 0 && k3 == 0; + } + + public int getK1() + { + return k1; + } + + public int getK2() + { + return k2; + } + + public int getK3() + { + return k3; + } + + public BigInteger getN() + { + return n; + } + + public BigInteger getH() + { + return h; + } + } +} diff --git a/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java b/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java new file mode 100644 index 00000000..b5e9aa55 --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java @@ -0,0 +1,1196 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; +import java.util.Random; + +public abstract class ECFieldElement + implements ECConstants +{ + + public abstract BigInteger toBigInteger(); + public abstract String getFieldName(); + public abstract int getFieldSize(); + public abstract ECFieldElement add(ECFieldElement b); + public abstract ECFieldElement subtract(ECFieldElement b); + public abstract ECFieldElement multiply(ECFieldElement b); + public abstract ECFieldElement divide(ECFieldElement b); + public abstract ECFieldElement negate(); + public abstract ECFieldElement square(); + public abstract ECFieldElement invert(); + public abstract ECFieldElement sqrt(); + + public String toString() + { + return this.toBigInteger().toString(2); + } + + public static class Fp extends ECFieldElement + { + BigInteger x; + + BigInteger q; + + public Fp(BigInteger q, BigInteger x) + { + this.x = x; + + if (x.compareTo(q) >= 0) + { + throw new IllegalArgumentException("x value too large in field element"); + } + + this.q = q; + } + + public BigInteger toBigInteger() + { + return x; + } + + /** + * return the field name for this field. + * + * @return the string "Fp". + */ + public String getFieldName() + { + return "Fp"; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public BigInteger getQ() + { + return q; + } + + public ECFieldElement add(ECFieldElement b) + { + return new Fp(q, x.add(b.toBigInteger()).mod(q)); + } + + public ECFieldElement subtract(ECFieldElement b) + { + return new Fp(q, x.subtract(b.toBigInteger()).mod(q)); + } + + public ECFieldElement multiply(ECFieldElement b) + { + return new Fp(q, x.multiply(b.toBigInteger()).mod(q)); + } + + public ECFieldElement divide(ECFieldElement b) + { + return new Fp(q, x.multiply(b.toBigInteger().modInverse(q)).mod(q)); + } + + public ECFieldElement negate() + { + return new Fp(q, x.negate().mod(q)); + } + + public ECFieldElement square() + { + return new Fp(q, x.multiply(x).mod(q)); + } + + public ECFieldElement invert() + { + return new Fp(q, x.modInverse(q)); + } + + // D.1.4 91 + /** + * return a sqrt root - the routine verifies that the calculation + * returns the right value - if none exists it returns null. + */ + public ECFieldElement sqrt() + { + if (!q.testBit(0)) + { + throw new RuntimeException("not done yet"); + } + + // note: even though this class implements ECConstants don't be tempted to + // remove the explicit declaration, some J2ME environments don't cope. + // p mod 4 == 3 + if (q.testBit(1)) + { + // z = g^(u+1) + p, p = 4u + 3 + ECFieldElement z = new Fp(q, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q)); + + return z.square().equals(this) ? z : null; + } + + // p mod 4 == 1 + BigInteger qMinusOne = q.subtract(ECConstants.ONE); + + BigInteger legendreExponent = qMinusOne.shiftRight(1); + if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) + { + return null; + } + + BigInteger u = qMinusOne.shiftRight(2); + BigInteger k = u.shiftLeft(1).add(ECConstants.ONE); + + BigInteger Q = this.x; + BigInteger fourQ = Q.shiftLeft(2).mod(q); + + BigInteger U, V; + Random rand = new Random(); + do + { + BigInteger P; + do + { + P = new BigInteger(q.bitLength(), rand); + } + while (P.compareTo(q) >= 0 + || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne))); + + BigInteger[] result = lucasSequence(q, P, Q, k); + U = result[0]; + V = result[1]; + + if (V.multiply(V).mod(q).equals(fourQ)) + { + // Integer division by 2, mod q + if (V.testBit(0)) + { + V = V.add(q); + } + + V = V.shiftRight(1); + + //assert V.multiply(V).mod(q).equals(x); + + return new ECFieldElement.Fp(q, V); + } + } + while (U.equals(ECConstants.ONE) || U.equals(qMinusOne)); + + return null; + +// BigInteger qMinusOne = q.subtract(ECConstants.ONE); +// BigInteger legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO); +// if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) +// { +// return null; +// } +// +// Random rand = new Random(); +// BigInteger fourX = x.shiftLeft(2); +// +// BigInteger r; +// do +// { +// r = new BigInteger(q.bitLength(), rand); +// } +// while (r.compareTo(q) >= 0 +// || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne))); +// +// BigInteger n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR); +// BigInteger n2 = n1.add(ECConstants.ONE); //q.add(ECConstants.THREE).divide(ECConstants.FOUR); +// +// BigInteger wOne = WOne(r, x, q); +// BigInteger wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q); +// BigInteger twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r); +// +// BigInteger root = twoR.modPow(q.subtract(ECConstants.TWO), q) +// .multiply(x).mod(q) +// .multiply(wSum).mod(q); +// +// return new Fp(q, root); + } + +// private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p) +// { +// if (n.equals(ECConstants.ONE)) +// { +// return wOne; +// } +// boolean isEven = !n.testBit(0); +// n = n.shiftRight(1);//divide(ECConstants.TWO); +// if (isEven) +// { +// BigInteger w = W(n, wOne, p); +// return w.multiply(w).subtract(ECConstants.TWO).mod(p); +// } +// BigInteger w1 = W(n.add(ECConstants.ONE), wOne, p); +// BigInteger w2 = W(n, wOne, p); +// return w1.multiply(w2).subtract(wOne).mod(p); +// } +// +// private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p) +// { +// return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p); +// } + + private static BigInteger[] lucasSequence( + BigInteger p, + BigInteger P, + BigInteger Q, + BigInteger k) + { + int n = k.bitLength(); + int s = k.getLowestSetBit(); + + BigInteger Uh = ECConstants.ONE; + BigInteger Vl = ECConstants.TWO; + BigInteger Vh = P; + BigInteger Ql = ECConstants.ONE; + BigInteger Qh = ECConstants.ONE; + + for (int j = n - 1; j >= s + 1; --j) + { + Ql = Ql.multiply(Qh).mod(p); + + if (k.testBit(j)) + { + Qh = Ql.multiply(Q).mod(p); + Uh = Uh.multiply(Vh).mod(p); + Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); + Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p); + } + else + { + Qh = Ql; + Uh = Uh.multiply(Vl).subtract(Ql).mod(p); + Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); + Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); + } + } + + Ql = Ql.multiply(Qh).mod(p); + Qh = Ql.multiply(Q).mod(p); + Uh = Uh.multiply(Vl).subtract(Ql).mod(p); + Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); + Ql = Ql.multiply(Qh).mod(p); + + for (int j = 1; j <= s; ++j) + { + Uh = Uh.multiply(Vl).mod(p); + Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); + Ql = Ql.multiply(Ql).mod(p); + } + + return new BigInteger[]{ Uh, Vl }; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof ECFieldElement.Fp)) + { + return false; + } + + ECFieldElement.Fp o = (ECFieldElement.Fp)other; + return q.equals(o.q) && x.equals(o.x); + } + + public int hashCode() + { + return q.hashCode() ^ x.hashCode(); + } + } + +// /** +// * Class representing the Elements of the finite field +// * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB) +// * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial +// * basis representations are supported. Gaussian normal basis (GNB) +// * representation is not supported. +// */ +// public static class F2m extends ECFieldElement +// { +// BigInteger x; +// +// /** +// * Indicates gaussian normal basis representation (GNB). Number chosen +// * according to X9.62. GNB is not implemented at present. +// */ +// public static final int GNB = 1; +// +// /** +// * Indicates trinomial basis representation (TPB). Number chosen +// * according to X9.62. +// */ +// public static final int TPB = 2; +// +// /** +// * Indicates pentanomial basis representation (PPB). Number chosen +// * according to X9.62. +// */ +// public static final int PPB = 3; +// +// /** +// * TPB or PPB. +// */ +// private int representation; +// +// /** +// * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. +// */ +// private int m; +// +// /** +// * TPB: The integer <code>k</code> where <code>x<sup>m</sup> + +// * x<sup>k</sup> + 1</code> represents the reduction polynomial +// * <code>f(z)</code>.<br> +// * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + +// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> +// * represents the reduction polynomial <code>f(z)</code>.<br> +// */ +// private int k1; +// +// /** +// * TPB: Always set to <code>0</code><br> +// * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + +// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> +// * represents the reduction polynomial <code>f(z)</code>.<br> +// */ +// private int k2; +// +// /** +// * TPB: Always set to <code>0</code><br> +// * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + +// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> +// * represents the reduction polynomial <code>f(z)</code>.<br> +// */ +// private int k3; +// +// /** +// * Constructor for PPB. +// * @param m The exponent <code>m</code> of +// * <code>F<sub>2<sup>m</sup></sub></code>. +// * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + +// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> +// * represents the reduction polynomial <code>f(z)</code>. +// * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + +// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> +// * represents the reduction polynomial <code>f(z)</code>. +// * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + +// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> +// * represents the reduction polynomial <code>f(z)</code>. +// * @param x The BigInteger representing the value of the field element. +// */ +// public F2m( +// int m, +// int k1, +// int k2, +// int k3, +// BigInteger x) +// { +//// super(x); +// this.x = x; +// +// if ((k2 == 0) && (k3 == 0)) +// { +// this.representation = TPB; +// } +// else +// { +// if (k2 >= k3) +// { +// throw new IllegalArgumentException( +// "k2 must be smaller than k3"); +// } +// if (k2 <= 0) +// { +// throw new IllegalArgumentException( +// "k2 must be larger than 0"); +// } +// this.representation = PPB; +// } +// +// if (x.signum() < 0) +// { +// throw new IllegalArgumentException("x value cannot be negative"); +// } +// +// this.m = m; +// this.k1 = k1; +// this.k2 = k2; +// this.k3 = k3; +// } +// +// /** +// * Constructor for TPB. +// * @param m The exponent <code>m</code> of +// * <code>F<sub>2<sup>m</sup></sub></code>. +// * @param k The integer <code>k</code> where <code>x<sup>m</sup> + +// * x<sup>k</sup> + 1</code> represents the reduction +// * polynomial <code>f(z)</code>. +// * @param x The BigInteger representing the value of the field element. +// */ +// public F2m(int m, int k, BigInteger x) +// { +// // Set k1 to k, and set k2 and k3 to 0 +// this(m, k, 0, 0, x); +// } +// +// public BigInteger toBigInteger() +// { +// return x; +// } +// +// public String getFieldName() +// { +// return "F2m"; +// } +// +// public int getFieldSize() +// { +// return m; +// } +// +// /** +// * Checks, if the ECFieldElements <code>a</code> and <code>b</code> +// * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code> +// * (having the same representation). +// * @param a field element. +// * @param b field element to be compared. +// * @throws IllegalArgumentException if <code>a</code> and <code>b</code> +// * are not elements of the same field +// * <code>F<sub>2<sup>m</sup></sub></code> (having the same +// * representation). +// */ +// public static void checkFieldElements( +// ECFieldElement a, +// ECFieldElement b) +// { +// if ((!(a instanceof F2m)) || (!(b instanceof F2m))) +// { +// throw new IllegalArgumentException("Field elements are not " +// + "both instances of ECFieldElement.F2m"); +// } +// +// if ((a.toBigInteger().signum() < 0) || (b.toBigInteger().signum() < 0)) +// { +// throw new IllegalArgumentException( +// "x value may not be negative"); +// } +// +// ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; +// ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; +// +// if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) +// || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) +// { +// throw new IllegalArgumentException("Field elements are not " +// + "elements of the same field F2m"); +// } +// +// if (aF2m.representation != bF2m.representation) +// { +// // Should never occur +// throw new IllegalArgumentException( +// "One of the field " +// + "elements are not elements has incorrect representation"); +// } +// } +// +// /** +// * Computes <code>z * a(z) mod f(z)</code>, where <code>f(z)</code> is +// * the reduction polynomial of <code>this</code>. +// * @param a The polynomial <code>a(z)</code> to be multiplied by +// * <code>z mod f(z)</code>. +// * @return <code>z * a(z) mod f(z)</code> +// */ +// private BigInteger multZModF(final BigInteger a) +// { +// // Left-shift of a(z) +// BigInteger az = a.shiftLeft(1); +// if (az.testBit(this.m)) +// { +// // If the coefficient of z^m in a(z) equals 1, reduction +// // modulo f(z) is performed: Add f(z) to to a(z): +// // Step 1: Unset mth coeffient of a(z) +// az = az.clearBit(this.m); +// +// // Step 2: Add r(z) to a(z), where r(z) is defined as +// // f(z) = z^m + r(z), and k1, k2, k3 are the positions of +// // the non-zero coefficients in r(z) +// az = az.flipBit(0); +// az = az.flipBit(this.k1); +// if (this.representation == PPB) +// { +// az = az.flipBit(this.k2); +// az = az.flipBit(this.k3); +// } +// } +// return az; +// } +// +// public ECFieldElement add(final ECFieldElement b) +// { +// // No check performed here for performance reasons. Instead the +// // elements involved are checked in ECPoint.F2m +// // checkFieldElements(this, b); +// if (b.toBigInteger().signum() == 0) +// { +// return this; +// } +// +// return new F2m(this.m, this.k1, this.k2, this.k3, this.x.xor(b.toBigInteger())); +// } +// +// public ECFieldElement subtract(final ECFieldElement b) +// { +// // Addition and subtraction are the same in F2m +// return add(b); +// } +// +// +// public ECFieldElement multiply(final ECFieldElement b) +// { +// // Left-to-right shift-and-add field multiplication in F2m +// // Input: Binary polynomials a(z) and b(z) of degree at most m-1 +// // Output: c(z) = a(z) * b(z) mod f(z) +// +// // No check performed here for performance reasons. Instead the +// // elements involved are checked in ECPoint.F2m +// // checkFieldElements(this, b); +// final BigInteger az = this.x; +// BigInteger bz = b.toBigInteger(); +// BigInteger cz; +// +// // Compute c(z) = a(z) * b(z) mod f(z) +// if (az.testBit(0)) +// { +// cz = bz; +// } +// else +// { +// cz = ECConstants.ZERO; +// } +// +// for (int i = 1; i < this.m; i++) +// { +// // b(z) := z * b(z) mod f(z) +// bz = multZModF(bz); +// +// if (az.testBit(i)) +// { +// // If the coefficient of x^i in a(z) equals 1, b(z) is added +// // to c(z) +// cz = cz.xor(bz); +// } +// } +// return new ECFieldElement.F2m(m, this.k1, this.k2, this.k3, cz); +// } +// +// +// public ECFieldElement divide(final ECFieldElement b) +// { +// // There may be more efficient implementations +// ECFieldElement bInv = b.invert(); +// return multiply(bInv); +// } +// +// public ECFieldElement negate() +// { +// // -x == x holds for all x in F2m +// return this; +// } +// +// public ECFieldElement square() +// { +// // Naive implementation, can probably be speeded up using modular +// // reduction +// return multiply(this); +// } +// +// public ECFieldElement invert() +// { +// // Inversion in F2m using the extended Euclidean algorithm +// // Input: A nonzero polynomial a(z) of degree at most m-1 +// // Output: a(z)^(-1) mod f(z) +// +// // u(z) := a(z) +// BigInteger uz = this.x; +// if (uz.signum() <= 0) +// { +// throw new ArithmeticException("x is zero or negative, " + +// "inversion is impossible"); +// } +// +// // v(z) := f(z) +// BigInteger vz = ECConstants.ZERO.setBit(m); +// vz = vz.setBit(0); +// vz = vz.setBit(this.k1); +// if (this.representation == PPB) +// { +// vz = vz.setBit(this.k2); +// vz = vz.setBit(this.k3); +// } +// +// // g1(z) := 1, g2(z) := 0 +// BigInteger g1z = ECConstants.ONE; +// BigInteger g2z = ECConstants.ZERO; +// +// // while u != 1 +// while (!(uz.equals(ECConstants.ZERO))) +// { +// // j := deg(u(z)) - deg(v(z)) +// int j = uz.bitLength() - vz.bitLength(); +// +// // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j +// if (j < 0) +// { +// final BigInteger uzCopy = uz; +// uz = vz; +// vz = uzCopy; +// +// final BigInteger g1zCopy = g1z; +// g1z = g2z; +// g2z = g1zCopy; +// +// j = -j; +// } +// +// // u(z) := u(z) + z^j * v(z) +// // Note, that no reduction modulo f(z) is required, because +// // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) +// // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) +// // = deg(u(z)) +// uz = uz.xor(vz.shiftLeft(j)); +// +// // g1(z) := g1(z) + z^j * g2(z) +// g1z = g1z.xor(g2z.shiftLeft(j)); +//// if (g1z.bitLength() > this.m) { +//// throw new ArithmeticException( +//// "deg(g1z) >= m, g1z = " + g1z.toString(2)); +//// } +// } +// return new ECFieldElement.F2m( +// this.m, this.k1, this.k2, this.k3, g2z); +// } +// +// public ECFieldElement sqrt() +// { +// throw new RuntimeException("Not implemented"); +// } +// +// /** +// * @return the representation of the field +// * <code>F<sub>2<sup>m</sup></sub></code>, either of +// * TPB (trinomial +// * basis representation) or +// * PPB (pentanomial +// * basis representation). +// */ +// public int getRepresentation() +// { +// return this.representation; +// } +// +// /** +// * @return the degree <code>m</code> of the reduction polynomial +// * <code>f(z)</code>. +// */ +// public int getM() +// { +// return this.m; +// } +// +// /** +// * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> + +// * x<sup>k</sup> + 1</code> represents the reduction polynomial +// * <code>f(z)</code>.<br> +// * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + +// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> +// * represents the reduction polynomial <code>f(z)</code>.<br> +// */ +// public int getK1() +// { +// return this.k1; +// } +// +// /** +// * @return TPB: Always returns <code>0</code><br> +// * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + +// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> +// * represents the reduction polynomial <code>f(z)</code>.<br> +// */ +// public int getK2() +// { +// return this.k2; +// } +// +// /** +// * @return TPB: Always set to <code>0</code><br> +// * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + +// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> +// * represents the reduction polynomial <code>f(z)</code>.<br> +// */ +// public int getK3() +// { +// return this.k3; +// } +// +// public boolean equals(Object anObject) +// { +// if (anObject == this) +// { +// return true; +// } +// +// if (!(anObject instanceof ECFieldElement.F2m)) +// { +// return false; +// } +// +// ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; +// +// return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2) +// && (this.k3 == b.k3) +// && (this.representation == b.representation) +// && (this.x.equals(b.x))); +// } +// +// public int hashCode() +// { +// return x.hashCode() ^ m ^ k1 ^ k2 ^ k3; +// } +// } + + /** + * Class representing the Elements of the finite field + * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB) + * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial + * basis representations are supported. Gaussian normal basis (GNB) + * representation is not supported. + */ + public static class F2m extends ECFieldElement + { + /** + * Indicates gaussian normal basis representation (GNB). Number chosen + * according to X9.62. GNB is not implemented at present. + */ + public static final int GNB = 1; + + /** + * Indicates trinomial basis representation (TPB). Number chosen + * according to X9.62. + */ + public static final int TPB = 2; + + /** + * Indicates pentanomial basis representation (PPB). Number chosen + * according to X9.62. + */ + public static final int PPB = 3; + + /** + * TPB or PPB. + */ + private int representation; + + /** + * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>. + */ + private int m; + + /** + * TPB: The integer <code>k</code> where <code>x<sup>m</sup> + + * x<sup>k</sup> + 1</code> represents the reduction polynomial + * <code>f(z)</code>.<br> + * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.<br> + */ + private int k1; + + /** + * TPB: Always set to <code>0</code><br> + * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.<br> + */ + private int k2; + + /** + * TPB: Always set to <code>0</code><br> + * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.<br> + */ + private int k3; + + /** + * The <code>IntArray</code> holding the bits. + */ + private IntArray x; + + /** + * The number of <code>int</code>s required to hold <code>m</code> bits. + */ + private int t; + + /** + * Constructor for PPB. + * @param m The exponent <code>m</code> of + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>. + * @param x The BigInteger representing the value of the field element. + */ + public F2m( + int m, + int k1, + int k2, + int k3, + BigInteger x) + { + // t = m / 32 rounded up to the next integer + t = (m + 31) >> 5; + this.x = new IntArray(x, t); + + if ((k2 == 0) && (k3 == 0)) + { + this.representation = TPB; + } + else + { + if (k2 >= k3) + { + throw new IllegalArgumentException( + "k2 must be smaller than k3"); + } + if (k2 <= 0) + { + throw new IllegalArgumentException( + "k2 must be larger than 0"); + } + this.representation = PPB; + } + + if (x.signum() < 0) + { + throw new IllegalArgumentException("x value cannot be negative"); + } + + this.m = m; + this.k1 = k1; + this.k2 = k2; + this.k3 = k3; + } + + /** + * Constructor for TPB. + * @param m The exponent <code>m</code> of + * <code>F<sub>2<sup>m</sup></sub></code>. + * @param k The integer <code>k</code> where <code>x<sup>m</sup> + + * x<sup>k</sup> + 1</code> represents the reduction + * polynomial <code>f(z)</code>. + * @param x The BigInteger representing the value of the field element. + */ + public F2m(int m, int k, BigInteger x) + { + // Set k1 to k, and set k2 and k3 to 0 + this(m, k, 0, 0, x); + } + + private F2m(int m, int k1, int k2, int k3, IntArray x) + { + t = (m + 31) >> 5; + this.x = x; + this.m = m; + this.k1 = k1; + this.k2 = k2; + this.k3 = k3; + + if ((k2 == 0) && (k3 == 0)) + { + this.representation = TPB; + } + else + { + this.representation = PPB; + } + + } + + public BigInteger toBigInteger() + { + return x.toBigInteger(); + } + + public String getFieldName() + { + return "F2m"; + } + + public int getFieldSize() + { + return m; + } + + /** + * Checks, if the ECFieldElements <code>a</code> and <code>b</code> + * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code> + * (having the same representation). + * @param a field element. + * @param b field element to be compared. + * @throws IllegalArgumentException if <code>a</code> and <code>b</code> + * are not elements of the same field + * <code>F<sub>2<sup>m</sup></sub></code> (having the same + * representation). + */ + public static void checkFieldElements( + ECFieldElement a, + ECFieldElement b) + { + if ((!(a instanceof F2m)) || (!(b instanceof F2m))) + { + throw new IllegalArgumentException("Field elements are not " + + "both instances of ECFieldElement.F2m"); + } + + ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; + ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; + + if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) + || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) + { + throw new IllegalArgumentException("Field elements are not " + + "elements of the same field F2m"); + } + + if (aF2m.representation != bF2m.representation) + { + // Should never occur + throw new IllegalArgumentException( + "One of the field " + + "elements are not elements has incorrect representation"); + } + } + + public ECFieldElement add(final ECFieldElement b) + { + // No check performed here for performance reasons. Instead the + // elements involved are checked in ECPoint.F2m + // checkFieldElements(this, b); + IntArray iarrClone = (IntArray)this.x.clone(); + F2m bF2m = (F2m)b; + iarrClone.addShifted(bF2m.x, 0); + return new F2m(m, k1, k2, k3, iarrClone); + } + + public ECFieldElement subtract(final ECFieldElement b) + { + // Addition and subtraction are the same in F2m + return add(b); + } + + public ECFieldElement multiply(final ECFieldElement b) + { + // Right-to-left comb multiplication in the IntArray + // Input: Binary polynomials a(z) and b(z) of degree at most m-1 + // Output: c(z) = a(z) * b(z) mod f(z) + + // No check performed here for performance reasons. Instead the + // elements involved are checked in ECPoint.F2m + // checkFieldElements(this, b); + F2m bF2m = (F2m)b; + IntArray mult = x.multiply(bF2m.x, m); + mult.reduce(m, new int[]{k1, k2, k3}); + return new F2m(m, k1, k2, k3, mult); + } + + public ECFieldElement divide(final ECFieldElement b) + { + // There may be more efficient implementations + ECFieldElement bInv = b.invert(); + return multiply(bInv); + } + + public ECFieldElement negate() + { + // -x == x holds for all x in F2m + return this; + } + + public ECFieldElement square() + { + IntArray squared = x.square(m); + squared.reduce(m, new int[]{k1, k2, k3}); + return new F2m(m, k1, k2, k3, squared); + } + + + public ECFieldElement invert() + { + // Inversion in F2m using the extended Euclidean algorithm + // Input: A nonzero polynomial a(z) of degree at most m-1 + // Output: a(z)^(-1) mod f(z) + + // u(z) := a(z) + IntArray uz = (IntArray)this.x.clone(); + + // v(z) := f(z) + IntArray vz = new IntArray(t); + vz.setBit(m); + vz.setBit(0); + vz.setBit(this.k1); + if (this.representation == PPB) + { + vz.setBit(this.k2); + vz.setBit(this.k3); + } + + // g1(z) := 1, g2(z) := 0 + IntArray g1z = new IntArray(t); + g1z.setBit(0); + IntArray g2z = new IntArray(t); + + // while u != 0 + while (!uz.isZero()) +// while (uz.getUsedLength() > 0) +// while (uz.bitLength() > 1) + { + // j := deg(u(z)) - deg(v(z)) + int j = uz.bitLength() - vz.bitLength(); + + // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j + if (j < 0) + { + final IntArray uzCopy = uz; + uz = vz; + vz = uzCopy; + + final IntArray g1zCopy = g1z; + g1z = g2z; + g2z = g1zCopy; + + j = -j; + } + + // u(z) := u(z) + z^j * v(z) + // Note, that no reduction modulo f(z) is required, because + // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) + // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) + // = deg(u(z)) + // uz = uz.xor(vz.shiftLeft(j)); + // jInt = n / 32 + int jInt = j >> 5; + // jInt = n % 32 + int jBit = j & 0x1F; + IntArray vzShift = vz.shiftLeft(jBit); + uz.addShifted(vzShift, jInt); + + // g1(z) := g1(z) + z^j * g2(z) +// g1z = g1z.xor(g2z.shiftLeft(j)); + IntArray g2zShift = g2z.shiftLeft(jBit); + g1z.addShifted(g2zShift, jInt); + + } + return new ECFieldElement.F2m( + this.m, this.k1, this.k2, this.k3, g2z); + } + + public ECFieldElement sqrt() + { + throw new RuntimeException("Not implemented"); + } + + /** + * @return the representation of the field + * <code>F<sub>2<sup>m</sup></sub></code>, either of + * TPB (trinomial + * basis representation) or + * PPB (pentanomial + * basis representation). + */ + public int getRepresentation() + { + return this.representation; + } + + /** + * @return the degree <code>m</code> of the reduction polynomial + * <code>f(z)</code>. + */ + public int getM() + { + return this.m; + } + + /** + * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> + + * x<sup>k</sup> + 1</code> represents the reduction polynomial + * <code>f(z)</code>.<br> + * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.<br> + */ + public int getK1() + { + return this.k1; + } + + /** + * @return TPB: Always returns <code>0</code><br> + * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.<br> + */ + public int getK2() + { + return this.k2; + } + + /** + * @return TPB: Always set to <code>0</code><br> + * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> + + * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code> + * represents the reduction polynomial <code>f(z)</code>.<br> + */ + public int getK3() + { + return this.k3; + } + + public boolean equals(Object anObject) + { + if (anObject == this) + { + return true; + } + + if (!(anObject instanceof ECFieldElement.F2m)) + { + return false; + } + + ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; + + return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2) + && (this.k3 == b.k3) + && (this.representation == b.representation) + && (this.x.equals(b.x))); + } + + public int hashCode() + { + return x.hashCode() ^ m ^ k1 ^ k2 ^ k3; + } + } +} diff --git a/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java b/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java new file mode 100644 index 00000000..4d72e33c --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java @@ -0,0 +1,19 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; + +/** + * Interface for classes encapsulating a point multiplication algorithm + * for <code>ECPoint</code>s. + */ +interface ECMultiplier +{ + /** + * Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e. + * <code>p</code> is added <code>k</code> times to itself. + * @param p The <code>ECPoint</code> to be multiplied. + * @param k The factor by which <code>p</code> i multiplied. + * @return <code>p</code> multiplied by <code>k</code>. + */ + ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo); +} diff --git a/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/src/main/java/org/bouncycastle/math/ec/ECPoint.java new file mode 100644 index 00000000..2d38ee4b --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/ECPoint.java @@ -0,0 +1,594 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; + +import org.bouncycastle.asn1.x9.X9IntegerConverter; + +/** + * base class for points on elliptic curves. + */ +public abstract class ECPoint +{ + ECCurve curve; + ECFieldElement x; + ECFieldElement y; + + protected boolean withCompression; + + protected ECMultiplier multiplier = null; + + protected PreCompInfo preCompInfo = null; + + private static X9IntegerConverter converter = new X9IntegerConverter(); + + protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y) + { + this.curve = curve; + this.x = x; + this.y = y; + } + + public ECCurve getCurve() + { + return curve; + } + + public ECFieldElement getX() + { + return x; + } + + public ECFieldElement getY() + { + return y; + } + + public boolean isInfinity() + { + return x == null && y == null; + } + + public boolean isCompressed() + { + return withCompression; + } + + public boolean equals( + Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof ECPoint)) + { + return false; + } + + ECPoint o = (ECPoint)other; + + if (this.isInfinity()) + { + return o.isInfinity(); + } + + return x.equals(o.x) && y.equals(o.y); + } + + public int hashCode() + { + if (this.isInfinity()) + { + return 0; + } + + return x.hashCode() ^ y.hashCode(); + } + +// /** +// * Mainly for testing. Explicitly set the <code>ECMultiplier</code>. +// * @param multiplier The <code>ECMultiplier</code> to be used to multiply +// * this <code>ECPoint</code>. +// */ +// public void setECMultiplier(ECMultiplier multiplier) +// { +// this.multiplier = multiplier; +// } + + /** + * Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s + * to save the precomputation for this <code>ECPoint</code> to store the + * precomputation result for use by subsequent multiplication. + * @param preCompInfo The values precomputed by the + * <code>ECMultiplier</code>. + */ + void setPreCompInfo(PreCompInfo preCompInfo) + { + this.preCompInfo = preCompInfo; + } + + public abstract byte[] getEncoded(); + + public abstract ECPoint add(ECPoint b); + public abstract ECPoint subtract(ECPoint b); + public abstract ECPoint negate(); + public abstract ECPoint twice(); + + /** + * Sets the default <code>ECMultiplier</code>, unless already set. + */ + synchronized void assertECMultiplier() + { + if (this.multiplier == null) + { + this.multiplier = new FpNafMultiplier(); + } + } + + /** + * Multiplies this <code>ECPoint</code> by the given number. + * @param k The multiplicator. + * @return <code>k * this</code>. + */ + public ECPoint multiply(BigInteger k) + { + if (this.isInfinity()) + { + return this; + } + + if (k.signum() == 0) + { + return this.curve.getInfinity(); + } + + assertECMultiplier(); + return this.multiplier.multiply(this, k, preCompInfo); + } + + /** + * Elliptic curve points over Fp + */ + public static class Fp extends ECPoint + { + + /** + * 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 + */ + public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y) + { + this(curve, x, y, false); + } + + /** + * Create a point that encodes with or without point compresion. + * + * @param curve the curve to use + * @param x affine x co-ordinate + * @param y affine y co-ordinate + * @param withCompression if true encode with point compression + */ + public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x != null && y == null) || (x == null && y != null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + /** + * return the field element encoded with point compression. (S 4.3.6) + */ + public byte[] getEncoded() + { + if (this.isInfinity()) + { + return new byte[1]; + } + + int qLength = converter.getByteLength(x); + + if (withCompression) + { + byte PC; + + if (this.getY().toBigInteger().testBit(0)) + { + PC = 0x03; + } + else + { + PC = 0x02; + } + + byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); + byte[] PO = new byte[X.length + 1]; + + PO[0] = PC; + System.arraycopy(X, 0, PO, 1, X.length); + + return PO; + } + else + { + byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); + byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength); + byte[] PO = new byte[X.length + Y.length + 1]; + + PO[0] = 0x04; + System.arraycopy(X, 0, PO, 1, X.length); + System.arraycopy(Y, 0, PO, X.length + 1, Y.length); + + return PO; + } + } + + // B.3 pg 62 + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + + if (b.isInfinity()) + { + return this; + } + + // Check if b = this or b = -this + if (this.x.equals(b.x)) + { + if (this.y.equals(b.y)) + { + // this = b, i.e. this must be doubled + return this.twice(); + } + + // this = -b, i.e. the result is the point at infinity + return this.curve.getInfinity(); + } + + ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x)); + + ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x); + ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); + + return new ECPoint.Fp(curve, x3, y3); + } + + // B.3 pg 62 + public ECPoint twice() + { + if (this.isInfinity()) + { + // Twice identity element (point at infinity) is identity + return this; + } + + if (this.y.toBigInteger().signum() == 0) + { + // if y1 == 0, then (x1, y1) == (x1, -y1) + // and hence this = -this and thus 2(x1, y1) == infinity + return this.curve.getInfinity(); + } + + ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2)); + ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3)); + ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO)); + + ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO)); + ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); + + return new ECPoint.Fp(curve, x3, y3, this.withCompression); + } + + // D.3.2 pg 102 (see Note:) + public ECPoint subtract(ECPoint b) + { + if (b.isInfinity()) + { + return this; + } + + // Add -b + return add(b.negate()); + } + + public ECPoint negate() + { + return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression); + } + + // TODO Uncomment this to enable WNAF algorithm for Fp point multiplication +// /** +// * Sets the default <code>ECMultiplier</code>, unless already set. +// */ +// synchronized void assertECMultiplier() +// { +// if (this.multiplier == null) +// { +// this.multiplier = new WNafMultiplier(); +// } +// } + } + + /** + * Elliptic curve points over F2m + */ + public static class F2m extends ECPoint + { + /** + * @param curve base curve + * @param x x point + * @param y y point + */ + public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y) + { + this(curve, x, y, false); + } + + /** + * @param curve base curve + * @param x x point + * @param y y point + * @param withCompression true if encode with point compression. + */ + public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x != null && y == null) || (x == null && y != null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + if (x != null) + { + // Check if x and y are elements of the same field + ECFieldElement.F2m.checkFieldElements(this.x, this.y); + + // Check if x and a are elements of the same field + if (curve != null) + { + ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA()); + } + } + + this.withCompression = withCompression; + } + + /** + * @deprecated use ECCurve.getInfinity() + * Constructor for point at infinity + */ + public F2m(ECCurve curve) + { + super(curve, null, null); + } + + /* (non-Javadoc) + * @see org.bouncycastle.math.ec.ECPoint#getEncoded() + */ + public byte[] getEncoded() + { + if (this.isInfinity()) + { + return new byte[1]; + } + + int byteCount = converter.getByteLength(this.x); + byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount); + byte[] PO; + + if (withCompression) + { + // See X9.62 4.3.6 and 4.2.2 + PO = new byte[byteCount + 1]; + + PO[0] = 0x02; + // X9.62 4.2.2 and 4.3.6: + // if x = 0 then ypTilde := 0, else ypTilde is the rightmost + // bit of y * x^(-1) + // if ypTilde = 0, then PC := 02, else PC := 03 + // Note: PC === PO[0] + if (!(this.getX().toBigInteger().equals(ECConstants.ZERO))) + { + if (this.getY().multiply(this.getX().invert()) + .toBigInteger().testBit(0)) + { + // ypTilde = 1, hence PC = 03 + PO[0] = 0x03; + } + } + + System.arraycopy(X, 0, PO, 1, byteCount); + } + else + { + byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount); + + PO = new byte[byteCount + byteCount + 1]; + + PO[0] = 0x04; + System.arraycopy(X, 0, PO, 1, byteCount); + System.arraycopy(Y, 0, PO, byteCount + 1, byteCount); + } + + return PO; + } + + /** + * 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.equals(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) + { + ECPoint.F2m other = b; + if (this.isInfinity()) + { + return other; + } + + if (other.isInfinity()) + { + return this; + } + + ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX(); + ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY(); + + // Check if other = this or other = -this + if (this.x.equals(x2)) + { + if (this.y.equals(y2)) + { + // this = other, i.e. this must be doubled + return (ECPoint.F2m)this.twice(); + } + + // this = -other, i.e. the result is the point at infinity + return (ECPoint.F2m)this.curve.getInfinity(); + } + + ECFieldElement.F2m lambda + = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2)); + + ECFieldElement.F2m x3 + = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA()); + + ECFieldElement.F2m y3 + = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y); + + return new ECPoint.F2m(curve, x3, y3, withCompression); + } + + /* (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()); + } + + /* (non-Javadoc) + * @see org.bouncycastle.math.ec.ECPoint#twice() + */ + public ECPoint twice() + { + if (this.isInfinity()) + { + // Twice identity element (point at infinity) is identity + return this; + } + + if (this.x.toBigInteger().signum() == 0) + { + // if x1 == 0, then (x1, y1) == (x1, x1 + y1) + // and hence this = -this and thus 2(x1, y1) == infinity + return this.curve.getInfinity(); + } + + ECFieldElement.F2m lambda + = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x)); + + ECFieldElement.F2m x3 + = (ECFieldElement.F2m)lambda.square().add(lambda). + add(this.curve.getA()); + + ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE); + ECFieldElement.F2m y3 + = (ECFieldElement.F2m)this.x.square().add( + x3.multiply(lambda.add(ONE))); + + return new ECPoint.F2m(this.curve, x3, y3, withCompression); + } + + public ECPoint negate() + { + return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression); + } + + // TODO Uncomment this to enable WNAF/WTNAF F2m point multiplication +// /** +// * Sets the appropriate <code>ECMultiplier</code>, unless already set. +// */ +// synchronized void assertECMultiplier() +// { +// if (this.multiplier == null) +// { +// if (((ECCurve.F2m)(this.curve)).isKoblitz()) +// { +// this.multiplier = new WTauNafMultiplier(); +// } +// else +// { +// this.multiplier = new WNafMultiplier(); +// } +// } +// } + } +} diff --git a/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java b/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java new file mode 100644 index 00000000..35e601d5 --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java @@ -0,0 +1,39 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; + +/** + * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm. + */ +class FpNafMultiplier implements ECMultiplier +{ + /** + * D.3.2 pg 101 + * @see org.bouncycastle.math.ec.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger) + */ + public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo) + { + // TODO Probably should try to add this + // BigInteger e = k.mod(n); // n == order of p + BigInteger e = k; + BigInteger h = e.multiply(BigInteger.valueOf(3)); + + ECPoint neg = p.negate(); + ECPoint R = p; + + for (int i = h.bitLength() - 2; i > 0; --i) + { + R = R.twice(); + + boolean hBit = h.testBit(i); + boolean eBit = e.testBit(i); + + if (hBit != eBit) + { + R = R.add(hBit ? p : neg); + } + } + + return R; + } +} diff --git a/src/main/java/org/bouncycastle/math/ec/IntArray.java b/src/main/java/org/bouncycastle/math/ec/IntArray.java new file mode 100644 index 00000000..ead38c48 --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/IntArray.java @@ -0,0 +1,518 @@ +package org.bouncycastle.math.ec; + +import org.bouncycastle.util.Arrays; + +import java.math.BigInteger; + +class IntArray +{ + // TODO make m fixed for the IntArray, and hence compute T once and for all + + private int[] m_ints; + + public IntArray(int intLen) + { + m_ints = new int[intLen]; + } + + public IntArray(int[] ints) + { + m_ints = ints; + } + + public IntArray(BigInteger bigInt) + { + this(bigInt, 0); + } + + public IntArray(BigInteger bigInt, int minIntLen) + { + if (bigInt.signum() == -1) + { + throw new IllegalArgumentException("Only positive Integers allowed"); + } + if (bigInt.equals(ECConstants.ZERO)) + { + m_ints = new int[] { 0 }; + return; + } + + byte[] barr = bigInt.toByteArray(); + int barrLen = barr.length; + int barrStart = 0; + if (barr[0] == 0) + { + // First byte is 0 to enforce highest (=sign) bit is zero. + // In this case ignore barr[0]. + barrLen--; + barrStart = 1; + } + int intLen = (barrLen + 3) / 4; + if (intLen < minIntLen) + { + m_ints = new int[minIntLen]; + } + else + { + m_ints = new int[intLen]; + } + + int iarrJ = intLen - 1; + int rem = barrLen % 4 + barrStart; + int temp = 0; + int barrI = barrStart; + if (barrStart < rem) + { + for (; barrI < rem; barrI++) + { + temp <<= 8; + int barrBarrI = barr[barrI]; + if (barrBarrI < 0) + { + barrBarrI += 256; + } + temp |= barrBarrI; + } + m_ints[iarrJ--] = temp; + } + + for (; iarrJ >= 0; iarrJ--) + { + temp = 0; + for (int i = 0; i < 4; i++) + { + temp <<= 8; + int barrBarrI = barr[barrI++]; + if (barrBarrI < 0) + { + barrBarrI += 256; + } + temp |= barrBarrI; + } + m_ints[iarrJ] = temp; + } + } + + public boolean isZero() + { + return m_ints.length == 0 + || (m_ints[0] == 0 && getUsedLength() == 0); + } + + public int getUsedLength() + { + int highestIntPos = m_ints.length; + + if (highestIntPos < 1) + { + return 0; + } + + // Check if first element will act as sentinel + if (m_ints[0] != 0) + { + while (m_ints[--highestIntPos] == 0) + { + } + return highestIntPos + 1; + } + + do + { + if (m_ints[--highestIntPos] != 0) + { + return highestIntPos + 1; + } + } + while (highestIntPos > 0); + + return 0; + } + + public int bitLength() + { + // JDK 1.5: see Integer.numberOfLeadingZeros() + int intLen = getUsedLength(); + if (intLen == 0) + { + return 0; + } + + int last = intLen - 1; + int highest = m_ints[last]; + int bits = (last << 5) + 1; + + // A couple of binary search steps + if ((highest & 0xffff0000) != 0) + { + if ((highest & 0xff000000) != 0) + { + bits += 24; + highest >>>= 24; + } + else + { + bits += 16; + highest >>>= 16; + } + } + else if (highest > 0x000000ff) + { + bits += 8; + highest >>>= 8; + } + + while (highest != 1) + { + ++bits; + highest >>>= 1; + } + + return bits; + } + + private int[] resizedInts(int newLen) + { + int[] newInts = new int[newLen]; + int oldLen = m_ints.length; + int copyLen = oldLen < newLen ? oldLen : newLen; + System.arraycopy(m_ints, 0, newInts, 0, copyLen); + return newInts; + } + + public BigInteger toBigInteger() + { + int usedLen = getUsedLength(); + if (usedLen == 0) + { + return ECConstants.ZERO; + } + + int highestInt = m_ints[usedLen - 1]; + byte[] temp = new byte[4]; + int barrI = 0; + boolean trailingZeroBytesDone = false; + for (int j = 3; j >= 0; j--) + { + byte thisByte = (byte) (highestInt >>> (8 * j)); + if (trailingZeroBytesDone || (thisByte != 0)) + { + trailingZeroBytesDone = true; + temp[barrI++] = thisByte; + } + } + + int barrLen = 4 * (usedLen - 1) + barrI; + byte[] barr = new byte[barrLen]; + for (int j = 0; j < barrI; j++) + { + barr[j] = temp[j]; + } + // Highest value int is done now + + for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) + { + for (int j = 3; j >= 0; j--) + { + barr[barrI++] = (byte) (m_ints[iarrJ] >>> (8 * j)); + } + } + return new BigInteger(1, barr); + } + + public void shiftLeft() + { + int usedLen = getUsedLength(); + if (usedLen == 0) + { + return; + } + if (m_ints[usedLen - 1] < 0) + { + // highest bit of highest used byte is set, so shifting left will + // make the IntArray one byte longer + usedLen++; + if (usedLen > m_ints.length) + { + // make the m_ints one byte longer, because we need one more + // byte which is not available in m_ints + m_ints = resizedInts(m_ints.length + 1); + } + } + + boolean carry = false; + for (int i = 0; i < usedLen; i++) + { + // nextCarry is true if highest bit is set + boolean nextCarry = m_ints[i] < 0; + m_ints[i] <<= 1; + if (carry) + { + // set lowest bit + m_ints[i] |= 1; + } + carry = nextCarry; + } + } + + public IntArray shiftLeft(int n) + { + int usedLen = getUsedLength(); + if (usedLen == 0) + { + return this; + } + + if (n == 0) + { + return this; + } + + if (n > 31) + { + throw new IllegalArgumentException("shiftLeft() for max 31 bits " + + ", " + n + "bit shift is not possible"); + } + + int[] newInts = new int[usedLen + 1]; + + int nm32 = 32 - n; + newInts[0] = m_ints[0] << n; + for (int i = 1; i < usedLen; i++) + { + newInts[i] = (m_ints[i] << n) | (m_ints[i - 1] >>> nm32); + } + newInts[usedLen] = m_ints[usedLen - 1] >>> nm32; + + return new IntArray(newInts); + } + + public void addShifted(IntArray other, int shift) + { + int usedLenOther = other.getUsedLength(); + int newMinUsedLen = usedLenOther + shift; + if (newMinUsedLen > m_ints.length) + { + m_ints = resizedInts(newMinUsedLen); + //System.out.println("Resize required"); + } + + for (int i = 0; i < usedLenOther; i++) + { + m_ints[i + shift] ^= other.m_ints[i]; + } + } + + public int getLength() + { + return m_ints.length; + } + + public boolean testBit(int n) + { + // theInt = n / 32 + int theInt = n >> 5; + // theBit = n % 32 + int theBit = n & 0x1F; + int tester = 1 << theBit; + return ((m_ints[theInt] & tester) != 0); + } + + public void flipBit(int n) + { + // theInt = n / 32 + int theInt = n >> 5; + // theBit = n % 32 + int theBit = n & 0x1F; + int flipper = 1 << theBit; + m_ints[theInt] ^= flipper; + } + + public void setBit(int n) + { + // theInt = n / 32 + int theInt = n >> 5; + // theBit = n % 32 + int theBit = n & 0x1F; + int setter = 1 << theBit; + m_ints[theInt] |= setter; + } + + public IntArray multiply(IntArray other, int m) + { + // Lenght of c is 2m bits rounded up to the next int (32 bit) + int t = (m + 31) >> 5; + if (m_ints.length < t) + { + m_ints = resizedInts(t); + } + + IntArray b = new IntArray(other.resizedInts(other.getLength() + 1)); + IntArray c = new IntArray((m + m + 31) >> 5); + // IntArray c = new IntArray(t + t); + int testBit = 1; + for (int k = 0; k < 32; k++) + { + for (int j = 0; j < t; j++) + { + if ((m_ints[j] & testBit) != 0) + { + // The kth bit of m_ints[j] is set + c.addShifted(b, j); + } + } + testBit <<= 1; + b.shiftLeft(); + } + return c; + } + + // public IntArray multiplyLeftToRight(IntArray other, int m) { + // // Lenght of c is 2m bits rounded up to the next int (32 bit) + // int t = (m + 31) / 32; + // if (m_ints.length < t) { + // m_ints = resizedInts(t); + // } + // + // IntArray b = new IntArray(other.resizedInts(other.getLength() + 1)); + // IntArray c = new IntArray((m + m + 31) / 32); + // // IntArray c = new IntArray(t + t); + // int testBit = 1 << 31; + // for (int k = 31; k >= 0; k--) { + // for (int j = 0; j < t; j++) { + // if ((m_ints[j] & testBit) != 0) { + // // The kth bit of m_ints[j] is set + // c.addShifted(b, j); + // } + // } + // testBit >>>= 1; + // if (k > 0) { + // c.shiftLeft(); + // } + // } + // return c; + // } + + // TODO note, redPol.length must be 3 for TPB and 5 for PPB + public void reduce(int m, int[] redPol) + { + for (int i = m + m - 2; i >= m; i--) + { + if (testBit(i)) + { + int bit = i - m; + flipBit(bit); + flipBit(i); + int l = redPol.length; + while (--l >= 0) + { + flipBit(redPol[l] + bit); + } + } + } + m_ints = resizedInts((m + 31) >> 5); + } + + public IntArray square(int m) + { + // TODO make the table static final + final int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40, + 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 }; + + int t = (m + 31) >> 5; + if (m_ints.length < t) + { + m_ints = resizedInts(t); + } + + IntArray c = new IntArray(t + t); + + // TODO twice the same code, put in separate private method + for (int i = 0; i < t; i++) + { + int v0 = 0; + for (int j = 0; j < 4; j++) + { + v0 = v0 >>> 8; + int u = (m_ints[i] >>> (j * 4)) & 0xF; + int w = table[u] << 24; + v0 |= w; + } + c.m_ints[i + i] = v0; + + v0 = 0; + int upper = m_ints[i] >>> 16; + for (int j = 0; j < 4; j++) + { + v0 = v0 >>> 8; + int u = (upper >>> (j * 4)) & 0xF; + int w = table[u] << 24; + v0 |= w; + } + c.m_ints[i + i + 1] = v0; + } + return c; + } + + public boolean equals(Object o) + { + if (!(o instanceof IntArray)) + { + return false; + } + IntArray other = (IntArray) o; + int usedLen = getUsedLength(); + if (other.getUsedLength() != usedLen) + { + return false; + } + for (int i = 0; i < usedLen; i++) + { + if (m_ints[i] != other.m_ints[i]) + { + return false; + } + } + return true; + } + + public int hashCode() + { + int usedLen = getUsedLength(); + int hash = 1; + for (int i = 0; i < usedLen; i++) + { + hash = hash * 31 + m_ints[i]; + } + return hash; + } + + public Object clone() + { + return new IntArray(Arrays.clone(m_ints)); + } + + public String toString() + { + int usedLen = getUsedLength(); + if (usedLen == 0) + { + return "0"; + } + + StringBuffer sb = new StringBuffer(Integer + .toBinaryString(m_ints[usedLen - 1])); + for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) + { + String hexString = Integer.toBinaryString(m_ints[iarrJ]); + + // Add leading zeroes, except for highest significant int + for (int i = hexString.length(); i < 8; i++) + { + hexString = "0" + hexString; + } + sb.append(hexString); + } + return sb.toString(); + } +} diff --git a/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java b/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java new file mode 100644 index 00000000..804dcf74 --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java @@ -0,0 +1,10 @@ +package org.bouncycastle.math.ec; + +/** + * Interface for classes storing precomputation data for multiplication + * algorithms. Used as a Memento (see GOF patterns) for + * <code>WNafMultiplier</code>. + */ +interface PreCompInfo +{ +} diff --git a/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java b/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java new file mode 100644 index 00000000..96e666d1 --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java @@ -0,0 +1,253 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; + +/** + * Class representing a simple version of a big decimal. A + * <code>SimpleBigDecimal</code> is basically a + * {@link java.math.BigInteger BigInteger} with a few digits on the right of + * the decimal point. The number of (binary) digits on the right of the decimal + * point is called the <code>scale</code> of the <code>SimpleBigDecimal</code>. + * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted + * automatically, but must be set manually. All <code>SimpleBigDecimal</code>s + * taking part in the same arithmetic operation must have equal scale. The + * result of a multiplication of two <code>SimpleBigDecimal</code>s returns a + * <code>SimpleBigDecimal</code> with double scale. + */ +class SimpleBigDecimal + //extends Number // not in J2ME - add compatibility class? +{ + private static final long serialVersionUID = 1L; + + private final BigInteger bigInt; + private final int scale; + + /** + * Returns a <code>SimpleBigDecimal</code> representing the same numerical + * value as <code>value</code>. + * @param value The value of the <code>SimpleBigDecimal</code> to be + * created. + * @param scale The scale of the <code>SimpleBigDecimal</code> to be + * created. + * @return The such created <code>SimpleBigDecimal</code>. + */ + public static SimpleBigDecimal getInstance(BigInteger value, int scale) + { + return new SimpleBigDecimal(value.shiftLeft(scale), scale); + } + + /** + * Constructor for <code>SimpleBigDecimal</code>. The value of the + * constructed <code>SimpleBigDecimal</code> equals <code>bigInt / + * 2<sup>scale</sup></code>. + * @param bigInt The <code>bigInt</code> value parameter. + * @param scale The scale of the constructed <code>SimpleBigDecimal</code>. + */ + public SimpleBigDecimal(BigInteger bigInt, int scale) + { + if (scale < 0) + { + throw new IllegalArgumentException("scale may not be negative"); + } + + this.bigInt = bigInt; + this.scale = scale; + } + + private SimpleBigDecimal(SimpleBigDecimal limBigDec) + { + bigInt = limBigDec.bigInt; + scale = limBigDec.scale; + } + + private void checkScale(SimpleBigDecimal b) + { + if (scale != b.scale) + { + throw new IllegalArgumentException("Only SimpleBigDecimal of " + + "same scale allowed in arithmetic operations"); + } + } + + public SimpleBigDecimal adjustScale(int newScale) + { + if (newScale < 0) + { + throw new IllegalArgumentException("scale may not be negative"); + } + + if (newScale == scale) + { + return new SimpleBigDecimal(this); + } + + return new SimpleBigDecimal(bigInt.shiftLeft(newScale - scale), + newScale); + } + + public SimpleBigDecimal add(SimpleBigDecimal b) + { + checkScale(b); + return new SimpleBigDecimal(bigInt.add(b.bigInt), scale); + } + + public SimpleBigDecimal add(BigInteger b) + { + return new SimpleBigDecimal(bigInt.add(b.shiftLeft(scale)), scale); + } + + public SimpleBigDecimal negate() + { + return new SimpleBigDecimal(bigInt.negate(), scale); + } + + public SimpleBigDecimal subtract(SimpleBigDecimal b) + { + return add(b.negate()); + } + + public SimpleBigDecimal subtract(BigInteger b) + { + return new SimpleBigDecimal(bigInt.subtract(b.shiftLeft(scale)), + scale); + } + + public SimpleBigDecimal multiply(SimpleBigDecimal b) + { + checkScale(b); + return new SimpleBigDecimal(bigInt.multiply(b.bigInt), scale + scale); + } + + public SimpleBigDecimal multiply(BigInteger b) + { + return new SimpleBigDecimal(bigInt.multiply(b), scale); + } + + public SimpleBigDecimal divide(SimpleBigDecimal b) + { + checkScale(b); + BigInteger dividend = bigInt.shiftLeft(scale); + return new SimpleBigDecimal(dividend.divide(b.bigInt), scale); + } + + public SimpleBigDecimal divide(BigInteger b) + { + return new SimpleBigDecimal(bigInt.divide(b), scale); + } + + public SimpleBigDecimal shiftLeft(int n) + { + return new SimpleBigDecimal(bigInt.shiftLeft(n), scale); + } + + public int compareTo(SimpleBigDecimal val) + { + checkScale(val); + return bigInt.compareTo(val.bigInt); + } + + public int compareTo(BigInteger val) + { + return bigInt.compareTo(val.shiftLeft(scale)); + } + + public BigInteger floor() + { + return bigInt.shiftRight(scale); + } + + public BigInteger round() + { + SimpleBigDecimal oneHalf = new SimpleBigDecimal(ECConstants.ONE, 1); + return add(oneHalf.adjustScale(scale)).floor(); + } + + public int intValue() + { + return floor().intValue(); + } + + public long longValue() + { + return floor().longValue(); + } + /* NON-J2ME compliant. + public double doubleValue() + { + return Double.valueOf(toString()).doubleValue(); + } + + public float floatValue() + { + return Float.valueOf(toString()).floatValue(); + } + */ + public int getScale() + { + return scale; + } + + public String toString() + { + if (scale == 0) + { + return bigInt.toString(); + } + + BigInteger floorBigInt = floor(); + + BigInteger fract = bigInt.subtract(floorBigInt.shiftLeft(scale)); + if (bigInt.signum() == -1) + { + fract = ECConstants.ONE.shiftLeft(scale).subtract(fract); + } + + if ((floorBigInt.signum() == -1) && (!(fract.equals(ECConstants.ZERO)))) + { + floorBigInt = floorBigInt.add(ECConstants.ONE); + } + String leftOfPoint = floorBigInt.toString(); + + char[] fractCharArr = new char[scale]; + String fractStr = fract.toString(2); + int fractLen = fractStr.length(); + int zeroes = scale - fractLen; + for (int i = 0; i < zeroes; i++) + { + fractCharArr[i] = '0'; + } + for (int j = 0; j < fractLen; j++) + { + fractCharArr[zeroes + j] = fractStr.charAt(j); + } + String rightOfPoint = new String(fractCharArr); + + StringBuffer sb = new StringBuffer(leftOfPoint); + sb.append("."); + sb.append(rightOfPoint); + + return sb.toString(); + } + + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + + if (!(o instanceof SimpleBigDecimal)) + { + return false; + } + + SimpleBigDecimal other = (SimpleBigDecimal)o; + return ((bigInt.equals(other.bigInt)) && (scale == other.scale)); + } + + public int hashCode() + { + return bigInt.hashCode() ^ scale; + } + +} diff --git a/src/main/java/org/bouncycastle/math/ec/Tnaf.java b/src/main/java/org/bouncycastle/math/ec/Tnaf.java new file mode 100644 index 00000000..af4355f3 --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/Tnaf.java @@ -0,0 +1,844 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; + +/** + * Class holding methods for point multiplication based on the window + * τ-adic nonadjacent form (WTNAF). The algorithms are based on the + * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves" + * by Jerome A. Solinas. The paper first appeared in the Proceedings of + * Crypto 1997. + */ +class Tnaf +{ + private static final BigInteger MINUS_ONE = ECConstants.ONE.negate(); + private static final BigInteger MINUS_TWO = ECConstants.TWO.negate(); + private static final BigInteger MINUS_THREE = ECConstants.THREE.negate(); + + /** + * The window width of WTNAF. The standard value of 4 is slightly less + * than optimal for running time, but keeps space requirements for + * precomputation low. For typical curves, a value of 5 or 6 results in + * a better running time. When changing this value, the + * <code>α<sub>u</sub></code>'s must be computed differently, see + * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson, + * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004, + * p. 121-122 + */ + public static final byte WIDTH = 4; + + /** + * 2<sup>4</sup> + */ + public static final byte POW_2_WIDTH = 16; + + /** + * The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array + * of <code>ZTauElement</code>s. + */ + public static final ZTauElement[] alpha0 = { + null, + new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null, + new ZTauElement(MINUS_THREE, MINUS_ONE), null, + new ZTauElement(MINUS_ONE, MINUS_ONE), null, + new ZTauElement(ECConstants.ONE, MINUS_ONE), null + }; + + /** + * The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array + * of TNAFs. + */ + public static final byte[][] alpha0Tnaf = { + null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, 1} + }; + + /** + * The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array + * of <code>ZTauElement</code>s. + */ + public static final ZTauElement[] alpha1 = {null, + new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null, + new ZTauElement(MINUS_THREE, ECConstants.ONE), null, + new ZTauElement(MINUS_ONE, ECConstants.ONE), null, + new ZTauElement(ECConstants.ONE, ECConstants.ONE), null + }; + + /** + * The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array + * of TNAFs. + */ + public static final byte[][] alpha1Tnaf = { + null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, -1} + }; + + /** + * Computes the norm of an element <code>λ</code> of + * <code><b>Z</b>[τ]</code>. + * @param mu The parameter <code>μ</code> of the elliptic curve. + * @param lambda The element <code>λ</code> of + * <code><b>Z</b>[τ]</code>. + * @return The norm of <code>λ</code>. + */ + public static BigInteger norm(final byte mu, ZTauElement lambda) + { + BigInteger norm; + + // s1 = u^2 + BigInteger s1 = lambda.u.multiply(lambda.u); + + // s2 = u * v + BigInteger s2 = lambda.u.multiply(lambda.v); + + // s3 = 2 * v^2 + BigInteger s3 = lambda.v.multiply(lambda.v).shiftLeft(1); + + if (mu == 1) + { + norm = s1.add(s2).add(s3); + } + else if (mu == -1) + { + norm = s1.subtract(s2).add(s3); + } + else + { + throw new IllegalArgumentException("mu must be 1 or -1"); + } + + return norm; + } + + /** + * Computes the norm of an element <code>λ</code> of + * <code><b>R</b>[τ]</code>, where <code>λ = u + vτ</code> + * and <code>u</code> and <code>u</code> are real numbers (elements of + * <code><b>R</b></code>). + * @param mu The parameter <code>μ</code> of the elliptic curve. + * @param u The real part of the element <code>λ</code> of + * <code><b>R</b>[τ]</code>. + * @param v The <code>τ</code>-adic part of the element + * <code>λ</code> of <code><b>R</b>[τ]</code>. + * @return The norm of <code>λ</code>. + */ + public static SimpleBigDecimal norm(final byte mu, SimpleBigDecimal u, + SimpleBigDecimal v) + { + SimpleBigDecimal norm; + + // s1 = u^2 + SimpleBigDecimal s1 = u.multiply(u); + + // s2 = u * v + SimpleBigDecimal s2 = u.multiply(v); + + // s3 = 2 * v^2 + SimpleBigDecimal s3 = v.multiply(v).shiftLeft(1); + + if (mu == 1) + { + norm = s1.add(s2).add(s3); + } + else if (mu == -1) + { + norm = s1.subtract(s2).add(s3); + } + else + { + throw new IllegalArgumentException("mu must be 1 or -1"); + } + + return norm; + } + + /** + * Rounds an element <code>λ</code> of <code><b>R</b>[τ]</code> + * to an element of <code><b>Z</b>[τ]</code>, such that their difference + * has minimal norm. <code>λ</code> is given as + * <code>λ = λ<sub>0</sub> + λ<sub>1</sub>τ</code>. + * @param lambda0 The component <code>λ<sub>0</sub></code>. + * @param lambda1 The component <code>λ<sub>1</sub></code>. + * @param mu The parameter <code>μ</code> of the elliptic curve. Must + * equal 1 or -1. + * @return The rounded element of <code><b>Z</b>[τ]</code>. + * @throws IllegalArgumentException if <code>lambda0</code> and + * <code>lambda1</code> do not have same scale. + */ + public static ZTauElement round(SimpleBigDecimal lambda0, + SimpleBigDecimal lambda1, byte mu) + { + int scale = lambda0.getScale(); + if (lambda1.getScale() != scale) + { + throw new IllegalArgumentException("lambda0 and lambda1 do not " + + "have same scale"); + } + + if (!((mu == 1) || (mu == -1))) + { + throw new IllegalArgumentException("mu must be 1 or -1"); + } + + BigInteger f0 = lambda0.round(); + BigInteger f1 = lambda1.round(); + + SimpleBigDecimal eta0 = lambda0.subtract(f0); + SimpleBigDecimal eta1 = lambda1.subtract(f1); + + // eta = 2*eta0 + mu*eta1 + SimpleBigDecimal eta = eta0.add(eta0); + if (mu == 1) + { + eta = eta.add(eta1); + } + else + { + // mu == -1 + eta = eta.subtract(eta1); + } + + // check1 = eta0 - 3*mu*eta1 + // check2 = eta0 + 4*mu*eta1 + SimpleBigDecimal threeEta1 = eta1.add(eta1).add(eta1); + SimpleBigDecimal fourEta1 = threeEta1.add(eta1); + SimpleBigDecimal check1; + SimpleBigDecimal check2; + if (mu == 1) + { + check1 = eta0.subtract(threeEta1); + check2 = eta0.add(fourEta1); + } + else + { + // mu == -1 + check1 = eta0.add(threeEta1); + check2 = eta0.subtract(fourEta1); + } + + byte h0 = 0; + byte h1 = 0; + + // if eta >= 1 + if (eta.compareTo(ECConstants.ONE) >= 0) + { + if (check1.compareTo(MINUS_ONE) < 0) + { + h1 = mu; + } + else + { + h0 = 1; + } + } + else + { + // eta < 1 + if (check2.compareTo(ECConstants.TWO) >= 0) + { + h1 = mu; + } + } + + // if eta < -1 + if (eta.compareTo(MINUS_ONE) < 0) + { + if (check1.compareTo(ECConstants.ONE) >= 0) + { + h1 = (byte)-mu; + } + else + { + h0 = -1; + } + } + else + { + // eta >= -1 + if (check2.compareTo(MINUS_TWO) < 0) + { + h1 = (byte)-mu; + } + } + + BigInteger q0 = f0.add(BigInteger.valueOf(h0)); + BigInteger q1 = f1.add(BigInteger.valueOf(h1)); + return new ZTauElement(q0, q1); + } + + /** + * Approximate division by <code>n</code>. For an integer + * <code>k</code>, the value <code>λ = s k / n</code> is + * computed to <code>c</code> bits of accuracy. + * @param k The parameter <code>k</code>. + * @param s The curve parameter <code>s<sub>0</sub></code> or + * <code>s<sub>1</sub></code>. + * @param vm The Lucas Sequence element <code>V<sub>m</sub></code>. + * @param a The parameter <code>a</code> of the elliptic curve. + * @param m The bit length of the finite field + * <code><b>F</b><sub>m</sub></code>. + * @param c The number of bits of accuracy, i.e. the scale of the returned + * <code>SimpleBigDecimal</code>. + * @return The value <code>λ = s k / n</code> computed to + * <code>c</code> bits of accuracy. + */ + public static SimpleBigDecimal approximateDivisionByN(BigInteger k, + BigInteger s, BigInteger vm, byte a, int m, int c) + { + int _k = (m + 5)/2 + c; + BigInteger ns = k.shiftRight(m - _k - 2 + a); + + BigInteger gs = s.multiply(ns); + + BigInteger hs = gs.shiftRight(m); + + BigInteger js = vm.multiply(hs); + + BigInteger gsPlusJs = gs.add(js); + BigInteger ls = gsPlusJs.shiftRight(_k-c); + if (gsPlusJs.testBit(_k-c-1)) + { + // round up + ls = ls.add(ECConstants.ONE); + } + + return new SimpleBigDecimal(ls, c); + } + + /** + * Computes the <code>τ</code>-adic NAF (non-adjacent form) of an + * element <code>λ</code> of <code><b>Z</b>[τ]</code>. + * @param mu The parameter <code>μ</code> of the elliptic curve. + * @param lambda The element <code>λ</code> of + * <code><b>Z</b>[τ]</code>. + * @return The <code>τ</code>-adic NAF of <code>λ</code>. + */ + public static byte[] tauAdicNaf(byte mu, ZTauElement lambda) + { + if (!((mu == 1) || (mu == -1))) + { + throw new IllegalArgumentException("mu must be 1 or -1"); + } + + BigInteger norm = norm(mu, lambda); + + // Ceiling of log2 of the norm + int log2Norm = norm.bitLength(); + + // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52 + int maxLength = log2Norm > 30 ? log2Norm + 4 : 34; + + // The array holding the TNAF + byte[] u = new byte[maxLength]; + int i = 0; + + // The actual length of the TNAF + int length = 0; + + BigInteger r0 = lambda.u; + BigInteger r1 = lambda.v; + + while(!((r0.equals(ECConstants.ZERO)) && (r1.equals(ECConstants.ZERO)))) + { + // If r0 is odd + if (r0.testBit(0)) + { + u[i] = (byte) ECConstants.TWO.subtract((r0.subtract(r1.shiftLeft(1))).mod(ECConstants.FOUR)).intValue(); + + // r0 = r0 - u[i] + if (u[i] == 1) + { + r0 = r0.clearBit(0); + } + else + { + // u[i] == -1 + r0 = r0.add(ECConstants.ONE); + } + length = i; + } + else + { + u[i] = 0; + } + + BigInteger t = r0; + BigInteger s = r0.shiftRight(1); + if (mu == 1) + { + r0 = r1.add(s); + } + else + { + // mu == -1 + r0 = r1.subtract(s); + } + + r1 = t.shiftRight(1).negate(); + i++; + } + + length++; + + // Reduce the TNAF array to its actual length + byte[] tnaf = new byte[length]; + System.arraycopy(u, 0, tnaf, 0, length); + return tnaf; + } + + /** + * Applies the operation <code>τ()</code> to an + * <code>ECPoint.F2m</code>. + * @param p The ECPoint.F2m to which <code>τ()</code> is applied. + * @return <code>τ(p)</code> + */ + public static ECPoint.F2m tau(ECPoint.F2m p) + { + if (p.isInfinity()) + { + return p; + } + + ECFieldElement x = p.getX(); + ECFieldElement y = p.getY(); + + return new ECPoint.F2m(p.getCurve(), x.square(), y.square(), p.isCompressed()); + } + + /** + * Returns the parameter <code>μ</code> of the elliptic curve. + * @param curve The elliptic curve from which to obtain <code>μ</code>. + * The curve must be a Koblitz curve, i.e. <code>a</code> equals + * <code>0</code> or <code>1</code> and <code>b</code> equals + * <code>1</code>. + * @return <code>μ</code> of the elliptic curve. + * @throws IllegalArgumentException if the given ECCurve is not a Koblitz + * curve. + */ + public static byte getMu(ECCurve.F2m curve) + { + BigInteger a = curve.getA().toBigInteger(); + byte mu; + + if (a.equals(ECConstants.ZERO)) + { + mu = -1; + } + else if (a.equals(ECConstants.ONE)) + { + mu = 1; + } + else + { + throw new IllegalArgumentException("No Koblitz curve (ABC), " + + "TNAF multiplication not possible"); + } + return mu; + } + + /** + * 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 + * <code>V<sub>k</sub></code>. + * @param mu The parameter <code>μ</code> of the elliptic curve. + * @param k The index of the second element of the Lucas Sequence to be + * returned. + * @param doV If set to true, computes <code>V<sub>k-1</sub></code> and + * <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and + * <code>U<sub>k</sub></code>. + * @return An array with 2 elements, containing <code>U<sub>k-1</sub></code> + * and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> + * and <code>V<sub>k</sub></code>. + */ + public static BigInteger[] getLucas(byte mu, int k, boolean doV) + { + if (!((mu == 1) || (mu == -1))) + { + throw new IllegalArgumentException("mu must be 1 or -1"); + } + + BigInteger u0; + BigInteger u1; + BigInteger u2; + + if (doV) + { + u0 = ECConstants.TWO; + u1 = BigInteger.valueOf(mu); + } + else + { + u0 = ECConstants.ZERO; + u1 = ECConstants.ONE; + } + + for (int i = 1; i < k; i++) + { + // u2 = mu*u1 - 2*u0; + BigInteger s = null; + if (mu == 1) + { + s = u1; + } + else + { + // mu == -1 + s = u1.negate(); + } + + u2 = s.subtract(u0.shiftLeft(1)); + u0 = u1; + u1 = u2; +// System.out.println(i + ": " + u2); +// System.out.println(); + } + + BigInteger[] retVal = {u0, u1}; + return retVal; + } + + /** + * Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is + * 4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for + * <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code> + * @param mu The parameter <code>μ</code> of the elliptic curve. + * @param w The window width of the WTNAF. + * @return the auxiliary value <code>t<sub>w</sub></code> + */ + public static BigInteger getTw(byte mu, int w) + { + if (w == 4) + { + if (mu == 1) + { + return BigInteger.valueOf(6); + } + else + { + // mu == -1 + return BigInteger.valueOf(10); + } + } + else + { + // For w <> 4, the values must be computed + BigInteger[] us = getLucas(mu, w, false); + BigInteger twoToW = ECConstants.ZERO.setBit(w); + BigInteger u1invert = us[1].modInverse(twoToW); + BigInteger tw; + tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW); +// System.out.println("mu = " + mu); +// System.out.println("tw = " + tw); + return tw; + } + } + + /** + * Computes the auxiliary values <code>s<sub>0</sub></code> and + * <code>s<sub>1</sub></code> used for partial modular reduction. + * @param curve The elliptic curve for which to compute + * <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>. + * @throws IllegalArgumentException if <code>curve</code> is not a + * Koblitz curve (Anomalous Binary Curve, ABC). + */ + public static BigInteger[] getSi(ECCurve.F2m curve) + { + if (!curve.isKoblitz()) + { + throw new IllegalArgumentException("si is defined for Koblitz curves only"); + } + + int m = curve.getM(); + int a = curve.getA().toBigInteger().intValue(); + byte mu = curve.getMu(); + int h = curve.getH().intValue(); + int index = m + 3 - a; + BigInteger[] ui = getLucas(mu, index, false); + + BigInteger dividend0; + BigInteger dividend1; + if (mu == 1) + { + dividend0 = ECConstants.ONE.subtract(ui[1]); + dividend1 = ECConstants.ONE.subtract(ui[0]); + } + else if (mu == -1) + { + dividend0 = ECConstants.ONE.add(ui[1]); + dividend1 = ECConstants.ONE.add(ui[0]); + } + else + { + throw new IllegalArgumentException("mu must be 1 or -1"); + } + + BigInteger[] si = new BigInteger[2]; + + if (h == 2) + { + si[0] = dividend0.shiftRight(1); + si[1] = dividend1.shiftRight(1).negate(); + } + else if (h == 4) + { + si[0] = dividend0.shiftRight(2); + si[1] = dividend1.shiftRight(2).negate(); + } + else + { + throw new IllegalArgumentException("h (Cofactor) must be 2 or 4"); + } + + return si; + } + + /** + * Partial modular reduction modulo + * <code>(τ<sup>m</sup> - 1)/(τ - 1)</code>. + * @param k The integer to be reduced. + * @param m The bitlength of the underlying finite field. + * @param a The parameter <code>a</code> of the elliptic curve. + * @param s The auxiliary values <code>s<sub>0</sub></code> and + * <code>s<sub>1</sub></code>. + * @param mu The parameter μ of the elliptic curve. + * @param c The precision (number of bits of accuracy) of the partial + * modular reduction. + * @return <code>ρ := k partmod (τ<sup>m</sup> - 1)/(τ - 1)</code> + */ + public static ZTauElement partModReduction(BigInteger k, int m, byte a, + BigInteger[] s, byte mu, byte c) + { + // d0 = s[0] + mu*s[1]; mu is either 1 or -1 + BigInteger d0; + if (mu == 1) + { + d0 = s[0].add(s[1]); + } + else + { + d0 = s[0].subtract(s[1]); + } + + BigInteger[] v = getLucas(mu, m, true); + BigInteger vm = v[1]; + + SimpleBigDecimal lambda0 = approximateDivisionByN( + k, s[0], vm, a, m, c); + + SimpleBigDecimal lambda1 = approximateDivisionByN( + k, s[1], vm, a, m, c); + + ZTauElement q = round(lambda0, lambda1, mu); + + // r0 = n - d0*q0 - 2*s1*q1 + BigInteger r0 = k.subtract(d0.multiply(q.u)).subtract( + BigInteger.valueOf(2).multiply(s[1]).multiply(q.v)); + + // r1 = s1*q0 - s0*q1 + BigInteger r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v)); + + return new ZTauElement(r0, r1); + } + + /** + * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} + * by a <code>BigInteger</code> using the reduced <code>τ</code>-adic + * NAF (RTNAF) method. + * @param p The ECPoint.F2m 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) + { + ECCurve.F2m curve = (ECCurve.F2m) p.getCurve(); + int m = curve.getM(); + byte a = (byte) curve.getA().toBigInteger().intValue(); + byte mu = curve.getMu(); + BigInteger[] s = curve.getSi(); + ZTauElement rho = partModReduction(k, m, a, s, mu, (byte)10); + + return multiplyTnaf(p, rho); + } + + /** + * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} + * 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 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) + { + ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); + byte mu = curve.getMu(); + byte[] u = tauAdicNaf(mu, lambda); + + ECPoint.F2m q = multiplyFromTnaf(p, u); + + return q; + } + + /** + * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} + * 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 u The the TNAF of <code>λ</code>.. + * @return <code>λ * p</code> + */ + public static ECPoint.F2m multiplyFromTnaf(ECPoint.F2m p, byte[] u) + { + ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); + ECPoint.F2m q = (ECPoint.F2m) curve.getInfinity(); + 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) + { + q = (ECPoint.F2m)q.subtractSimple(p); + } + } + return q; + } + + /** + * Computes the <code>[τ]</code>-adic window NAF of an element + * <code>λ</code> of <code><b>Z</b>[τ]</code>. + * @param mu The parameter μ of the elliptic curve. + * @param lambda The element <code>λ</code> of + * <code><b>Z</b>[τ]</code> of which to compute the + * <code>[τ]</code>-adic NAF. + * @param width The window width of the resulting WNAF. + * @param pow2w 2<sup>width</sup>. + * @param tw The auxiliary value <code>t<sub>w</sub></code>. + * @param alpha The <code>α<sub>u</sub></code>'s for the window width. + * @return The <code>[τ]</code>-adic window NAF of + * <code>λ</code>. + */ + public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda, + byte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha) + { + if (!((mu == 1) || (mu == -1))) + { + throw new IllegalArgumentException("mu must be 1 or -1"); + } + + BigInteger norm = norm(mu, lambda); + + // Ceiling of log2 of the norm + int log2Norm = norm.bitLength(); + + // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52 + int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width; + + // The array holding the TNAF + byte[] u = new byte[maxLength]; + + // 2^(width - 1) + BigInteger pow2wMin1 = pow2w.shiftRight(1); + + // Split lambda into two BigIntegers to simplify calculations + BigInteger r0 = lambda.u; + BigInteger r1 = lambda.v; + int i = 0; + + // while lambda <> (0, 0) + while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO)))) + { + // if r0 is odd + if (r0.testBit(0)) + { + // uUnMod = r0 + r1*tw mod 2^width + BigInteger uUnMod + = r0.add(r1.multiply(tw)).mod(pow2w); + + byte uLocal; + // if uUnMod >= 2^(width - 1) + if (uUnMod.compareTo(pow2wMin1) >= 0) + { + uLocal = (byte) uUnMod.subtract(pow2w).intValue(); + } + else + { + uLocal = (byte) uUnMod.intValue(); + } + // uLocal is now in [-2^(width-1), 2^(width-1)-1] + + u[i] = uLocal; + boolean s = true; + if (uLocal < 0) + { + s = false; + uLocal = (byte)-uLocal; + } + // uLocal is now >= 0 + + if (s) + { + r0 = r0.subtract(alpha[uLocal].u); + r1 = r1.subtract(alpha[uLocal].v); + } + else + { + r0 = r0.add(alpha[uLocal].u); + r1 = r1.add(alpha[uLocal].v); + } + } + else + { + u[i] = 0; + } + + BigInteger t = r0; + + if (mu == 1) + { + r0 = r1.add(r0.shiftRight(1)); + } + else + { + // mu == -1 + r0 = r1.subtract(r0.shiftRight(1)); + } + r1 = t.shiftRight(1).negate(); + i++; + } + return u; + } + + /** + * Does the precomputation for WTNAF multiplication. + * @param p The <code>ECPoint</code> for which to do the precomputation. + * @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) + { + 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; + } + + int precompLen = alphaTnaf.length; + for (int i = 3; i < precompLen; i = i + 2) + { + pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]); + } + + return pu; + } +} diff --git a/src/main/java/org/bouncycastle/math/ec/ZTauElement.java b/src/main/java/org/bouncycastle/math/ec/ZTauElement.java new file mode 100644 index 00000000..7402f222 --- /dev/null +++ b/src/main/java/org/bouncycastle/math/ec/ZTauElement.java @@ -0,0 +1,37 @@ +package org.bouncycastle.math.ec; + +import java.math.BigInteger; + +/** + * Class representing an element of <code><b>Z</b>[τ]</code>. Let + * <code>λ</code> be an element of <code><b>Z</b>[τ]</code>. Then + * <code>λ</code> is given as <code>λ = u + vτ</code>. The + * components <code>u</code> and <code>v</code> may be used directly, there + * are no accessor methods. + * Immutable class. + */ +class ZTauElement +{ + /** + * The "real" part of <code>λ</code>. + */ + public final BigInteger u; + + /** + * The "<code>τ</code>-adic" part of <code>λ</code>. + */ + public final BigInteger v; + + /** + * Constructor for an element <code>λ</code> of + * <code><b>Z</b>[τ]</code>. + * @param u The "real" part of <code>λ</code>. + * @param v The "<code>τ</code>-adic" part of + * <code>λ</code>. + */ + public ZTauElement(BigInteger u, BigInteger v) + { + this.u = u; + this.v = v; + } +} |