summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2014-08-07 16:03:01 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2014-08-07 16:03:01 +0000
commit1c91ea67b835e4147503075b510098ec57ec6671 (patch)
tree6c876ccbb5560aa6f9b7d42eeae00495568e5bc4
parentecd1c124e0cc0db8e0e2bffe01177f0abe796bd8 (diff)
parent9c4a275f619a103c2cb54a7b117acfc19611a853 (diff)
downloadandroid_external_bouncycastle-1c91ea67b835e4147503075b510098ec57ec6671.tar.gz
android_external_bouncycastle-1c91ea67b835e4147503075b510098ec57ec6671.tar.bz2
android_external_bouncycastle-1c91ea67b835e4147503075b510098ec57ec6671.zip
am 9c4a275f: am e46fd725: Merge "Upgrade to 1.51"
* commit '9c4a275f619a103c2cb54a7b117acfc19611a853': Upgrade to 1.51
-rw-r--r--NOTICE2
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/selector/MSOutlookKeyIdCalculator.java395
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java10
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java2
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java117
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java9
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java20
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/Recipient.java5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/RecipientOperator.java48
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java16
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/GenericKey.java41
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/InputDecryptor.java29
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/MacCalculator.java34
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java6
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java6
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaDigestCalculatorProviderBuilder.java6
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java78
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java216
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encodable.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encoding.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java166
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java365
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java149
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Object.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java458
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java105
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetStringParser.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java73
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1SequenceParser.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java102
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1SetParser.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java306
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java190
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java155
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java340
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java150
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java452
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERUTCTime.java269
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERUTF8String.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERVisibleString.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java70
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java99
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java192
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java162
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java152
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/BasicConstraints.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java71
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/Time.java70
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extensions.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509NameEntryConverter.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java63
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/SkippingCipher.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/SkippingStreamCipher.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java108
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/StreamCipher.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/EncodableDigest.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java68
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java41
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java48
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java326
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java163
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java91
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java299
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java130
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java22
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java39
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java124
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java42
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java67
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java174
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java35
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java59
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/Pack.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java53
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java52
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java169
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java145
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java37
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/PKCS12BagAttributeCarrierImpl.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java95
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java19
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java87
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java (renamed from bcprov/src/main/java/org/bouncycastle/jcajce/DefaultJcaJceHelper.java)6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java (renamed from bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceHelper.java)5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceUtils.java130
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java (renamed from bcprov/src/main/java/org/bouncycastle/jcajce/NamedJcaJceHelper.java)5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java (renamed from bcprov/src/main/java/org/bouncycastle/jcajce/ProviderJcaJceHelper.java)5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java22
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java37
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPrivateKey.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPublicKey.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPrivateKey.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPublicKey.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/X509SignatureUtil.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java352
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java473
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java871
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java681
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECPointMap.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java57
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java40
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java71
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/GLVMultiplier.java42
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java860
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java320
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ScaleXPointMap.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java49
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java182
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java79
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Field.java177
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java213
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java298
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java80
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java286
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1FieldElement.java190
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java310
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java78
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Field.java178
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java243
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java298
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java80
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java298
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1FieldElement.java273
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java308
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java78
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java179
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java215
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java298
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java80
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java312
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1FieldElement.java189
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java308
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java80
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java295
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1FieldElement.java211
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java309
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java80
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Field.java156
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1FieldElement.java169
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java333
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/endo/ECEndomorphism.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVEndomorphism.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java58
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java59
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/field/ExtensionField.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/field/FiniteField.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/field/FiniteFields.java53
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/field/GF2Polynomial.java42
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/field/GenericPolynomialExtensionField.java62
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/field/Polynomial.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/field/PolynomialExtensionField.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/field/PrimeField.java42
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Mod.java199
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java1038
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java968
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java1182
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java1306
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat384.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat512.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Arrays.java115
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Integers.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Memoable.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Pack.java201
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Strings.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/encoders/Base64.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/encoders/DecoderException.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/encoders/EncoderException.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/encoders/Hex.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/encoders/HexEncoder.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/Streams.java58
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/TeeInputStream.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObject.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/pem/PemReader.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/X509AttributeCertificate.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/X509CertStoreSelector.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/X509Util.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/X509V3CertificateGenerator.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/extension/SubjectKeyIdentifierStructure.java53
-rw-r--r--bouncycastle.config54
-rw-r--r--bouncycastle.version2
-rwxr-xr-ximport_bouncycastle.sh4
-rw-r--r--patches/bcpkix.patch290
-rw-r--r--patches/bcprov.patch1329
287 files changed, 21379 insertions, 6121 deletions
diff --git a/NOTICE b/NOTICE
index b7e58c1..f1591ef 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,4 +1,4 @@
-Copyright (c) 2000-2013 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org)
+Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/selector/MSOutlookKeyIdCalculator.java b/bcpkix/src/main/java/org/bouncycastle/cert/selector/MSOutlookKeyIdCalculator.java
index 3f4e22c..8f6d119 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/selector/MSOutlookKeyIdCalculator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/selector/MSOutlookKeyIdCalculator.java
@@ -4,14 +4,16 @@ import java.io.IOException;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.util.Pack;
class MSOutlookKeyIdCalculator
{
+ // This is less than ideal, but it seems to be the best way of supporting this without exposing SHA-1
+ // as the class is only used to workout the MSOutlook Key ID, you can think of the fact it's SHA-1 as
+ // a coincidence...
static byte[] calculateKeyId(SubjectPublicKeyInfo info)
{
- Digest dig = new SHA1Digest(); // TODO: include definition of SHA-1 here
+ SHA1Digest dig = new SHA1Digest();
byte[] hash = new byte[dig.getDigestSize()];
byte[] spkiEnc = new byte[0];
try
@@ -30,4 +32,391 @@ class MSOutlookKeyIdCalculator
return hash;
}
+
+ private static abstract class GeneralDigest
+ {
+ private static final int BYTE_LENGTH = 64;
+ private byte[] xBuf;
+ private int xBufOff;
+
+ private long byteCount;
+
+ /**
+ * Standard constructor
+ */
+ protected GeneralDigest()
+ {
+ xBuf = new byte[4];
+ xBufOff = 0;
+ }
+
+ /**
+ * Copy constructor. We are using copy constructors in place
+ * of the Object.clone() interface as this interface is not
+ * supported by J2ME.
+ */
+ protected GeneralDigest(GeneralDigest t)
+ {
+ xBuf = new byte[t.xBuf.length];
+
+ copyIn(t);
+ }
+
+ protected void copyIn(GeneralDigest t)
+ {
+ System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
+
+ xBufOff = t.xBufOff;
+ byteCount = t.byteCount;
+ }
+
+ public void update(
+ byte in)
+ {
+ xBuf[xBufOff++] = in;
+
+ if (xBufOff == xBuf.length)
+ {
+ processWord(xBuf, 0);
+ xBufOff = 0;
+ }
+
+ byteCount++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((xBufOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > xBuf.length)
+ {
+ processWord(in, inOff);
+
+ inOff += xBuf.length;
+ len -= xBuf.length;
+ byteCount += xBuf.length;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ public void finish()
+ {
+ long bitLength = (byteCount << 3);
+
+ //
+ // add the pad bytes.
+ //
+ update((byte)128);
+
+ while (xBufOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(bitLength);
+
+ processBlock();
+ }
+
+ public void reset()
+ {
+ byteCount = 0;
+
+ xBufOff = 0;
+ for (int i = 0; i < xBuf.length; i++)
+ {
+ xBuf[i] = 0;
+ }
+ }
+
+ protected abstract void processWord(byte[] in, int inOff);
+
+ protected abstract void processLength(long bitLength);
+
+ protected abstract void processBlock();
+ }
+
+ private static class SHA1Digest
+ extends GeneralDigest
+ {
+ private static final int DIGEST_LENGTH = 20;
+
+ private int H1, H2, H3, H4, H5;
+
+ private int[] X = new int[80];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA1Digest()
+ {
+ reset();
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-1";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ // Note: Inlined for performance
+ // X[xOff] = Pack.bigEndianToInt(in, inOff);
+ int n = in[ inOff] << 24;
+ n |= (in[++inOff] & 0xff) << 16;
+ n |= (in[++inOff] & 0xff) << 8;
+ n |= (in[++inOff] & 0xff);
+ X[xOff] = n;
+
+ if (++xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength >>> 32);
+ X[15] = (int)(bitLength & 0xffffffff);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.intToBigEndian(H1, out, outOff);
+ Pack.intToBigEndian(H2, out, outOff + 4);
+ Pack.intToBigEndian(H3, out, outOff + 8);
+ Pack.intToBigEndian(H4, out, outOff + 12);
+ Pack.intToBigEndian(H5, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+ H5 = 0xc3d2e1f0;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // Additive constants
+ //
+ private static final int Y1 = 0x5a827999;
+ private static final int Y2 = 0x6ed9eba1;
+ private static final int Y3 = 0x8f1bbcdc;
+ private static final int Y4 = 0xca62c1d6;
+
+ private int f(
+ int u,
+ int v,
+ int w)
+ {
+ return ((u & v) | ((~u) & w));
+ }
+
+ private int h(
+ int u,
+ int v,
+ int w)
+ {
+ return (u ^ v ^ w);
+ }
+
+ private int g(
+ int u,
+ int v,
+ int w)
+ {
+ return ((u & v) | (u & w) | (v & w));
+ }
+
+ protected void processBlock()
+ {
+ //
+ // expand 16 word block into 80 word block.
+ //
+ for (int i = 16; i < 80; i++)
+ {
+ int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16];
+ X[i] = t << 1 | t >>> 31;
+ }
+
+ //
+ // set up working variables.
+ //
+ int A = H1;
+ int B = H2;
+ int C = H3;
+ int D = H4;
+ int E = H5;
+
+ //
+ // round 1
+ //
+ int idx = 0;
+
+ for (int j = 0; j < 4; j++)
+ {
+ // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1;
+ C = C << 30 | C >>> 2;
+ }
+
+ //
+ // round 2
+ //
+ for (int j = 0; j < 4; j++)
+ {
+ // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2;
+ C = C << 30 | C >>> 2;
+ }
+
+ //
+ // round 3
+ //
+ for (int j = 0; j < 4; j++)
+ {
+ // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3;
+ C = C << 30 | C >>> 2;
+ }
+
+ //
+ // round 4
+ //
+ for (int j = 0; j <= 3; j++)
+ {
+ // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4;
+ C = C << 30 | C >>> 2;
+ }
+
+
+ H1 += A;
+ H2 += B;
+ H3 += C;
+ H4 += D;
+ H5 += E;
+
+ //
+ // reset start of the buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ X[i] = 0;
+ }
+ }
+ }
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java
index 0c52082..ec4da91 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java
@@ -475,7 +475,7 @@ public class CMSSignedData
* @param signedData the signed data object to be used as a base.
* @param certificates the new certificates to be used.
* @param attrCerts the new attribute certificates to be used.
- * @param crls the new CRLs to be used.
+ * @param revocations the new CRLs to be used - a collection of X509CRLHolder objects, OtherRevocationInfoFormat, or both.
* @return a new signed data object.
* @exception CMSException if there is an error processing the CertStore
*/
@@ -483,7 +483,7 @@ public class CMSSignedData
CMSSignedData signedData,
Store certificates,
Store attrCerts,
- Store crls)
+ Store revocations)
throws CMSException
{
//
@@ -492,7 +492,7 @@ public class CMSSignedData
CMSSignedData cms = new CMSSignedData(signedData);
//
- // replace the certs and crls in the SignedData object
+ // replace the certs and revocations in the SignedData object
//
ASN1Set certSet = null;
ASN1Set crlSet = null;
@@ -518,9 +518,9 @@ public class CMSSignedData
}
}
- if (crls != null)
+ if (revocations != null)
{
- ASN1Set set = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(crls));
+ ASN1Set set = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(revocations));
if (set.size() != 0)
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java
index eea8a1a..5417ce4 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java
@@ -140,7 +140,7 @@ public class CMSSignedDataGenerator
ASN1OctetString octs = null;
- if (content != null)
+ if (content.getContent() != null)
{
ByteArrayOutputStream bOut = null;
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java
index d6126b6..e5f7e9b 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java
@@ -13,6 +13,7 @@ import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.BEROctetStringGenerator;
import org.bouncycastle.asn1.BERSet;
import org.bouncycastle.asn1.DERSet;
@@ -29,6 +30,7 @@ import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.util.Store;
+import org.bouncycastle.util.Strings;
import org.bouncycastle.util.io.Streams;
import org.bouncycastle.util.io.TeeInputStream;
import org.bouncycastle.util.io.TeeOutputStream;
@@ -99,18 +101,37 @@ class CMSUtils
static List getCRLsFromStore(Store crlStore)
throws CMSException
{
- List certs = new ArrayList();
+ List crls = new ArrayList();
try
{
for (Iterator it = crlStore.getMatches(null).iterator(); it.hasNext();)
{
- X509CRLHolder c = (X509CRLHolder)it.next();
-
- certs.add(c.toASN1Structure());
+ Object rev = it.next();
+
+ if (rev instanceof X509CRLHolder)
+ {
+ X509CRLHolder c = (X509CRLHolder)rev;
+
+ crls.add(c.toASN1Structure());
+ }
+ // BEGIN android-removed
+ // else if (rev instanceof OtherRevocationInfoFormat)
+ // {
+ // OtherRevocationInfoFormat infoFormat = OtherRevocationInfoFormat.getInstance(rev);
+ //
+ // validateInfoFormat(infoFormat);
+ //
+ // crls.add(new DERTaggedObject(false, 1, infoFormat));
+ // }
+ // END android-removed
+ else if (rev instanceof ASN1TaggedObject)
+ {
+ crls.add(rev);
+ }
}
- return certs;
+ return crls;
}
catch (ClassCastException e)
{
@@ -119,6 +140,19 @@ class CMSUtils
}
// BEGIN android-removed
+ // private static void validateInfoFormat(OtherRevocationInfoFormat infoFormat)
+ // {
+ // if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(infoFormat.getInfoFormat()))
+ // {
+ // OCSPResponse resp = OCSPResponse.getInstance(infoFormat.getInfo());
+ //
+ // if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
+ // {
+ // throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
+ // }
+ // }
+ // }
+ //
// static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos)
// {
// List others = new ArrayList();
@@ -126,18 +160,10 @@ class CMSUtils
// for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext();)
// {
// ASN1Encodable info = (ASN1Encodable)it.next();
+ // OtherRevocationInfoFormat infoFormat = new OtherRevocationInfoFormat(otherRevocationInfoFormat, info);
+ // validateInfoFormat(infoFormat);
//
- // if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(otherRevocationInfoFormat))
- // {
- // OCSPResponse resp = OCSPResponse.getInstance(info);
- //
- // if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
- // {
- // throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
- // }
- // }
- //
- // others.add(new DERTaggedObject(false, 1, new OtherRevocationInfoFormat(otherRevocationInfoFormat, info)));
+ // others.add(new DERTaggedObject(false, 1, infoFormat));
// }
//
// return others;
@@ -202,7 +228,64 @@ class CMSUtils
throw new CMSException("Malformed content.", e);
}
}
-
+
+ static byte[] getPasswordBytes(int scheme, char[] password)
+ {
+ if (scheme == PasswordRecipient.PKCS5_SCHEME2)
+ {
+ return PKCS5PasswordToBytes(password);
+ }
+
+ return PKCS5PasswordToUTF8Bytes(password);
+ }
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS5 (ascii, no padding)
+ *
+ * @param password a character array representing the password.
+ * @return a byte array representing the password.
+ */
+ private static byte[] PKCS5PasswordToBytes(
+ char[] password)
+ {
+ if (password != null)
+ {
+ byte[] bytes = new byte[password.length];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)password[i];
+ }
+
+ return bytes;
+ }
+ else
+ {
+ return new byte[0];
+ }
+ }
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS5 (UTF-8, no padding)
+ *
+ * @param password a character array representing the password.
+ * @return a byte array representing the password.
+ */
+ private static byte[] PKCS5PasswordToUTF8Bytes(
+ char[] password)
+ {
+ if (password != null)
+ {
+ return Strings.toUTF8ByteArray(password);
+ }
+ else
+ {
+ return new byte[0];
+ }
+ }
+
public static byte[] streamToByteArray(
InputStream in)
throws IOException
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
index a9997a4..f69772d 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
@@ -5,6 +5,7 @@ import java.util.Map;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
// BEGIN android-removed
+// import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
// END android-removed
import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
@@ -66,6 +67,14 @@ public class DefaultCMSSignatureAlgorithmNameGenerator
addEntries(EACObjectIdentifiers.id_TA_RSA_v1_5_SHA_256, "SHA256", "RSA");
addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_1, "SHA1", "RSAandMGF1");
addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_256, "SHA256", "RSAandMGF1");
+ // BEGIN android-removed
+ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA1, "SHA1", "PLAIN-ECDSA");
+ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA224, "SHA224", "PLAIN-ECDSA");
+ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA256, "SHA256", "PLAIN-ECDSA");
+ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA384, "SHA384", "PLAIN-ECDSA");
+ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA512, "SHA512", "PLAIN-ECDSA");
+ // addEntries(BSIObjectIdentifiers.ecdsa_plain_RIPEMD160, "RIPEMD160", "PLAIN-ECDSA");
+ // END android-removed
encryptionAlgs.put(X9ObjectIdentifiers.id_dsa, "DSA");
encryptionAlgs.put(PKCSObjectIdentifiers.rsaEncryption, "RSA");
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java
new file mode 100644
index 0000000..c81c302
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java
@@ -0,0 +1,20 @@
+package org.bouncycastle.cms;
+
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public interface PasswordRecipient
+ extends Recipient
+{
+ public static final int PKCS5_SCHEME2 = 0;
+ public static final int PKCS5_SCHEME2_UTF8 = 1;
+
+ byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize)
+ throws CMSException;
+
+ RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, byte[] derivedKey, byte[] encryptedEncryptedContentKey)
+ throws CMSException;
+
+ int getPasswordConversionScheme();
+
+ char[] getPassword();
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/Recipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/Recipient.java
new file mode 100644
index 0000000..88c88a6
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/Recipient.java
@@ -0,0 +1,5 @@
+package org.bouncycastle.cms;
+
+public interface Recipient
+{
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/RecipientOperator.java b/bcpkix/src/main/java/org/bouncycastle/cms/RecipientOperator.java
new file mode 100644
index 0000000..7b3e3e5
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/RecipientOperator.java
@@ -0,0 +1,48 @@
+package org.bouncycastle.cms;
+
+import java.io.InputStream;
+
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.operator.InputDecryptor;
+import org.bouncycastle.operator.MacCalculator;
+import org.bouncycastle.util.io.TeeInputStream;
+
+public class RecipientOperator
+{
+ private final AlgorithmIdentifier algorithmIdentifier;
+ private final Object operator;
+
+ public RecipientOperator(InputDecryptor decryptor)
+ {
+ this.algorithmIdentifier = decryptor.getAlgorithmIdentifier();
+ this.operator = decryptor;
+ }
+
+ public RecipientOperator(MacCalculator macCalculator)
+ {
+ this.algorithmIdentifier = macCalculator.getAlgorithmIdentifier();
+ this.operator = macCalculator;
+ }
+
+ public InputStream getInputStream(InputStream dataIn)
+ {
+ if (operator instanceof InputDecryptor)
+ {
+ return ((InputDecryptor)operator).getInputStream(dataIn);
+ }
+ else
+ {
+ return new TeeInputStream(dataIn, ((MacCalculator)operator).getOutputStream());
+ }
+ }
+
+ public boolean isMacBased()
+ {
+ return operator instanceof MacCalculator;
+ }
+
+ public byte[] getMac()
+ {
+ return ((MacCalculator)operator).getMac();
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java
index 808eb4e..f6a5482 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java
@@ -10,7 +10,9 @@ import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERNull;
// BEGIN android-removed
+// import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
// END android-removed
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
@@ -88,8 +90,18 @@ public class DefaultSignatureAlgorithmIdentifierFinder
// algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
// algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
// algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
+ // algorithms.put("SHA1WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA1);
+ // algorithms.put("SHA224WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA224);
+ // algorithms.put("SHA256WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA256);
+ // algorithms.put("SHA384WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA384);
+ // algorithms.put("SHA512WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA512);
+ // algorithms.put("RIPEMD160WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_RIPEMD160);
+ // algorithms.put("SHA1WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1);
+ // algorithms.put("SHA224WITHPCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_224);
+ // algorithms.put("SHA256WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_256);
+ // algorithms.put("SHA384WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_384);
+ // algorithms.put("SHA512WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_512);
// END android-removed
-
//
// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
// The parameters field SHALL be NULL for RSA based signature algorithms.
@@ -227,4 +239,4 @@ public class DefaultSignatureAlgorithmIdentifierFinder
{
return generate(sigAlgName);
}
-} \ No newline at end of file
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/GenericKey.java b/bcpkix/src/main/java/org/bouncycastle/operator/GenericKey.java
new file mode 100644
index 0000000..c637b66
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/GenericKey.java
@@ -0,0 +1,41 @@
+package org.bouncycastle.operator;
+
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class GenericKey
+{
+ private AlgorithmIdentifier algorithmIdentifier;
+ private Object representation;
+
+ /**
+ * @deprecated provide an AlgorithmIdentifier.
+ * @param representation key data
+ */
+ public GenericKey(Object representation)
+ {
+ this.algorithmIdentifier = null;
+ this.representation = representation;
+ }
+
+ public GenericKey(AlgorithmIdentifier algorithmIdentifier, byte[] representation)
+ {
+ this.algorithmIdentifier = algorithmIdentifier;
+ this.representation = representation;
+ }
+
+ protected GenericKey(AlgorithmIdentifier algorithmIdentifier, Object representation)
+ {
+ this.algorithmIdentifier = algorithmIdentifier;
+ this.representation = representation;
+ }
+
+ public AlgorithmIdentifier getAlgorithmIdentifier()
+ {
+ return algorithmIdentifier;
+ }
+
+ public Object getRepresentation()
+ {
+ return representation;
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/InputDecryptor.java b/bcpkix/src/main/java/org/bouncycastle/operator/InputDecryptor.java
new file mode 100644
index 0000000..80d7d82
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/InputDecryptor.java
@@ -0,0 +1,29 @@
+package org.bouncycastle.operator;
+
+import java.io.InputStream;
+
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * General interface for an operator that is able to produce
+ * an InputStream that will decrypt a stream of encrypted data.
+ */
+public interface InputDecryptor
+{
+ /**
+ * Return the algorithm identifier describing the encryption
+ * algorithm and parameters this decryptor can process.
+ *
+ * @return algorithm oid and parameters.
+ */
+ AlgorithmIdentifier getAlgorithmIdentifier();
+
+ /**
+ * Wrap the passed in input stream encIn, returning an input stream
+ * that decrypts what it reads from encIn before returning it.
+ *
+ * @param encIn InputStream containing encrypted input.
+ * @return an decrypting InputStream
+ */
+ InputStream getInputStream(InputStream encIn);
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/MacCalculator.java b/bcpkix/src/main/java/org/bouncycastle/operator/MacCalculator.java
new file mode 100644
index 0000000..0572afc
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/MacCalculator.java
@@ -0,0 +1,34 @@
+package org.bouncycastle.operator;
+
+import java.io.OutputStream;
+
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public interface MacCalculator
+{
+ AlgorithmIdentifier getAlgorithmIdentifier();
+
+ /**
+ * Returns a stream that will accept data for the purpose of calculating
+ * the MAC for later verification. Use org.bouncycastle.util.io.TeeOutputStream if you want to accumulate
+ * the data on the fly as well.
+ *
+ * @return an OutputStream
+ */
+ OutputStream getOutputStream();
+
+ /**
+ * Return the calculated MAC based on what has been written to the stream.
+ *
+ * @return calculated MAC.
+ */
+ byte[] getMac();
+
+
+ /**
+ * Return the key used for calculating the MAC.
+ *
+ * @return the MAC key.
+ */
+ GenericKey getKey();
+} \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java
index 04885c0..31af916 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java
@@ -10,9 +10,9 @@ import java.security.Signature;
import java.security.SignatureException;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.jcajce.DefaultJcaJceHelper;
-import org.bouncycastle.jcajce.NamedJcaJceHelper;
-import org.bouncycastle.jcajce.ProviderJcaJceHelper;
+import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
+import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
+import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.OperatorCreationException;
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
index 87a6699..14ab78d 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
@@ -15,9 +15,9 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
-import org.bouncycastle.jcajce.DefaultJcaJceHelper;
-import org.bouncycastle.jcajce.NamedJcaJceHelper;
-import org.bouncycastle.jcajce.ProviderJcaJceHelper;
+import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
+import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
+import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
import org.bouncycastle.operator.ContentVerifier;
import org.bouncycastle.operator.ContentVerifierProvider;
import org.bouncycastle.operator.OperatorCreationException;
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaDigestCalculatorProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaDigestCalculatorProviderBuilder.java
index 6f59cd0..e356796 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaDigestCalculatorProviderBuilder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaDigestCalculatorProviderBuilder.java
@@ -7,9 +7,9 @@ import java.security.MessageDigest;
import java.security.Provider;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.jcajce.DefaultJcaJceHelper;
-import org.bouncycastle.jcajce.NamedJcaJceHelper;
-import org.bouncycastle.jcajce.ProviderJcaJceHelper;
+import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
+import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
+import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java
index 74c1b28..927b4d7 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java
@@ -25,7 +25,9 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERNull;
// BEGIN android-removed
+// import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
// END android-removed
import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
@@ -38,8 +40,8 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.jcajce.JcaJceHelper;
-import org.bouncycastle.jcajce.JcaJceUtils;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceUtils;
import org.bouncycastle.operator.OperatorCreationException;
class OperatorHelper
@@ -62,6 +64,17 @@ class OperatorHelper
// BEGIN android-removed
// oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, "GOST3411WITHGOST3410");
// oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, "GOST3411WITHECGOST3410");
+ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA1, "SHA1WITHPLAIN-ECDSA");
+ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA224, "SHA224WITHPLAIN-ECDSA");
+ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA256, "SHA256WITHPLAIN-ECDSA");
+ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA384, "SHA384WITHPLAIN-ECDSA");
+ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA512, "SHA512WITHPLAIN-ECDSA");
+ // oids.put(BSIObjectIdentifiers.ecdsa_plain_RIPEMD160, "RIPEMD160WITHPLAIN-ECDSA");
+ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_1, "SHA1WITHCVC-ECDSA");
+ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_224, "SHA224WITHCVC-ECDSA");
+ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_256, "SHA256WITHCVC-ECDSA");
+ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_384, "SHA384WITHCVC-ECDSA");
+ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_512, "SHA512WITHCVC-ECDSA");
// END android-removed
oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
@@ -84,9 +97,9 @@ class OperatorHelper
oids.put(NISTObjectIdentifiers.id_sha256, "SHA-256");
oids.put(NISTObjectIdentifiers.id_sha384, "SHA-384");
oids.put(NISTObjectIdentifiers.id_sha512, "SHA-512");
- oids.put(TeleTrusTObjectIdentifiers.ripemd128, "RIPEMD-128");
- oids.put(TeleTrusTObjectIdentifiers.ripemd160, "RIPEMD-160");
- oids.put(TeleTrusTObjectIdentifiers.ripemd256, "RIPEMD-256");
+ oids.put(TeleTrusTObjectIdentifiers.ripemd128, "RIPEMD128");
+ oids.put(TeleTrusTObjectIdentifiers.ripemd160, "RIPEMD160");
+ oids.put(TeleTrusTObjectIdentifiers.ripemd256, "RIPEMD256");
asymmetricWrapperAlgNames.put(PKCSObjectIdentifiers.rsaEncryption, "RSA/ECB/PKCS1Padding");
@@ -235,7 +248,7 @@ class OperatorHelper
try
{
- dig = helper.createDigest(getDigestAlgName(digAlgId.getAlgorithm()));
+ dig = helper.createDigest(JcaJceUtils.getDigestAlgName(digAlgId.getAlgorithm()));
}
catch (NoSuchAlgorithmException e)
{
@@ -329,7 +342,7 @@ class OperatorHelper
if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS))
{
RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params);
- return getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "WITHRSAANDMGF1";
+ return JcaJceUtils.getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "WITHRSAANDMGF1";
}
}
@@ -341,57 +354,6 @@ class OperatorHelper
return sigAlgId.getAlgorithm().getId();
}
- private static String getDigestAlgName(
- ASN1ObjectIdentifier digestAlgOID)
- {
- if (PKCSObjectIdentifiers.md5.equals(digestAlgOID))
- {
- return "MD5";
- }
- else if (OIWObjectIdentifiers.idSHA1.equals(digestAlgOID))
- {
- return "SHA1";
- }
- else if (NISTObjectIdentifiers.id_sha224.equals(digestAlgOID))
- {
- return "SHA224";
- }
- else if (NISTObjectIdentifiers.id_sha256.equals(digestAlgOID))
- {
- return "SHA256";
- }
- else if (NISTObjectIdentifiers.id_sha384.equals(digestAlgOID))
- {
- return "SHA384";
- }
- else if (NISTObjectIdentifiers.id_sha512.equals(digestAlgOID))
- {
- return "SHA512";
- }
- // BEGIN android-removed
- // else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID))
- // {
- // return "RIPEMD128";
- // }
- // else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID))
- // {
- // return "RIPEMD160";
- // }
- // else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID))
- // {
- // return "RIPEMD256";
- // }
- // else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID))
- // {
- // return "GOST3411";
- // }
- // END android-removed
- else
- {
- return digestAlgOID.getId();
- }
- }
-
public X509Certificate convertCertificate(X509CertificateHolder certHolder)
throws CertificateException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
index d7216a6..8816b2b 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
@@ -2,9 +2,18 @@ package org.bouncycastle.asn1;
import java.io.IOException;
+/**
+ * Interface to parse ASN.1 application specific objects.
+ */
public interface ASN1ApplicationSpecificParser
extends ASN1Encodable, InMemoryRepresentable
{
+ /**
+ * Read the next object in the parser.
+ *
+ * @return an ASN1Encodable
+ * @throws IOException on a parsing or decoding error.
+ */
ASN1Encodable readObject()
throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java
index 1360e8b..30d7d45 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java
@@ -1,15 +1,221 @@
package org.bouncycastle.asn1;
+import java.io.IOException;
+
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Public facade of ASN.1 Boolean data.
+ * <p>
+ * Use following to place a new instance of ASN.1 Boolean in your dataset:
+ * </p>
+ * <ul>
+ * <li> ASN1Boolean.TRUE literal</li>
+ * <li> ASN1Boolean.FALSE literal</li>
+ * <li> {@link ASN1Boolean#getInstance(boolean) ASN1Boolean.getInstance(boolean)}</li>
+ * <li> {@link ASN1Boolean#getInstance(int) ASN1Boolean.getInstance(int)}</li>
+ * </ul>
+ * </p>
+ */
public class ASN1Boolean
- extends DERBoolean
+ extends ASN1Primitive
{
- public ASN1Boolean(boolean value)
+ private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff };
+ private static final byte[] FALSE_VALUE = new byte[] { 0 };
+
+ // BEGIN android-changed
+ final private byte[] value;
+ // END android-changed
+
+ public static final ASN1Boolean FALSE = new ASN1Boolean(false);
+ public static final ASN1Boolean TRUE = new ASN1Boolean(true);
+
+ /**
+ * return a boolean from the passed in object.
+ *
+ * @param obj an ASN1Boolean or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Boolean instance.
+ */
+ public static ASN1Boolean getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Boolean)
+ {
+ return (ASN1Boolean)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ byte[] enc = (byte[])obj;
+ try
+ {
+ return (ASN1Boolean)fromByteArray(enc);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct boolean from byte[]: " + e.getMessage());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an ASN1Boolean from the passed in boolean.
+ * @return an ASN1Boolean instance.
+ */
+ public static ASN1Boolean getInstance(
+ boolean value)
+ {
+ return (value ? TRUE : FALSE);
+ }
+
+ /**
+ * return an ASN1Boolean from the passed in value.
+ * @return an ASN1Boolean instance.
+ */
+ public static ASN1Boolean getInstance(
+ int value)
{
- super(value);
+ return (value != 0 ? TRUE : FALSE);
}
- ASN1Boolean(byte[] value)
+ // BEGIN android-added
+ /**
+ * return a ASN1Boolean from the passed in array.
+ */
+ public static ASN1Boolean getInstance(
+ byte[] octets)
{
- super(value);
+ return (octets[0] != 0) ? TRUE : FALSE;
+ }
+
+ // END android-added
+ /**
+ * return a Boolean from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1Boolean instance.
+ */
+ public static ASN1Boolean getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1Boolean)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return ASN1Boolean.fromOctetString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ // BEGIN android-changed
+ protected ASN1Boolean(
+ // END android-changed
+ byte[] value)
+ {
+ if (value.length != 1)
+ {
+ throw new IllegalArgumentException("byte value should have 1 byte in it");
+ }
+
+ if (value[0] == 0)
+ {
+ this.value = FALSE_VALUE;
+ }
+ else if ((value[0] & 0xff) == 0xff)
+ {
+ this.value = TRUE_VALUE;
+ }
+ else
+ {
+ this.value = Arrays.clone(value);
+ }
+ }
+
+ /**
+ * @deprecated use getInstance(boolean) method.
+ * @param value true or false.
+ */
+ // BEGIN android-changed
+ protected ASN1Boolean(
+ boolean value)
+ // END android-changed
+ {
+ this.value = (value) ? TRUE_VALUE : FALSE_VALUE;
+ }
+
+ public boolean isTrue()
+ {
+ return (value[0] != 0);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 3;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.BOOLEAN, value);
+ }
+
+ protected boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (o instanceof ASN1Boolean)
+ {
+ return (value[0] == ((ASN1Boolean)o).value[0]);
+ }
+
+ return false;
+ }
+
+ public int hashCode()
+ {
+ return value[0];
+ }
+
+
+ public String toString()
+ {
+ return (value[0] != 0) ? "TRUE" : "FALSE";
+ }
+
+ static ASN1Boolean fromOctetString(byte[] value)
+ {
+ if (value.length != 1)
+ {
+ throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it");
+ }
+
+ if (value[0] == 0)
+ {
+ return FALSE;
+ }
+ else if ((value[0] & 0xff) == 0xff)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return new ASN1Boolean(value);
+ }
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java
index 603131d..8a6714f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java
@@ -5,8 +5,22 @@ package org.bouncycastle.asn1;
* own object any attempt to tag the object implicitly will convert the tag to
* an explicit one as the encoding rules require.
* <p>
- * If you use this interface your class should also implement the getInstance
- * pattern which takes a tag object and the tagging mode used.
+ * If you use this interface your class should also implement the getInstance()
+ * pattern which takes a tag object and the tagging mode used.
+ * <p>
+ * <hr>
+ * <p><b>X.690</b></p>
+ * <p><b>8: Basic encoding rules</b></p>
+ * <p><b>8.13 Encoding of a choice value </b></p>
+ * <p>
+ * The encoding of a choice value shall be the same as the encoding of a value of the chosen type.
+ * <blockquote>
+ * NOTE 1 &mdash; The encoding may be primitive or constructed depending on the chosen type.
+ * <p>
+ * NOTE 2 &mdash; The tag used in the identifier octets is the tag of the chosen type,
+ * as specified in the ASN.1 definition of the choice type.
+ * </blockquote>
+ * </p>
*/
public interface ASN1Choice
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encodable.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encodable.java
index f5738bf..aa8825c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encodable.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encodable.java
@@ -1,6 +1,13 @@
package org.bouncycastle.asn1;
+/**
+ * Basic interface to produce serialisers for ASN.1 encodings.
+ */
public interface ASN1Encodable
{
+ /**
+ * Return an object, possibly constructed, of ASN.1 primitives
+ * @return an ASN.1 primitive.
+ */
ASN1Primitive toASN1Primitive();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java
index 2819a8d..530da52 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java
@@ -3,19 +3,35 @@ package org.bouncycastle.asn1;
import java.util.Enumeration;
import java.util.Vector;
+/**
+ * Mutable class for building ASN.1 constructed objects.
+ */
public class ASN1EncodableVector
{
Vector v = new Vector();
+ /**
+ * Base constructor.
+ */
public ASN1EncodableVector()
{
}
+ /**
+ * Add an encodable to the vector.
+ *
+ * @param obj the encodable to add.
+ */
public void add(ASN1Encodable obj)
{
v.addElement(obj);
}
+ /**
+ * Add the contents of another vector.
+ *
+ * @param other the vector to add.
+ */
public void addAll(ASN1EncodableVector other)
{
for (Enumeration en = other.v.elements(); en.hasMoreElements();)
@@ -24,11 +40,22 @@ public class ASN1EncodableVector
}
}
+ /**
+ * Return the object at position i in this vector.
+ *
+ * @param i the index of the object of interest.
+ * @return the object at position i.
+ */
public ASN1Encodable get(int i)
{
return (ASN1Encodable)v.elementAt(i);
}
+ /**
+ * Return the size of the vector.
+ *
+ * @return the object count in the vector.
+ */
public int size()
{
return v.size();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encoding.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encoding.java
index 821d3b9..94a8842 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encoding.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Encoding.java
@@ -1,8 +1,22 @@
package org.bouncycastle.asn1;
+/**
+ * Supported encoding formats.
+ */
public interface ASN1Encoding
{
+ /**
+ * DER - distinguished encoding rules.
+ */
static final String DER = "DER";
+
+ /**
+ * DL - definite length encoding.
+ */
static final String DL = "DL";
+
+ /**
+ * BER - basic encoding rules.
+ */
static final String BER = "BER";
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java
index d93fd91..d6fd2e2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java
@@ -1,22 +1,174 @@
package org.bouncycastle.asn1;
+import java.io.IOException;
import java.math.BigInteger;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Class representing the ASN.1 ENUMERATED type.
+ */
public class ASN1Enumerated
- extends DEREnumerated
+ extends ASN1Primitive
{
- ASN1Enumerated(byte[] bytes)
+ byte[] bytes;
+
+ /**
+ * return an enumerated from the passed in object
+ *
+ * @param obj an ASN1Enumerated or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Enumerated instance, or null.
+ */
+ public static ASN1Enumerated getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Enumerated)
+ {
+ return (ASN1Enumerated)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1Enumerated)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Enumerated from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1Enumerated instance, or null.
+ */
+ public static ASN1Enumerated getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1Enumerated)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return fromOctetString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * Constructor from int.
+ *
+ * @param value the value of this enumerated.
+ */
+ public ASN1Enumerated(
+ int value)
+ {
+ bytes = BigInteger.valueOf(value).toByteArray();
+ }
+
+ /**
+ * Constructor from BigInteger
+ *
+ * @param value the value of this enumerated.
+ */
+ public ASN1Enumerated(
+ BigInteger value)
+ {
+ bytes = value.toByteArray();
+ }
+
+ /**
+ * Constructor from encoded BigInteger.
+ *
+ * @param bytes the value of this enumerated as an encoded BigInteger (signed).
+ */
+ public ASN1Enumerated(
+ byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ public BigInteger getValue()
{
- super(bytes);
+ return new BigInteger(bytes);
}
- public ASN1Enumerated(BigInteger value)
+ boolean isConstructed()
{
- super(value);
+ return false;
}
- public ASN1Enumerated(int value)
+ int encodedLength()
{
- super(value);
+ return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.ENUMERATED, bytes);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Enumerated))
+ {
+ return false;
+ }
+
+ ASN1Enumerated other = (ASN1Enumerated)o;
+
+ return Arrays.areEqual(this.bytes, other.bytes);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(bytes);
+ }
+
+ private static ASN1Enumerated[] cache = new ASN1Enumerated[12];
+
+ static ASN1Enumerated fromOctetString(byte[] enc)
+ {
+ if (enc.length > 1)
+ {
+ return new ASN1Enumerated(Arrays.clone(enc));
+ }
+
+ if (enc.length == 0)
+ {
+ throw new IllegalArgumentException("ENUMERATED has zero length");
+ }
+ int value = enc[0] & 0xff;
+
+ if (value >= cache.length)
+ {
+ return new ASN1Enumerated(Arrays.clone(enc));
+ }
+
+ ASN1Enumerated possibleMatch = cache[value];
+
+ if (possibleMatch == null)
+ {
+ possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc));
+ }
+
+ return possibleMatch;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
index 0088a53..d760a1f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
@@ -1,22 +1,373 @@
package org.bouncycastle.asn1;
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Strings;
+
+/**
+ * Base class representing the ASN.1 GeneralizedTime type.
+ * <p>
+ * The main difference between these and UTC time is a 4 digit year.
+ * </p>
+ */
public class ASN1GeneralizedTime
- extends DERGeneralizedTime
+ extends ASN1Primitive
{
- ASN1GeneralizedTime(byte[] bytes)
+ private byte[] time;
+
+ /**
+ * return a generalized time from the passed in object
+ *
+ * @param obj an ASN1GeneralizedTime or an object that can be converted into one.
+ * @return an ASN1GeneralizedTime instance, or null.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1GeneralizedTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1GeneralizedTime)
+ {
+ return (ASN1GeneralizedTime)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1GeneralizedTime)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Generalized Time object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @return an ASN1GeneralizedTime instance.
+ * @throws IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1GeneralizedTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1GeneralizedTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+ * for local time, or Z+-HHMM on the end, for difference between local
+ * time and UTC time. The fractional second amount f must consist of at
+ * least one number with trailing zeroes removed.
+ *
+ * @param time the time string.
+ * @throws IllegalArgumentException if String is an illegal format.
+ */
+ public ASN1GeneralizedTime(
+ String time)
+ {
+ this.time = Strings.toByteArray(time);
+ try
+ {
+ this.getDate();
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Base constructor from a java.util.date object
+ *
+ * @param time a date object representing the time of interest.
+ */
+ public ASN1GeneralizedTime(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ /**
+ * Base constructor from a java.util.date and Locale - you may need to use this if the default locale
+ * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
+ *
+ * @param time a date object representing the time of interest.
+ * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
+ */
+ public ASN1GeneralizedTime(
+ Date time,
+ Locale locale)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'", locale);
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ ASN1GeneralizedTime(
+ byte[] bytes)
+ {
+ this.time = bytes;
+ }
+
+ /**
+ * Return the time.
+ *
+ * @return The time string as it appeared in the encoded object.
+ */
+ public String getTimeString()
+ {
+ return Strings.fromByteArray(time);
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ * <p/>
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ * <pre>
+ * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ * </pre>
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.charAt(stime.length() - 1) == 'Z')
+ {
+ return stime.substring(0, stime.length() - 1) + "GMT+00:00";
+ }
+ else
+ {
+ int signPos = stime.length() - 5;
+ char sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos, signPos + 3)
+ + ":"
+ + stime.substring(signPos + 3);
+ }
+ else
+ {
+ signPos = stime.length() - 3;
+ sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos)
+ + ":00";
+ }
+ }
+ }
+ return stime + calculateGMTOffset();
+ }
+
+ private String calculateGMTOffset()
+ {
+ String sign = "+";
+ TimeZone timeZone = TimeZone.getDefault();
+ int offset = timeZone.getRawOffset();
+ if (offset < 0)
+ {
+ sign = "-";
+ offset = -offset;
+ }
+ int hours = offset / (60 * 60 * 1000);
+ int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
+
+ try
+ {
+ if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
+ {
+ hours += sign.equals("+") ? 1 : -1;
+ }
+ }
+ catch (ParseException e)
+ {
+ // we'll do our best and ignore daylight savings
+ }
+
+ return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+ }
+
+ private String convert(int time)
+ {
+ if (time < 10)
+ {
+ return "0" + time;
+ }
+
+ return Integer.toString(time);
+ }
+
+ public Date getDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF;
+ String stime = Strings.fromByteArray(time);
+ String d = stime;
+
+ if (stime.endsWith("Z"))
+ {
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+ }
+ else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0)
+ {
+ d = this.getTime();
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+ }
+ else
+ {
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
+ }
+
+ if (hasFractionalSeconds())
+ {
+ // java misinterprets extra digits as being milliseconds...
+ String frac = d.substring(14);
+ int index;
+ for (index = 1; index < frac.length(); index++)
+ {
+ char ch = frac.charAt(index);
+ if (!('0' <= ch && ch <= '9'))
+ {
+ break;
+ }
+ }
+
+ if (index - 1 > 3)
+ {
+ frac = frac.substring(0, 4) + frac.substring(index);
+ d = d.substring(0, 14) + frac;
+ }
+ else if (index - 1 == 1)
+ {
+ frac = frac.substring(0, index) + "00" + frac.substring(index);
+ d = d.substring(0, 14) + frac;
+ }
+ else if (index - 1 == 2)
+ {
+ frac = frac.substring(0, index) + "0" + frac.substring(index);
+ d = d.substring(0, 14) + frac;
+ }
+ }
+
+ return dateF.parse(d);
+ }
+
+ private boolean hasFractionalSeconds()
+ {
+ for (int i = 0; i != time.length; i++)
+ {
+ if (time[i] == '.')
+ {
+ if (i == 14)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean isConstructed()
{
- super(bytes);
+ return false;
}
- public ASN1GeneralizedTime(Date time)
+ int encodedLength()
{
- super(time);
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.GENERALIZED_TIME, time);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1GeneralizedTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((ASN1GeneralizedTime)o).time);
}
- public ASN1GeneralizedTime(String time)
+ public int hashCode()
{
- super(time);
+ return Arrays.hashCode(time);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java
index 4471433..1971af9 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java
@@ -124,6 +124,12 @@ public class ASN1InputStream
/**
* build an object given its tag and the number of bytes to construct it from.
+ *
+ * @param tag the full tag details.
+ * @param tagNo the tagNo defined.
+ * @param length the length of the object.
+ * @return the resulting primitive.
+ * @throws java.io.IOException on processing exception.
*/
protected ASN1Primitive buildObject(
int tag,
@@ -438,7 +444,7 @@ public class ASN1InputStream
case IA5_STRING:
return new DERIA5String(defIn.toByteArray());
case INTEGER:
- return new ASN1Integer(defIn.toByteArray());
+ return new ASN1Integer(defIn.toByteArray(), false);
case NULL:
return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
case NUMERIC_STRING:
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java
index d60c6a8..10326cf 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java
@@ -1,22 +1,157 @@
package org.bouncycastle.asn1;
+import java.io.IOException;
import java.math.BigInteger;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Class representing the ASN.1 INTEGER type.
+ */
public class ASN1Integer
- extends DERInteger
+ extends ASN1Primitive
{
- ASN1Integer(byte[] bytes)
+ byte[] bytes;
+
+ /**
+ * return an integer from the passed in object
+ *
+ * @param obj an ASN1Integer or an object that can be converted into one.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Integer instance.
+ */
+ public static ASN1Integer getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Integer)
+ {
+ return (ASN1Integer)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1Integer)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Integer from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1Integer instance.
+ */
+ public static ASN1Integer getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1Integer)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets());
+ }
+ }
+
+ public ASN1Integer(
+ long value)
{
- super(bytes);
+ bytes = BigInteger.valueOf(value).toByteArray();
}
- public ASN1Integer(BigInteger value)
+ public ASN1Integer(
+ BigInteger value)
{
- super(value);
+ bytes = value.toByteArray();
}
- public ASN1Integer(long value)
+ public ASN1Integer(
+ byte[] bytes)
{
- super(value);
+ this(bytes, true);
}
+
+ ASN1Integer(byte[] bytes, boolean clone)
+ {
+ this.bytes = (clone) ? Arrays.clone(bytes) : bytes;
+ }
+
+ public BigInteger getValue()
+ {
+ return new BigInteger(bytes);
+ }
+
+ /**
+ * in some cases positive values get crammed into a space,
+ * that's not quite big enough...
+ * @return the BigInteger that results from treating this ASN.1 INTEGER as unsigned.
+ */
+ public BigInteger getPositiveValue()
+ {
+ return new BigInteger(1, bytes);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.INTEGER, bytes);
+ }
+
+ public int hashCode()
+ {
+ int value = 0;
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ value ^= (bytes[i] & 0xff) << (i % 4);
+ }
+
+ return value;
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Integer))
+ {
+ return false;
+ }
+
+ ASN1Integer other = (ASN1Integer)o;
+
+ return Arrays.areEqual(bytes, other.bytes);
+ }
+
+ public String toString()
+ {
+ return getValue().toString();
+ }
+
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java
index 84814c5..f1098e7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java
@@ -3,20 +3,32 @@ package org.bouncycastle.asn1;
import java.io.IOException;
/**
- * A NULL object.
+ * A NULL object - use DERNull.INSTANCE for populating structures.
*/
public abstract class ASN1Null
extends ASN1Primitive
{
- /**
- * @deprecated use DERNull.INSTANCE
- */
- // BEGIN android-changed
+ // BEGIN android-added
/*package*/ ASN1Null()
{
}
- // END android-changed
+ // END android-added
+ /**
+ * Return an instance of ASN.1 NULL from the passed in object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link ASN1Null} object
+ * <li> a byte[] containing ASN.1 NULL object
+ * </ul>
+ * </p>
+ *
+ * @param o object to be converted.
+ * @return an instance of ASN1Null, or null.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static ASN1Null getInstance(Object o)
{
if (o instanceof ASN1Null)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Object.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Object.java
index 956fb7d..cfda1a6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Object.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Object.java
@@ -3,6 +3,9 @@ package org.bouncycastle.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+/**
+ * Base class for defining an ASN.1 object.
+ */
public abstract class ASN1Object
implements ASN1Encodable
{
@@ -88,10 +91,21 @@ public abstract class ASN1Object
return this.toASN1Primitive();
}
+ /**
+ * Return true if obj is a byte array and represents an object with the given tag value.
+ *
+ * @param obj object of interest.
+ * @param tagValue tag value to check for.
+ * @return true if obj is a byte encoding starting with the given tag value, false otherwise.
+ */
protected static boolean hasEncodedTagValue(Object obj, int tagValue)
{
return (obj instanceof byte[]) && ((byte[])obj)[0] == tagValue;
}
+ /**
+ * Method providing a primitive representation of this object suitable for encoding.
+ * @return a primitive representation of this object.
+ */
public abstract ASN1Primitive toASN1Primitive();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
index 98f46a6..9d54058 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
@@ -1,21 +1,217 @@
package org.bouncycastle.asn1;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Class representing the ASN.1 OBJECT IDENTIFIER type.
+ */
public class ASN1ObjectIdentifier
- extends DERObjectIdentifier
+ extends ASN1Primitive
{
- public ASN1ObjectIdentifier(String identifier)
+ String identifier;
+
+ private byte[] body;
+
+ /**
+ * return an OID from the passed in object
+ * @param obj an ASN1ObjectIdentifier or an object that can be converted into one.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1ObjectIdentifier instance, or null.
+ */
+ public static ASN1ObjectIdentifier getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1ObjectIdentifier)
+ {
+ return (ASN1ObjectIdentifier)obj;
+ }
+
+ if (obj instanceof ASN1Encodable && ((ASN1Encodable)obj).toASN1Primitive() instanceof ASN1ObjectIdentifier)
+ {
+ return (ASN1ObjectIdentifier)((ASN1Encodable)obj).toASN1Primitive();
+ }
+
+ if (obj instanceof byte[])
+ {
+ byte[] enc = (byte[])obj;
+ try
+ {
+ return (ASN1ObjectIdentifier)fromByteArray(enc);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct object identifier from byte[]: " + e.getMessage());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Object Identifier from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1ObjectIdentifier instance, or null.
+ */
+ public static ASN1ObjectIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1ObjectIdentifier)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets());
+ }
+ }
+
+ private static final long LONG_LIMIT = (Long.MAX_VALUE >> 7) - 0x7f;
+
+ ASN1ObjectIdentifier(
+ byte[] bytes)
+ {
+ StringBuffer objId = new StringBuffer();
+ long value = 0;
+ BigInteger bigValue = null;
+ boolean first = true;
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ int b = bytes[i] & 0xff;
+
+ if (value <= LONG_LIMIT)
+ {
+ value += (b & 0x7f);
+ if ((b & 0x80) == 0) // end of number reached
+ {
+ if (first)
+ {
+ if (value < 40)
+ {
+ objId.append('0');
+ }
+ else if (value < 80)
+ {
+ objId.append('1');
+ value -= 40;
+ }
+ else
+ {
+ objId.append('2');
+ value -= 80;
+ }
+ first = false;
+ }
+
+ objId.append('.');
+ objId.append(value);
+ value = 0;
+ }
+ else
+ {
+ value <<= 7;
+ }
+ }
+ else
+ {
+ if (bigValue == null)
+ {
+ bigValue = BigInteger.valueOf(value);
+ }
+ bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
+ if ((b & 0x80) == 0)
+ {
+ if (first)
+ {
+ objId.append('2');
+ bigValue = bigValue.subtract(BigInteger.valueOf(80));
+ first = false;
+ }
+
+ objId.append('.');
+ objId.append(bigValue);
+ bigValue = null;
+ value = 0;
+ }
+ else
+ {
+ bigValue = bigValue.shiftLeft(7);
+ }
+ }
+ }
+
+ // BEGIN android-changed
+ /*
+ * Intern the identifier so there aren't hundreds of duplicates
+ * (in practice).
+ */
+ this.identifier = objId.toString().intern();
+ // END android-changed
+ this.body = Arrays.clone(bytes);
+ }
+
+ /**
+ * Create an OID based on the passed in String.
+ *
+ * @param identifier a string representation of an OID.
+ */
+ public ASN1ObjectIdentifier(
+ String identifier)
{
- super(identifier);
+ if (identifier == null)
+ {
+ throw new IllegalArgumentException("'identifier' cannot be null");
+ }
+ if (!isValidIdentifier(identifier))
+ {
+ throw new IllegalArgumentException("string " + identifier + " not an OID");
+ }
+
+ // BEGIN android-changed
+ /*
+ * Intern the identifier so there aren't hundreds of duplicates
+ * (in practice).
+ */
+ this.identifier = identifier.intern();
+ // END android-changed
}
- ASN1ObjectIdentifier(byte[] bytes)
+ /**
+ * Create an OID that creates a branch under the current one.
+ *
+ * @param branchID node numbers for the new branch.
+ * @return the OID for the new created branch.
+ */
+ ASN1ObjectIdentifier(ASN1ObjectIdentifier oid, String branchID)
{
- super(bytes);
+ if (!isValidBranchID(branchID, 0))
+ {
+ throw new IllegalArgumentException("string " + branchID + " not a valid OID branch");
+ }
+
+ this.identifier = oid.getId() + "." + branchID;
}
- ASN1ObjectIdentifier(ASN1ObjectIdentifier oid, String branch)
+ /**
+ * Return the OID as a string.
+ *
+ * @return the string representation of the OID carried by this object.
+ */
+ public String getId()
{
- super(oid, branch);
+ return identifier;
}
/**
@@ -31,12 +227,258 @@ public class ASN1ObjectIdentifier
/**
* Return true if this oid is an extension of the passed in branch, stem.
+ *
* @param stem the arc or branch that is a possible parent.
- * @return true if the branch is on the passed in stem, false otherwise.
+ * @return true if the branch is on the passed in stem, false otherwise.
*/
public boolean on(ASN1ObjectIdentifier stem)
{
String id = getId(), stemId = stem.getId();
return id.length() > stemId.length() && id.charAt(stemId.length()) == '.' && id.startsWith(stemId);
}
+
+ private void writeField(
+ ByteArrayOutputStream out,
+ long fieldValue)
+ {
+ byte[] result = new byte[9];
+ int pos = 8;
+ result[pos] = (byte)((int)fieldValue & 0x7f);
+ while (fieldValue >= (1L << 7))
+ {
+ fieldValue >>= 7;
+ result[--pos] = (byte)((int)fieldValue & 0x7f | 0x80);
+ }
+ out.write(result, pos, 9 - pos);
+ }
+
+ private void writeField(
+ ByteArrayOutputStream out,
+ BigInteger fieldValue)
+ {
+ int byteCount = (fieldValue.bitLength() + 6) / 7;
+ if (byteCount == 0)
+ {
+ out.write(0);
+ }
+ else
+ {
+ BigInteger tmpValue = fieldValue;
+ byte[] tmp = new byte[byteCount];
+ for (int i = byteCount - 1; i >= 0; i--)
+ {
+ tmp[i] = (byte)((tmpValue.intValue() & 0x7f) | 0x80);
+ tmpValue = tmpValue.shiftRight(7);
+ }
+ tmp[byteCount - 1] &= 0x7f;
+ out.write(tmp, 0, tmp.length);
+ }
+ }
+
+ private void doOutput(ByteArrayOutputStream aOut)
+ {
+ OIDTokenizer tok = new OIDTokenizer(identifier);
+ int first = Integer.parseInt(tok.nextToken()) * 40;
+
+ String secondToken = tok.nextToken();
+ if (secondToken.length() <= 18)
+ {
+ writeField(aOut, first + Long.parseLong(secondToken));
+ }
+ else
+ {
+ writeField(aOut, new BigInteger(secondToken).add(BigInteger.valueOf(first)));
+ }
+
+ while (tok.hasMoreTokens())
+ {
+ String token = tok.nextToken();
+ if (token.length() <= 18)
+ {
+ writeField(aOut, Long.parseLong(token));
+ }
+ else
+ {
+ writeField(aOut, new BigInteger(token));
+ }
+ }
+ }
+
+ protected synchronized byte[] getBody()
+ {
+ if (body == null)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ doOutput(bOut);
+
+ body = bOut.toByteArray();
+ }
+
+ return body;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBody().length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ byte[] enc = getBody();
+
+ out.write(BERTags.OBJECT_IDENTIFIER);
+ out.writeLength(enc.length);
+ out.write(enc);
+ }
+
+ public int hashCode()
+ {
+ return identifier.hashCode();
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1ObjectIdentifier))
+ {
+ return false;
+ }
+
+ return identifier.equals(((ASN1ObjectIdentifier)o).identifier);
+ }
+
+ public String toString()
+ {
+ return getId();
+ }
+
+ private static boolean isValidBranchID(
+ String branchID, int start)
+ {
+ boolean periodAllowed = false;
+
+ int pos = branchID.length();
+ while (--pos >= start)
+ {
+ char ch = branchID.charAt(pos);
+
+ // TODO Leading zeroes?
+ if ('0' <= ch && ch <= '9')
+ {
+ periodAllowed = true;
+ continue;
+ }
+
+ if (ch == '.')
+ {
+ if (!periodAllowed)
+ {
+ return false;
+ }
+
+ periodAllowed = false;
+ continue;
+ }
+
+ return false;
+ }
+
+ return periodAllowed;
+ }
+
+ private static boolean isValidIdentifier(
+ String identifier)
+ {
+ if (identifier.length() < 3 || identifier.charAt(1) != '.')
+ {
+ return false;
+ }
+
+ char first = identifier.charAt(0);
+ if (first < '0' || first > '2')
+ {
+ return false;
+ }
+
+ return isValidBranchID(identifier, 2);
+ }
+
+ private static ASN1ObjectIdentifier[][] cache = new ASN1ObjectIdentifier[256][];
+
+ static ASN1ObjectIdentifier fromOctetString(byte[] enc)
+ {
+ if (enc.length < 3)
+ {
+ return new ASN1ObjectIdentifier(enc);
+ }
+
+ int idx1 = enc[enc.length - 2] & 0xff;
+ // in this case top bit is always zero
+ int idx2 = enc[enc.length - 1] & 0x7f;
+
+ ASN1ObjectIdentifier possibleMatch;
+
+ synchronized (cache)
+ {
+ ASN1ObjectIdentifier[] first = cache[idx1];
+ if (first == null)
+ {
+ first = cache[idx1] = new ASN1ObjectIdentifier[128];
+ }
+
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ idx1 = (idx1 + 1) & 0xff;
+ first = cache[idx1];
+ if (first == null)
+ {
+ first = cache[idx1] = new ASN1ObjectIdentifier[128];
+ }
+
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ idx2 = (idx2 + 1) & 0x7f;
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ return new ASN1ObjectIdentifier(enc);
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java
index 703b858..200b66a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java
@@ -7,6 +7,96 @@ import java.io.InputStream;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
+/**
+ * Abstract base for the ASN.1 OCTET STRING data type
+ * <p>
+ * This supports BER, and DER forms of the data.
+ * </p><p>
+ * DER form is always primitive single OCTET STRING, while
+ * BER support includes the constructed forms.
+ * </p>
+ * <hr>
+ * <p><b>X.690</b></p>
+ * <p><b>8: Basic encoding rules</b></p>
+ * <p><b>8.7 Encoding of an octetstring value</b></p>
+ * <p>
+ * <b>8.7.1</b> The encoding of an octetstring value shall be
+ * either primitive or constructed at the option of the sender.
+ * <blockquote>
+ * NOTE &mdash; Where it is necessary to transfer part of an octet string
+ * before the entire OCTET STRING is available, the constructed encoding
+ * is used.
+ * </blockquote>
+ * <p>
+ * <b>8.7.2</b> The primitive encoding contains zero,
+ * one or more contents octets equal in value to the octets
+ * in the data value, in the order they appear in the data value,
+ * and with the most significant bit of an octet of the data value
+ * aligned with the most significant bit of an octet of the contents octets.
+ * </p>
+ * <p>
+ * <b>8.7.3</b> The contents octets for the constructed encoding shall consist
+ * of zero, one, or more encodings.
+ * <blockquote>
+ * NOTE &mdash; Each such encoding includes identifier, length, and contents octets,
+ * and may include end-of-contents octets if it is constructed.
+ * </blockquote>
+ * </p>
+ * <p>
+ * <b>8.7.3.1</b> To encode an octetstring value in this way,
+ * it is segmented. Each segment shall consist of a series of
+ * consecutive octets of the value. There shall be no significance
+ * placed on the segment boundaries.
+ * <blockquote>
+ * NOTE &mdash; A segment may be of size zero, i.e. contain no octets.
+ * </blockquote>
+ * </p>
+ * <p>
+ * <b>8.7.3.2</b> Each encoding in the contents octets shall represent
+ * a segment of the overall octetstring, the encoding arising from
+ * a recursive application of this subclause.
+ * In this recursive application, each segment is treated as if it were
+ * a octetstring value. The encodings of the segments shall appear in the contents
+ * octets in the order in which their octets appear in the overall value.
+ * <blockquote>
+ * NOTE 1 &mdash; As a consequence of this recursion,
+ * each encoding in the contents octets may itself
+ * be primitive or constructed.
+ * However, such encodings will usually be primitive.
+ * </p><p>
+ * NOTE 2 &mdash; In particular, the tags in the contents octets are always universal class, number 4.
+ * </blockquote>
+ * </p>
+ * <p><b>9: Canonical encoding rules</b></p>
+ * <p><b>9.1 Length forms</b></p>
+ * <p>
+ * If the encoding is constructed, it shall employ the indefinite length form.
+ * If the encoding is primitive, it shall include the fewest length octets necessary.
+ * [Contrast with 8.1.3.2 b).]
+ * </p>
+ * <p><b>9.2 String encoding forms</b></p>
+ * <p>
+ * BIT STRING, OCTET STRING,and restricted character string
+ * values shall be encoded with a primitive encoding if they would
+ * require no more than 1000 contents octets, and as a constructed
+ * encoding otherwise. The string fragments contained in
+ * the constructed encoding shall be encoded with a primitive encoding.
+ * The encoding of each fragment, except possibly
+ * the last, shall have 1000 contents octets. (Contrast with 8.21.6.)
+ * </p>
+ * <b>10: Distinguished encoding rules</b>
+ * </p><p>
+ * <b>10.1 Length forms</b>
+ * The definite form of length encoding shall be used,
+ * encoded in the minimum number of octets.
+ * [Contrast with 8.1.3.2 b).]
+ * </p><p>
+ * <b>10.2 String encoding forms</b>
+ * For BIT STRING, OCTET STRING and restricted character string types,
+ * the constructed form of encoding shall not be used.
+ * (Contrast with 8.21.6.)
+ * </p>
+ */
public abstract class ASN1OctetString
extends ASN1Primitive
implements ASN1OctetStringParser
@@ -88,16 +178,31 @@ public abstract class ASN1OctetString
this.string = string;
}
+ /**
+ * Return the content of the OCTET STRING as an InputStream.
+ *
+ * @return an InputStream representing the OCTET STRING's content.
+ */
public InputStream getOctetStream()
{
return new ByteArrayInputStream(string);
}
+ /**
+ * Return the parser associated with this object.
+ *
+ * @return a parser based on this OCTET STRING
+ */
public ASN1OctetStringParser parser()
{
return this;
}
+ /**
+ * Return the content of the OCTET STRING as a byte array.
+ *
+ * @return the byte[] representing the OCTET STRING's content.
+ */
public byte[] getOctets()
{
return string;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetStringParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetStringParser.java
index 0042317..122331f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetStringParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetStringParser.java
@@ -2,8 +2,16 @@ package org.bouncycastle.asn1;
import java.io.InputStream;
+/**
+ * A basic parser for an OCTET STRING object
+ */
public interface ASN1OctetStringParser
extends ASN1Encodable, InMemoryRepresentable
{
+ /**
+ * Return the content of the OCTET STRING as an InputStream.
+ *
+ * @return an InputStream representing the OCTET STRING's content.
+ */
public InputStream getOctetStream();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java
index e6fe137..3c887e5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java
@@ -2,6 +2,9 @@ package org.bouncycastle.asn1;
import java.io.IOException;
+/**
+ * Base class for ASN.1 primitive objects. These are the actual objects used to generate byte encodings.
+ */
public abstract class ASN1Primitive
extends ASN1Object
{
@@ -47,11 +50,21 @@ public abstract class ASN1Primitive
return this;
}
+ /**
+ * Return the current object as one which encodes using Distinguished Encoding Rules.
+ *
+ * @return a DER version of this.
+ */
ASN1Primitive toDERObject()
{
return this;
}
+ /**
+ * Return the current object as one which encodes using Definite Length encoding.
+ *
+ * @return a DL version of this.
+ */
ASN1Primitive toDLObject()
{
return this;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java
index 0507a2b..aa543f2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java
@@ -4,16 +4,64 @@ import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
+/**
+ * ASN.1 <code>SEQUENCE</code> and <code>SEQUENCE OF</code> constructs.
+ * <p>
+ * DER form is always definite form length fields, while
+ * BER support uses indefinite form.
+ * <hr>
+ * <p><b>X.690</b></p>
+ * <p><b>8: Basic encoding rules</b></p>
+ * <p><b>8.9 Encoding of a sequence value </b></p>
+ * 8.9.1 The encoding of a sequence value shall be constructed.
+ * <p>
+ * <b>8.9.2</b> The contents octets shall consist of the complete
+ * encoding of one data value from each of the types listed in
+ * the ASN.1 definition of the sequence type, in the order of
+ * their appearance in the definition, unless the type was referenced
+ * with the keyword <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * </p><p>
+ * <b>8.9.3</b> The encoding of a data value may, but need not,
+ * be present for a type which was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * If present, it shall appear in the encoding at the point
+ * corresponding to the appearance of the type in the ASN.1 definition.
+ * </p><p>
+ * <b>8.10 Encoding of a sequence-of value </b>
+ * </p><p>
+ * <b>8.10.1</b> The encoding of a sequence-of value shall be constructed.
+ * <p>
+ * <b>8.10.2</b> The contents octets shall consist of zero,
+ * one or more complete encodings of data values from the type listed in
+ * the ASN.1 definition.
+ * <p>
+ * <b>8.10.3</b> The order of the encodings of the data values shall be
+ * the same as the order of the data values in the sequence-of value to
+ * be encoded.
+ * </p>
+ * <p><b>9: Canonical encoding rules</b></p>
+ * <p><b>9.1 Length forms</b></p>
+ * If the encoding is constructed, it shall employ the indefinite length form.
+ * If the encoding is primitive, it shall include the fewest length octets necessary.
+ * [Contrast with 8.1.3.2 b).]
+ *
+ * <p><b>11: Restrictions on BER employed by both CER and DER</b></p>
+ * <p><b>11.5 Set and sequence components with default value</b></p>
+ * The encoding of a set value or sequence value shall not include
+ * an encoding for any component value which is equal to
+ * its default value.
+ */
public abstract class ASN1Sequence
extends ASN1Primitive
{
protected Vector seq = new Vector();
/**
- * return an ASN1Sequence from the given object.
+ * Return an ASN1Sequence from the given object.
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Sequence instance, or null.
*/
public static ASN1Sequence getInstance(
Object obj)
@@ -65,6 +113,7 @@ public abstract class ASN1Sequence
* false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return an ASN1Sequence instance.
*/
public static ASN1Sequence getInstance(
ASN1TaggedObject obj,
@@ -110,14 +159,15 @@ public abstract class ASN1Sequence
}
/**
- * create an empty sequence
+ * Create an empty sequence
*/
protected ASN1Sequence()
{
}
/**
- * create a sequence containing one object
+ * Create a sequence containing one object
+ * @param obj the object to be put in the SEQUENCE.
*/
protected ASN1Sequence(
ASN1Encodable obj)
@@ -126,7 +176,8 @@ public abstract class ASN1Sequence
}
/**
- * create a sequence containing a vector of objects.
+ * Create a sequence containing a vector of objects.
+ * @param v the vector of objects to be put in the SEQUENCE
*/
protected ASN1Sequence(
ASN1EncodableVector v)
@@ -138,7 +189,7 @@ public abstract class ASN1Sequence
}
/**
- * create a sequence containing a vector of objects.
+ * Create a sequence containing a vector of objects.
*/
protected ASN1Sequence(
ASN1Encodable[] array)
@@ -209,7 +260,7 @@ public abstract class ASN1Sequence
}
/**
- * return the object at the sequence position indicated by index.
+ * Return the object at the sequence position indicated by index.
*
* @param index the sequence number (starting at zero) of the object
* @return the object at the sequence position indicated by index.
@@ -221,7 +272,7 @@ public abstract class ASN1Sequence
}
/**
- * return the number of objects in this sequence.
+ * Return the number of objects in this sequence.
*
* @return the number of objects in this sequence.
*/
@@ -290,6 +341,10 @@ public abstract class ASN1Sequence
return encObj;
}
+ /**
+ * Change current SEQUENCE object to be encoded as {@link DERSequence}.
+ * This is part of Distinguished Encoding Rules form serialization.
+ */
ASN1Primitive toDERObject()
{
ASN1Sequence derSeq = new DERSequence();
@@ -299,6 +354,10 @@ public abstract class ASN1Sequence
return derSeq;
}
+ /**
+ * Change current SEQUENCE object to be encoded as {@link DLSequence}.
+ * This is part of Direct Length form serialization.
+ */
ASN1Primitive toDLObject()
{
ASN1Sequence dlSeq = new DLSequence();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1SequenceParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1SequenceParser.java
index 441f150..22f83c2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1SequenceParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1SequenceParser.java
@@ -2,9 +2,18 @@ package org.bouncycastle.asn1;
import java.io.IOException;
+/**
+ * A basic parser for a SEQUENCE object
+ */
public interface ASN1SequenceParser
extends ASN1Encodable, InMemoryRepresentable
{
+ /**
+ * Read the next object from the underlying object representing a SEQUENCE.
+ *
+ * @throws IOException for bad input stream.
+ * @return the next object, null if we are at the end.
+ */
ASN1Encodable readObject()
throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java
index f1ac6c7..895f002 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java
@@ -5,7 +5,94 @@ import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
-abstract public class ASN1Set
+/**
+ * ASN.1 <code>SET</code> and <code>SET OF</code> constructs.
+ * <p>
+ * Note: This does not know which syntax the set is!
+ * (The difference: ordering of SET elements or not ordering.)
+ * <p>
+ * DER form is always definite form length fields, while
+ * BER support uses indefinite form.
+ * <p>
+ * The CER form support does not exist.
+ * <p>
+ * <hr>
+ * <h2>X.690</h2>
+ * <h3>8: Basic encoding rules</h3>
+ * <h4>8.11 Encoding of a set value </h4>
+ * <b>8.11.1</b> The encoding of a set value shall be constructed
+ * <p>
+ * <b>8.11.2</b> The contents octets shall consist of the complete
+ * encoding of a data value from each of the types listed in the
+ * ASN.1 definition of the set type, in an order chosen by the sender,
+ * unless the type was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * <p>
+ * <b>8.11.3</b> The encoding of a data value may, but need not,
+ * be present for a type which was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * <blockquote>
+ * NOTE &mdash; The order of data values in a set value is not significant,
+ * and places no constraints on the order during transfer
+ * </blockquote>
+ * <h4>8.12 Encoding of a set-of value</h4>
+ * <b>8.12.1</b> The encoding of a set-of value shall be constructed.
+ * <p>
+ * <b>8.12.2</b> The text of 8.10.2 applies:
+ * <i>The contents octets shall consist of zero,
+ * one or more complete encodings of data values from the type listed in
+ * the ASN.1 definition.</i>
+ * <p>
+ * <b>8.12.3</b> The order of data values need not be preserved by
+ * the encoding and subsequent decoding.
+ *
+ * <h3>9: Canonical encoding rules</h3>
+ * <h4>9.1 Length forms</h4>
+ * If the encoding is constructed, it shall employ the indefinite length form.
+ * If the encoding is primitive, it shall include the fewest length octets necessary.
+ * [Contrast with 8.1.3.2 b).]
+ * <h4>9.3 Set components</h4>
+ * The encodings of the component values of a set value shall
+ * appear in an order determined by their tags as specified
+ * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
+ * Additionally, for the purposes of determining the order in which
+ * components are encoded when one or more component is an untagged
+ * choice type, each untagged choice type is ordered as though it
+ * has a tag equal to that of the smallest tag in that choice type
+ * or any untagged choice types nested within.
+ *
+ * <h3>10: Distinguished encoding rules</h3>
+ * <h4>10.1 Length forms</h4>
+ * The definite form of length encoding shall be used,
+ * encoded in the minimum number of octets.
+ * [Contrast with 8.1.3.2 b).]
+ * <h4>10.3 Set components</h4>
+ * The encodings of the component values of a set value shall appear
+ * in an order determined by their tags as specified
+ * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
+ * <blockquote>
+ * NOTE &mdash; Where a component of the set is an untagged choice type,
+ * the location of that component in the ordering will depend on
+ * the tag of the choice component being encoded.
+ * </blockquote>
+ *
+ * <h3>11: Restrictions on BER employed by both CER and DER</h3>
+ * <h4>11.5 Set and sequence components with default value </h4>
+ * The encoding of a set value or sequence value shall not include
+ * an encoding for any component value which is equal to
+ * its default value.
+ * <h4>11.6 Set-of components </h4>
+ * <p>
+ * The encodings of the component values of a set-of value
+ * shall appear in ascending order, the encodings being compared
+ * as octet strings with the shorter components being padded at
+ * their trailing end with 0-octets.
+ * <blockquote>
+ * NOTE &mdash; The padding octets are for comparison purposes only
+ * and do not appear in the encodings.
+ * </blockquote>
+ */
+public abstract class ASN1Set
extends ASN1Primitive
{
private Vector set = new Vector();
@@ -16,6 +103,7 @@ abstract public class ASN1Set
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1Set instance, or null.
*/
public static ASN1Set getInstance(
Object obj)
@@ -67,6 +155,7 @@ abstract public class ASN1Set
* false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return an ASN1Set instance.
*/
public static ASN1Set getInstance(
ASN1TaggedObject obj,
@@ -135,6 +224,7 @@ abstract public class ASN1Set
/**
* create a sequence containing one object
+ * @param obj object to be added to the SET.
*/
protected ASN1Set(
ASN1Encodable obj)
@@ -144,6 +234,8 @@ abstract public class ASN1Set
/**
* create a sequence containing a vector of objects.
+ * @param v a vector of objects to make up the SET.
+ * @param doSort true if should be sorted DER style, false otherwise.
*/
protected ASN1Set(
ASN1EncodableVector v,
@@ -275,6 +367,10 @@ abstract public class ASN1Set
return hashCode;
}
+ /**
+ * Change current SET object to be encoded as {@link DERSet}.
+ * This is part of Distinguished Encoding Rules form serialization.
+ */
ASN1Primitive toDERObject()
{
if (isSorted)
@@ -304,6 +400,10 @@ abstract public class ASN1Set
}
}
+ /**
+ * Change current SET object to be encoded as {@link DLSet}.
+ * This is part of Direct Length form serialization.
+ */
ASN1Primitive toDLObject()
{
ASN1Set derSet = new DLSet();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1SetParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1SetParser.java
index e025535..5f36dbb 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1SetParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1SetParser.java
@@ -2,9 +2,18 @@ package org.bouncycastle.asn1;
import java.io.IOException;
+/**
+ * A basic parser for a SET object
+ */
public interface ASN1SetParser
extends ASN1Encodable, InMemoryRepresentable
{
+ /**
+ * Read the next object from the underlying object representing a SET.
+ *
+ * @throws IOException for bad input stream.
+ * @return the next object, null if we are at the end.
+ */
public ASN1Encodable readObject()
throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java
index 420fa34..418c101 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java
@@ -4,6 +4,9 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+/**
+ * A parser for ASN.1 streams which also returns, where possible, parsers for the objects it encounters.
+ */
public class ASN1StreamParser
{
private final InputStream _in;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java
index d3816f2..2c82df3 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java
@@ -1,22 +1,314 @@
package org.bouncycastle.asn1;
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Strings;
+
+/**
+- * UTC time object.
+ * Internal facade of {@link ASN1UTCTime}.
+ * <p>
+ * This datatype is valid only from 1950-01-01 00:00:00 UTC until 2049-12-31 23:59:59 UTC.
+ * <p>
+ * <hr>
+ * <p><b>X.690</b></p>
+ * <p><b>11: Restrictions on BER employed by both CER and DER</b></p>
+ * <p><b>11.8 UTCTime </b></p>
+ * <b>11.8.1</b> The encoding shall terminate with "Z",
+ * as described in the ITU-T X.680 | ISO/IEC 8824-1 clause on UTCTime.
+ * <p>
+ * <b>11.8.2</b> The seconds element shall always be present.
+ * <p>
+ * <b>11.8.3</b> Midnight (GMT) shall be represented in the form:
+ * <blockquote>
+ * "YYMMDD000000Z"
+ * </blockquote>
+ * where "YYMMDD" represents the day following the midnight in question.
+ */
public class ASN1UTCTime
- extends DERUTCTime
+ extends ASN1Primitive
{
- ASN1UTCTime(byte[] bytes)
+ private byte[] time;
+
+ /**
+ * return an UTC Time from the passed in object.
+ *
+ * @param obj an ASN1UTCTime or an object that can be converted into one.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ * @return an ASN1UTCTime instance, or null.
+ */
+ public static ASN1UTCTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1UTCTime)
+ {
+ return (ASN1UTCTime)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1UTCTime)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an UTC Time from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ * @return an ASN1UTCTime instance, or null.
+ */
+ public static ASN1UTCTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Object o = obj.getObject();
+
+ if (explicit || o instanceof ASN1UTCTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+ * never encoded. When you're creating one of these objects from scratch, that's
+ * what you want to use, otherwise we'll try to deal with whatever gets read from
+ * the input stream... (this is why the input format is different from the getTime()
+ * method output).
+ * <p>
+ *
+ * @param time the time string.
+ */
+ public ASN1UTCTime(
+ String time)
+ {
+ this.time = Strings.toByteArray(time);
+ try
+ {
+ this.getDate();
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * base constructor from a java.util.date object
+ * @param time the Date to build the time from.
+ */
+ public ASN1UTCTime(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ /**
+ * Base constructor from a java.util.date and Locale - you may need to use this if the default locale
+ * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
+ *
+ * @param time a date object representing the time of interest.
+ * @param locale an appropriate Locale for producing an ASN.1 UTCTime value.
+ */
+ public ASN1UTCTime(
+ Date time,
+ Locale locale)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'", locale);
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ ASN1UTCTime(
+ byte[] time)
+ {
+ this.time = time;
+ }
+
+ /**
+ * return the time as a date based on whatever a 2 digit year will return. For
+ * standardised processing use getAdjustedDate().
+ *
+ * @return the resulting date
+ * @exception ParseException if the date string cannot be parsed.
+ */
+ public Date getDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
+
+ return dateF.parse(getTime());
+ }
+
+ /**
+ * return the time as an adjusted date
+ * in the range of 1950 - 2049.
+ *
+ * @return a date in the range of 1950 to 2049.
+ * @exception ParseException if the date string cannot be parsed.
+ */
+ public Date getAdjustedDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+ return dateF.parse(getAdjustedTime());
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ * <p>
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ * <pre>
+ * dateF = new SimpleDateFormat("yyMMddHHmmssz");
+ * </pre>
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ * <p>
+ * <b>Note:</b> In some cases, due to the local date processing, this
+ * may lead to unexpected results. If you want to stick the normal
+ * convention of 1950 to 2049 use the getAdjustedTime() method.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
+ {
+ if (stime.length() == 11)
+ {
+ return stime.substring(0, 10) + "00GMT+00:00";
+ }
+ else
+ {
+ return stime.substring(0, 12) + "GMT+00:00";
+ }
+ }
+ else
+ {
+ int index = stime.indexOf('-');
+ if (index < 0)
+ {
+ index = stime.indexOf('+');
+ }
+ String d = stime;
+
+ if (index == stime.length() - 3)
+ {
+ d += "00";
+ }
+
+ if (index == 10)
+ {
+ return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
+ }
+ else
+ {
+ return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
+ }
+ }
+ }
+
+ /**
+ * return a time string as an adjusted date with a 4 digit year. This goes
+ * in the range of 1950 - 2049.
+ */
+ public String getAdjustedTime()
+ {
+ String d = this.getTime();
+
+ if (d.charAt(0) < '5')
+ {
+ return "20" + d;
+ }
+ else
+ {
+ return "19" + d;
+ }
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
{
- super(bytes);
+ out.write(BERTags.UTC_TIME);
+
+ int length = time.length;
+
+ out.writeLength(length);
+
+ for (int i = 0; i != length; i++)
+ {
+ out.write((byte)time[i]);
+ }
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1UTCTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((ASN1UTCTime)o).time);
}
- public ASN1UTCTime(Date time)
+ public int hashCode()
{
- super(time);
+ return Arrays.hashCode(time);
}
- public ASN1UTCTime(String time)
+ public String toString()
{
- super(time);
+ return Strings.fromByteArray(time);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java
index 5b59288..85d9843 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERApplicationSpecific.java
@@ -103,15 +103,6 @@ public class DERApplicationSpecific
throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage());
}
}
- else if (obj instanceof ASN1Encodable)
- {
- ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
-
- if (primitive instanceof ASN1Sequence)
- {
- return (DERApplicationSpecific)primitive;
- }
- }
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java
index 341e46a..635300b 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java
@@ -18,6 +18,7 @@ public class DERBMPString
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERBMPString instance, or null.
*/
public static DERBMPString getInstance(
Object obj)
@@ -50,6 +51,7 @@ public class DERBMPString
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return a DERBMPString instance.
*/
public static DERBMPString getInstance(
ASN1TaggedObject obj,
@@ -69,6 +71,7 @@ public class DERBMPString
/**
* basic constructor - byte encoded string.
+ * @param string the encoded BMP STRING to wrap.
*/
DERBMPString(
byte[] string)
@@ -90,6 +93,7 @@ public class DERBMPString
/**
* basic constructor
+ * @param string a String to wrap as a BMP STRING.
*/
public DERBMPString(
String string)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java
index a7b02ec..4852a79 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java
@@ -18,7 +18,8 @@ public class DERBitString
protected int padBits;
/**
- * return the correct number of pad bits for a bit string defined in
+ * @param bitString an int containing the BIT STRING
+ * @return the correct number of pad bits for a bit string defined in
* a 32 bit constant
*/
static protected int getPadBits(
@@ -66,7 +67,8 @@ public class DERBitString
}
/**
- * return the correct number of bytes for a bit string defined in
+ * @param bitString an int containing the BIT STRING
+ * @return the correct number of bytes for a bit string defined in
* a 32 bit constant
*/
static protected byte[] getBytes(int bitString)
@@ -93,7 +95,9 @@ public class DERBitString
/**
* return a Bit String from the passed in object
*
+ * @param obj a DERBitString or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERBitString instance, or null.
*/
public static DERBitString getInstance(
Object obj)
@@ -114,6 +118,7 @@ public class DERBitString
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return a DERBitString instance, or null.
*/
public static DERBitString getInstance(
ASN1TaggedObject obj,
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java
index 634f5a8..378ea35 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java
@@ -1,196 +1,22 @@
package org.bouncycastle.asn1;
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-
+/**
+ * @deprecated use ASN1Boolean
+ */
public class DERBoolean
- extends ASN1Primitive
+ extends ASN1Boolean
{
- private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff };
- private static final byte[] FALSE_VALUE = new byte[] { 0 };
-
- // BEGIN android-changed
- final private byte[] value;
- // END android-changed
-
- public static final ASN1Boolean FALSE = new ASN1Boolean(false);
- public static final ASN1Boolean TRUE = new ASN1Boolean(true);
-
-
- /**
- * return a boolean from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1Boolean getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Boolean)
- {
- return (ASN1Boolean)obj;
- }
-
- if (obj instanceof DERBoolean)
- {
- return ((DERBoolean)obj).isTrue() ? DERBoolean.TRUE : DERBoolean.FALSE;
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a ASN1Boolean from the passed in boolean.
- */
- public static ASN1Boolean getInstance(
- boolean value)
- {
- return (value ? TRUE : FALSE);
- }
-
- /**
- * return a ASN1Boolean from the passed in boolean.
- */
- public static ASN1Boolean getInstance(
- int value)
- {
- return (value != 0 ? TRUE : FALSE);
- }
-
- // BEGIN android-added
- /**
- * return a DERBoolean from the passed in array.
- */
- public static DERBoolean getInstance(
- byte[] octets)
- {
- return (octets[0] != 0) ? TRUE : FALSE;
- }
-
- // END android-added
- /**
- * return a Boolean from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1Boolean getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERBoolean)
- {
- return getInstance(o);
- }
- else
- {
- return ASN1Boolean.fromOctetString(((ASN1OctetString)o).getOctets());
- }
- }
-
- // BEGIN android-changed
- protected DERBoolean(
- // END android-changed
- byte[] value)
- {
- if (value.length != 1)
- {
- throw new IllegalArgumentException("byte value should have 1 byte in it");
- }
-
- if (value[0] == 0)
- {
- this.value = FALSE_VALUE;
- }
- else if (value[0] == 0xff)
- {
- this.value = TRUE_VALUE;
- }
- else
- {
- this.value = Arrays.clone(value);
- }
- }
-
/**
* @deprecated use getInstance(boolean) method.
* @param value
*/
- // BEGIN android-changed
- protected DERBoolean(
- boolean value)
- // END android-changed
+ public DERBoolean(boolean value)
{
- this.value = (value) ? TRUE_VALUE : FALSE_VALUE;
+ super(value);
}
- public boolean isTrue()
+ DERBoolean(byte[] value)
{
- return (value[0] != 0);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 3;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.BOOLEAN, value);
- }
-
- protected boolean asn1Equals(
- ASN1Primitive o)
- {
- if ((o == null) || !(o instanceof DERBoolean))
- {
- return false;
- }
-
- return (value[0] == ((DERBoolean)o).value[0]);
- }
-
- public int hashCode()
- {
- return value[0];
- }
-
-
- public String toString()
- {
- return (value[0] != 0) ? "TRUE" : "FALSE";
- }
-
- static ASN1Boolean fromOctetString(byte[] value)
- {
- if (value.length != 1)
- {
- throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it");
- }
-
- if (value[0] == 0)
- {
- return FALSE;
- }
- else if (value[0] == 0xff)
- {
- return TRUE;
- }
- else
- {
- return new ASN1Boolean(value);
- }
+ super(value);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java b/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
index 9b1ef55..daa8777 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
@@ -1,170 +1,37 @@
package org.bouncycastle.asn1;
-import java.io.IOException;
import java.math.BigInteger;
-import org.bouncycastle.util.Arrays;
-
/**
- * Use ASN1Enumerated instead of this.
+ * @deprecated Use ASN1Enumerated instead of this.
*/
public class DEREnumerated
- extends ASN1Primitive
+ extends ASN1Enumerated
{
- byte[] bytes;
-
- /**
- * return an integer from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1Enumerated getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Enumerated)
- {
- return (ASN1Enumerated)obj;
- }
-
- if (obj instanceof DEREnumerated)
- {
- return new ASN1Enumerated(((DEREnumerated)obj).getValue());
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (ASN1Enumerated)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Enumerated from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1Enumerated getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DEREnumerated)
- {
- return getInstance(o);
- }
- else
- {
- return fromOctetString(((ASN1OctetString)o).getOctets());
- }
- }
-
/**
+ * @param bytes the value of this enumerated as an encoded BigInteger (signed).
* @deprecated use ASN1Enumerated
*/
- public DEREnumerated(
- int value)
+ DEREnumerated(byte[] bytes)
{
- bytes = BigInteger.valueOf(value).toByteArray();
+ super(bytes);
}
/**
+ * @param value the value of this enumerated.
* @deprecated use ASN1Enumerated
*/
- public DEREnumerated(
- BigInteger value)
+ public DEREnumerated(BigInteger value)
{
- bytes = value.toByteArray();
+ super(value);
}
/**
+ * @param value the value of this enumerated.
* @deprecated use ASN1Enumerated
*/
- public DEREnumerated(
- byte[] bytes)
- {
- this.bytes = bytes;
- }
-
- public BigInteger getValue()
- {
- return new BigInteger(bytes);
- }
-
- boolean isConstructed()
+ public DEREnumerated(int value)
{
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.ENUMERATED, bytes);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DEREnumerated))
- {
- return false;
- }
-
- DEREnumerated other = (DEREnumerated)o;
-
- return Arrays.areEqual(this.bytes, other.bytes);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(bytes);
- }
-
- private static ASN1Enumerated[] cache = new ASN1Enumerated[12];
-
- static ASN1Enumerated fromOctetString(byte[] enc)
- {
- if (enc.length > 1)
- {
- return new ASN1Enumerated(Arrays.clone(enc));
- }
-
- if (enc.length == 0)
- {
- throw new IllegalArgumentException("ENUMERATED has zero length");
- }
- int value = enc[0] & 0xff;
-
- if (value >= cache.length)
- {
- return new ASN1Enumerated(Arrays.clone(enc));
- }
-
- ASN1Enumerated possibleMatch = cache[value];
-
- if (possibleMatch == null)
- {
- possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc));
- }
-
- return possibleMatch;
+ super(value);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java
index 43e4673..adee74e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java
@@ -1,350 +1,28 @@
package org.bouncycastle.asn1;
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.Date;
-import java.util.SimpleTimeZone;
-import java.util.TimeZone;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
/**
- * Generalized time object.
+ * DER Generalized time object.
*/
public class DERGeneralizedTime
- extends ASN1Primitive
+ extends ASN1GeneralizedTime
{
- private byte[] time;
-
- /**
- * return a generalized time from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1GeneralizedTime getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1GeneralizedTime)
- {
- return (ASN1GeneralizedTime)obj;
- }
-
- if (obj instanceof DERGeneralizedTime)
- {
- return new ASN1GeneralizedTime(((DERGeneralizedTime)obj).time);
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (ASN1GeneralizedTime)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Generalized Time object from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1GeneralizedTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERGeneralizedTime)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
- * for local time, or Z+-HHMM on the end, for difference between local
- * time and UTC time. The fractional second amount f must consist of at
- * least one number with trailing zeroes removed.
- *
- * @param time the time string.
- * @exception IllegalArgumentException if String is an illegal format.
- */
- public DERGeneralizedTime(
- String time)
- {
- this.time = Strings.toByteArray(time);
- try
- {
- this.getDate();
- }
- catch (ParseException e)
- {
- throw new IllegalArgumentException("invalid date string: " + e.getMessage());
- }
- }
-
- /**
- * base constructor from a java.util.date object
- */
- public DERGeneralizedTime(
- Date time)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- this.time = Strings.toByteArray(dateF.format(time));
- }
-
- DERGeneralizedTime(
- byte[] bytes)
- {
- this.time = bytes;
- }
-
- /**
- * Return the time.
- * @return The time string as it appeared in the encoded object.
- */
- public String getTimeString()
- {
- return Strings.fromByteArray(time);
- }
-
- /**
- * return the time - always in the form of
- * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- * <p>
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- * <pre>
- * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
- * </pre>
- * To read in the time and get a date which is compatible with our local
- * time zone.
- */
- public String getTime()
- {
- String stime = Strings.fromByteArray(time);
-
- //
- // standardise the format.
- //
- if (stime.charAt(stime.length() - 1) == 'Z')
- {
- return stime.substring(0, stime.length() - 1) + "GMT+00:00";
- }
- else
- {
- int signPos = stime.length() - 5;
- char sign = stime.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return stime.substring(0, signPos)
- + "GMT"
- + stime.substring(signPos, signPos + 3)
- + ":"
- + stime.substring(signPos + 3);
- }
- else
- {
- signPos = stime.length() - 3;
- sign = stime.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return stime.substring(0, signPos)
- + "GMT"
- + stime.substring(signPos)
- + ":00";
- }
- }
- }
- return stime + calculateGMTOffset();
- }
- private String calculateGMTOffset()
+ DERGeneralizedTime(byte[] bytes)
{
- String sign = "+";
- TimeZone timeZone = TimeZone.getDefault();
- int offset = timeZone.getRawOffset();
- if (offset < 0)
- {
- sign = "-";
- offset = -offset;
- }
- int hours = offset / (60 * 60 * 1000);
- int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
-
- try
- {
- if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
- {
- hours += sign.equals("+") ? 1 : -1;
- }
- }
- catch (ParseException e)
- {
- // we'll do our best and ignore daylight savings
- }
-
- return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+ super(bytes);
}
- private String convert(int time)
+ public DERGeneralizedTime(Date time)
{
- if (time < 10)
- {
- return "0" + time;
- }
-
- return Integer.toString(time);
- }
-
- public Date getDate()
- throws ParseException
- {
- SimpleDateFormat dateF;
- String stime = Strings.fromByteArray(time);
- String d = stime;
-
- if (stime.endsWith("Z"))
- {
- if (hasFractionalSeconds())
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
- }
- else
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
- }
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
- }
- else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0)
- {
- d = this.getTime();
- if (hasFractionalSeconds())
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
- }
- else
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
- }
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
- }
- else
- {
- if (hasFractionalSeconds())
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
- }
- else
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss");
- }
-
- dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
- }
-
- if (hasFractionalSeconds())
- {
- // java misinterprets extra digits as being milliseconds...
- String frac = d.substring(14);
- int index;
- for (index = 1; index < frac.length(); index++)
- {
- char ch = frac.charAt(index);
- if (!('0' <= ch && ch <= '9'))
- {
- break;
- }
- }
-
- if (index - 1 > 3)
- {
- frac = frac.substring(0, 4) + frac.substring(index);
- d = d.substring(0, 14) + frac;
- }
- else if (index - 1 == 1)
- {
- frac = frac.substring(0, index) + "00" + frac.substring(index);
- d = d.substring(0, 14) + frac;
- }
- else if (index - 1 == 2)
- {
- frac = frac.substring(0, index) + "0" + frac.substring(index);
- d = d.substring(0, 14) + frac;
- }
- }
-
- return dateF.parse(d);
+ super(time);
}
- private boolean hasFractionalSeconds()
+ public DERGeneralizedTime(String time)
{
- for (int i = 0; i != time.length; i++)
- {
- if (time[i] == '.')
- {
- if (i == 14)
- {
- return true;
- }
- }
- }
- return false;
+ super(time);
}
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- int length = time.length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.GENERALIZED_TIME, time);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERGeneralizedTime))
- {
- return false;
- }
-
- return Arrays.areEqual(time, ((DERGeneralizedTime)o).time);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
- }
+ // TODO: create proper DER encoding.
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java
index 631672e..1c533b1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java
@@ -17,7 +17,9 @@ public class DERIA5String
/**
* return a IA5 string from the passed in object
*
+ * @param obj a DERIA5String or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERIA5String instance, or null.
*/
public static DERIA5String getInstance(
Object obj)
@@ -50,6 +52,7 @@ public class DERIA5String
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return a DERIA5String instance, or null.
*/
public static DERIA5String getInstance(
ASN1TaggedObject obj,
@@ -69,6 +72,7 @@ public class DERIA5String
/**
* basic constructor - with bytes.
+ * @param string the byte encoding of the characters making up the string.
*/
DERIA5String(
byte[] string)
@@ -78,6 +82,7 @@ public class DERIA5String
/**
* basic constructor - without validation.
+ * @param string the base string to use..
*/
public DERIA5String(
String string)
@@ -163,7 +168,8 @@ public class DERIA5String
* return true if the passed in String can be represented without
* loss as an IA5String, false otherwise.
*
- * @return true if in printable set, false otherwise.
+ * @param str the string to check.
+ * @return true if character set in IA5String set, false otherwise.
*/
public static boolean isIA5String(
String str)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java
index 57cc84a..d2e850f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java
@@ -1,160 +1,30 @@
package org.bouncycastle.asn1;
-import java.io.IOException;
import java.math.BigInteger;
-import org.bouncycastle.util.Arrays;
-
/**
- * Use ASN1Integer instead of this,
+ * @deprecated Use ASN1Integer instead of this,
*/
public class DERInteger
- extends ASN1Primitive
+ extends ASN1Integer
{
- byte[] bytes;
-
- /**
- * return an integer from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1Integer getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Integer)
- {
- return (ASN1Integer)obj;
- }
- if (obj instanceof DERInteger)
- {
- return new ASN1Integer((((DERInteger)obj).getValue()));
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (ASN1Integer)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
/**
- * return an Integer from a tagged object.
+ * Constructor from a byte array containing a signed representation of the number.
*
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1Integer getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERInteger)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets());
- }
- }
-
- /**
- * @deprecated use ASN1Integer constructor
- */
- public DERInteger(
- long value)
- {
- bytes = BigInteger.valueOf(value).toByteArray();
- }
-
- /**
- * @deprecated use ASN1Integer constructor
+ * @param bytes a byte array containing the signed number.A copy is made of the byte array.
*/
- public DERInteger(
- BigInteger value)
+ public DERInteger(byte[] bytes)
{
- bytes = value.toByteArray();
+ super(bytes, true);
}
- /**
- * @deprecated use ASN1Integer constructor
- */
- public DERInteger(
- byte[] bytes)
+ public DERInteger(BigInteger value)
{
- this.bytes = bytes;
- }
-
- public BigInteger getValue()
- {
- return new BigInteger(bytes);
- }
-
- /**
- * in some cases positive values get crammed into a space,
- * that's not quite big enough...
- */
- public BigInteger getPositiveValue()
- {
- return new BigInteger(1, bytes);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.INTEGER, bytes);
- }
-
- public int hashCode()
- {
- int value = 0;
-
- for (int i = 0; i != bytes.length; i++)
- {
- value ^= (bytes[i] & 0xff) << (i % 4);
- }
-
- return value;
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERInteger))
- {
- return false;
- }
-
- DERInteger other = (DERInteger)o;
-
- return Arrays.areEqual(bytes, other.bytes);
+ super(value);
}
- public String toString()
+ public DERInteger(long value)
{
- return getValue().toString();
+ super(value);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java
index eca4eea..e1b1276 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java
@@ -17,7 +17,9 @@ public class DERNumericString
/**
* return a Numeric string from the passed in object
*
+ * @param obj a DERNumericString or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERNumericString instance, or null
*/
public static DERNumericString getInstance(
Object obj)
@@ -50,6 +52,7 @@ public class DERNumericString
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return a DERNumericString instance, or null.
*/
public static DERNumericString getInstance(
ASN1TaggedObject obj,
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
index b82647e..acb2ada 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
@@ -1,458 +1,24 @@
package org.bouncycastle.asn1;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
/**
- * Use ASN1ObjectIdentifier instead of this,
+ *
+ * @deprecated Use ASN1ObjectIdentifier instead of this,
*/
public class DERObjectIdentifier
- extends ASN1Primitive
+ extends ASN1ObjectIdentifier
{
- String identifier;
-
- private byte[] body;
-
- /**
- * return an OID from the passed in object
- *
- * @throws IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1ObjectIdentifier getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1ObjectIdentifier)
- {
- return (ASN1ObjectIdentifier)obj;
- }
-
- if (obj instanceof DERObjectIdentifier)
- {
- return new ASN1ObjectIdentifier(((DERObjectIdentifier)obj).getId());
- }
-
- if (obj instanceof ASN1Encodable && ((ASN1Encodable)obj).toASN1Primitive() instanceof ASN1ObjectIdentifier)
- {
- return (ASN1ObjectIdentifier)((ASN1Encodable)obj).toASN1Primitive();
- }
-
- if (obj instanceof byte[])
- {
- byte[] enc = (byte[])obj;
- if (enc[0] == BERTags.OBJECT_IDENTIFIER)
- {
- try
- {
- return (ASN1ObjectIdentifier)fromByteArray(enc);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
- }
- }
- else
- { // TODO: this really shouldn't be supported here...
- return ASN1ObjectIdentifier.fromOctetString((byte[])obj);
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Object Identifier from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @throws IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1ObjectIdentifier getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERObjectIdentifier)
- {
- return getInstance(o);
- }
- else
- {
- return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets());
- }
- }
-
- private static final long LONG_LIMIT = (Long.MAX_VALUE >> 7) - 0x7f;
-
- DERObjectIdentifier(
- byte[] bytes)
+ public DERObjectIdentifier(String identifier)
{
- StringBuffer objId = new StringBuffer();
- long value = 0;
- BigInteger bigValue = null;
- boolean first = true;
-
- for (int i = 0; i != bytes.length; i++)
- {
- int b = bytes[i] & 0xff;
-
- if (value <= LONG_LIMIT)
- {
- value += (b & 0x7f);
- if ((b & 0x80) == 0) // end of number reached
- {
- if (first)
- {
- if (value < 40)
- {
- objId.append('0');
- }
- else if (value < 80)
- {
- objId.append('1');
- value -= 40;
- }
- else
- {
- objId.append('2');
- value -= 80;
- }
- first = false;
- }
-
- objId.append('.');
- objId.append(value);
- value = 0;
- }
- else
- {
- value <<= 7;
- }
- }
- else
- {
- if (bigValue == null)
- {
- bigValue = BigInteger.valueOf(value);
- }
- bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
- if ((b & 0x80) == 0)
- {
- if (first)
- {
- objId.append('2');
- bigValue = bigValue.subtract(BigInteger.valueOf(80));
- first = false;
- }
-
- objId.append('.');
- objId.append(bigValue);
- bigValue = null;
- value = 0;
- }
- else
- {
- bigValue = bigValue.shiftLeft(7);
- }
- }
- }
-
- // BEGIN android-changed
- /*
- * Intern the identifier so there aren't hundreds of duplicates
- * (in practice).
- */
- this.identifier = objId.toString().intern();
- // END android-changed
- this.body = Arrays.clone(bytes);
+ super(identifier);
}
- /**
- * @deprecated use ASN1ObjectIdentifier constructor.
- */
- public DERObjectIdentifier(
- String identifier)
+ DERObjectIdentifier(byte[] bytes)
{
- if (identifier == null)
- {
- throw new IllegalArgumentException("'identifier' cannot be null");
- }
- if (!isValidIdentifier(identifier))
- {
- throw new IllegalArgumentException("string " + identifier + " not an OID");
- }
-
- // BEGIN android-changed
- /*
- * Intern the identifier so there aren't hundreds of duplicates
- * (in practice).
- */
- this.identifier = identifier.intern();
- // END android-changed
+ super(bytes);
}
- DERObjectIdentifier(DERObjectIdentifier oid, String branchID)
+ DERObjectIdentifier(ASN1ObjectIdentifier oid, String branch)
{
- if (!isValidBranchID(branchID, 0))
- {
- throw new IllegalArgumentException("string " + branchID + " not a valid OID branch");
- }
-
- this.identifier = oid.getId() + "." + branchID;
- }
-
- public String getId()
- {
- return identifier;
- }
-
- private void writeField(
- ByteArrayOutputStream out,
- long fieldValue)
- {
- byte[] result = new byte[9];
- int pos = 8;
- result[pos] = (byte)((int)fieldValue & 0x7f);
- while (fieldValue >= (1L << 7))
- {
- fieldValue >>= 7;
- result[--pos] = (byte)((int)fieldValue & 0x7f | 0x80);
- }
- out.write(result, pos, 9 - pos);
- }
-
- private void writeField(
- ByteArrayOutputStream out,
- BigInteger fieldValue)
- {
- int byteCount = (fieldValue.bitLength() + 6) / 7;
- if (byteCount == 0)
- {
- out.write(0);
- }
- else
- {
- BigInteger tmpValue = fieldValue;
- byte[] tmp = new byte[byteCount];
- for (int i = byteCount - 1; i >= 0; i--)
- {
- tmp[i] = (byte)((tmpValue.intValue() & 0x7f) | 0x80);
- tmpValue = tmpValue.shiftRight(7);
- }
- tmp[byteCount - 1] &= 0x7f;
- out.write(tmp, 0, tmp.length);
- }
- }
-
- private void doOutput(ByteArrayOutputStream aOut)
- {
- OIDTokenizer tok = new OIDTokenizer(identifier);
- int first = Integer.parseInt(tok.nextToken()) * 40;
-
- String secondToken = tok.nextToken();
- if (secondToken.length() <= 18)
- {
- writeField(aOut, first + Long.parseLong(secondToken));
- }
- else
- {
- writeField(aOut, new BigInteger(secondToken).add(BigInteger.valueOf(first)));
- }
-
- while (tok.hasMoreTokens())
- {
- String token = tok.nextToken();
- if (token.length() <= 18)
- {
- writeField(aOut, Long.parseLong(token));
- }
- else
- {
- writeField(aOut, new BigInteger(token));
- }
- }
- }
-
- protected synchronized byte[] getBody()
- {
- if (body == null)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- doOutput(bOut);
-
- body = bOut.toByteArray();
- }
-
- return body;
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- throws IOException
- {
- int length = getBody().length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- byte[] enc = getBody();
-
- out.write(BERTags.OBJECT_IDENTIFIER);
- out.writeLength(enc.length);
- out.write(enc);
- }
-
- public int hashCode()
- {
- return identifier.hashCode();
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERObjectIdentifier))
- {
- return false;
- }
-
- return identifier.equals(((DERObjectIdentifier)o).identifier);
- }
-
- public String toString()
- {
- return getId();
- }
-
- private static boolean isValidBranchID(
- String branchID, int start)
- {
- boolean periodAllowed = false;
-
- int pos = branchID.length();
- while (--pos >= start)
- {
- char ch = branchID.charAt(pos);
-
- // TODO Leading zeroes?
- if ('0' <= ch && ch <= '9')
- {
- periodAllowed = true;
- continue;
- }
-
- if (ch == '.')
- {
- if (!periodAllowed)
- {
- return false;
- }
-
- periodAllowed = false;
- continue;
- }
-
- return false;
- }
-
- return periodAllowed;
- }
-
- private static boolean isValidIdentifier(
- String identifier)
- {
- if (identifier.length() < 3 || identifier.charAt(1) != '.')
- {
- return false;
- }
-
- char first = identifier.charAt(0);
- if (first < '0' || first > '2')
- {
- return false;
- }
-
- return isValidBranchID(identifier, 2);
- }
-
- private static ASN1ObjectIdentifier[][] cache = new ASN1ObjectIdentifier[256][];
-
- static ASN1ObjectIdentifier fromOctetString(byte[] enc)
- {
- if (enc.length < 3)
- {
- return new ASN1ObjectIdentifier(enc);
- }
-
- int idx1 = enc[enc.length - 2] & 0xff;
- // in this case top bit is always zero
- int idx2 = enc[enc.length - 1] & 0x7f;
-
- ASN1ObjectIdentifier possibleMatch;
-
- synchronized (cache)
- {
- ASN1ObjectIdentifier[] first = cache[idx1];
- if (first == null)
- {
- first = cache[idx1] = new ASN1ObjectIdentifier[128];
- }
-
- possibleMatch = first[idx2];
- if (possibleMatch == null)
- {
- return first[idx2] = new ASN1ObjectIdentifier(enc);
- }
-
- if (Arrays.areEqual(enc, possibleMatch.getBody()))
- {
- return possibleMatch;
- }
-
- idx1 = (idx1 + 1) & 0xff;
- first = cache[idx1];
- if (first == null)
- {
- first = cache[idx1] = new ASN1ObjectIdentifier[128];
- }
-
- possibleMatch = first[idx2];
- if (possibleMatch == null)
- {
- return first[idx2] = new ASN1ObjectIdentifier(enc);
- }
-
- if (Arrays.areEqual(enc, possibleMatch.getBody()))
- {
- return possibleMatch;
- }
-
- idx2 = (idx2 + 1) & 0x7f;
- possibleMatch = first[idx2];
- if (possibleMatch == null)
- {
- return first[idx2] = new ASN1ObjectIdentifier(enc);
- }
- }
-
- if (Arrays.areEqual(enc, possibleMatch.getBody()))
- {
- return possibleMatch;
- }
-
- return new ASN1ObjectIdentifier(enc);
+ super(oid, branch);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java
index 59d0110..7d56b49 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java
@@ -18,8 +18,10 @@ public class DERPrintableString
/**
* return a printable string from the passed in object.
- *
+ *
+ * @param obj a DERPrintableString or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERPrintableString instance, or null.
*/
public static DERPrintableString getInstance(
Object obj)
@@ -52,6 +54,7 @@ public class DERPrintableString
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return a DERPrintableString instance, or null.
*/
public static DERPrintableString getInstance(
ASN1TaggedObject obj,
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java
index d50fb7c..783cd33 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java
@@ -18,7 +18,9 @@ public class DERT61String
/**
* return a T61 string from the passed in object.
*
+ * @param obj a DERT61String or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERT61String instance, or null
*/
public static DERT61String getInstance(
Object obj)
@@ -51,6 +53,7 @@ public class DERT61String
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return a DERT61String instance, or null
*/
public static DERT61String getInstance(
ASN1TaggedObject obj,
@@ -70,6 +73,8 @@ public class DERT61String
/**
* basic constructor - string encoded as a sequence of bytes.
+ *
+ * @param string the byte encoding of the string to be wrapped.
*/
public DERT61String(
byte[] string)
@@ -79,6 +84,8 @@ public class DERT61String
/**
* basic constructor - with string 8 bit assumed.
+ *
+ * @param string the string to be wrapped.
*/
public DERT61String(
String string)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERUTCTime.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERUTCTime.java
index c5bd536..18e17b1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERUTCTime.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERUTCTime.java
@@ -1,278 +1,27 @@
package org.bouncycastle.asn1;
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.Date;
-import java.util.SimpleTimeZone;
-
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
/**
- * UTC time object.
+ * DER UTC time object.
*/
public class DERUTCTime
- extends ASN1Primitive
+ extends ASN1UTCTime
{
- private byte[] time;
-
- /**
- * return an UTC Time from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1UTCTime getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1UTCTime)
- {
- return (ASN1UTCTime)obj;
- }
-
- if (obj instanceof DERUTCTime)
- {
- return new ASN1UTCTime(((DERUTCTime)obj).time);
- }
-
- if (obj instanceof byte[])
- {
- try
- {
- return (ASN1UTCTime)fromByteArray((byte[])obj);
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
- }
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an UTC Time from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1UTCTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Object o = obj.getObject();
-
- if (explicit || o instanceof ASN1UTCTime)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
- * never encoded. When you're creating one of these objects from scratch, that's
- * what you want to use, otherwise we'll try to deal with whatever gets read from
- * the input stream... (this is why the input format is different from the getTime()
- * method output).
- * <p>
- *
- * @param time the time string.
- */
- public DERUTCTime(
- String time)
- {
- this.time = Strings.toByteArray(time);
- try
- {
- this.getDate();
- }
- catch (ParseException e)
- {
- throw new IllegalArgumentException("invalid date string: " + e.getMessage());
- }
- }
-
- /**
- * base constructer from a java.util.date object
- */
- public DERUTCTime(
- Date time)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- this.time = Strings.toByteArray(dateF.format(time));
- }
-
- DERUTCTime(
- byte[] time)
- {
- this.time = time;
- }
-
- /**
- * return the time as a date based on whatever a 2 digit year will return. For
- * standardised processing use getAdjustedDate().
- *
- * @return the resulting date
- * @exception ParseException if the date string cannot be parsed.
- */
- public Date getDate()
- throws ParseException
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
-
- return dateF.parse(getTime());
- }
-
- /**
- * return the time as an adjusted date
- * in the range of 1950 - 2049.
- *
- * @return a date in the range of 1950 to 2049.
- * @exception ParseException if the date string cannot be parsed.
- */
- public Date getAdjustedDate()
- throws ParseException
+ DERUTCTime(byte[] bytes)
{
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
-
- return dateF.parse(getAdjustedTime());
- }
-
- /**
- * return the time - always in the form of
- * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- * <p>
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- * <pre>
- * dateF = new SimpleDateFormat("yyMMddHHmmssz");
- * </pre>
- * To read in the time and get a date which is compatible with our local
- * time zone.
- * <p>
- * <b>Note:</b> In some cases, due to the local date processing, this
- * may lead to unexpected results. If you want to stick the normal
- * convention of 1950 to 2049 use the getAdjustedTime() method.
- */
- public String getTime()
- {
- String stime = Strings.fromByteArray(time);
-
- //
- // standardise the format.
- //
- if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
- {
- if (stime.length() == 11)
- {
- return stime.substring(0, 10) + "00GMT+00:00";
- }
- else
- {
- return stime.substring(0, 12) + "GMT+00:00";
- }
- }
- else
- {
- int index = stime.indexOf('-');
- if (index < 0)
- {
- index = stime.indexOf('+');
- }
- String d = stime;
-
- if (index == stime.length() - 3)
- {
- d += "00";
- }
-
- if (index == 10)
- {
- return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
- }
- else
- {
- return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
- }
- }
- }
-
- /**
- * return a time string as an adjusted date with a 4 digit year. This goes
- * in the range of 1950 - 2049.
- */
- public String getAdjustedTime()
- {
- String d = this.getTime();
-
- if (d.charAt(0) < '5')
- {
- return "20" + d;
- }
- else
- {
- return "19" + d;
- }
- }
-
- boolean isConstructed()
- {
- return false;
+ super(bytes);
}
- int encodedLength()
+ public DERUTCTime(Date time)
{
- int length = time.length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
+ super(time);
}
- void encode(
- ASN1OutputStream out)
- throws IOException
+ public DERUTCTime(String time)
{
- out.write(BERTags.UTC_TIME);
-
- int length = time.length;
-
- out.writeLength(length);
-
- for (int i = 0; i != length; i++)
- {
- out.write((byte)time[i]);
- }
+ super(time);
}
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERUTCTime))
- {
- return false;
- }
- return Arrays.areEqual(time, ((DERUTCTime)o).time);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
- }
-
- public String toString()
- {
- return Strings.fromByteArray(time);
- }
+ // TODO: create proper DER encoding.
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERUTF8String.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERUTF8String.java
index fa34b22..f54d1db 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERUTF8String.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERUTF8String.java
@@ -15,10 +15,12 @@ public class DERUTF8String
private byte[] string;
/**
- * return an UTF8 string from the passed in object.
- *
+ * Return an UTF8 string from the passed in object.
+ *
+ * @param obj a DERUTF8String or an object that can be converted into one.
* @exception IllegalArgumentException
* if the object cannot be converted.
+ * @return a DERUTF8String instance, or null
*/
public static DERUTF8String getInstance(Object obj)
{
@@ -44,7 +46,7 @@ public class DERUTF8String
}
/**
- * return an UTF8 String from a tagged object.
+ * Return an UTF8 String from a tagged object.
*
* @param obj
* the tagged object holding the object we want
@@ -53,6 +55,7 @@ public class DERUTF8String
* otherwise.
* @exception IllegalArgumentException
* if the tagged object cannot be converted.
+ * @return a DERUTF8String instance, or null
*/
public static DERUTF8String getInstance(
ASN1TaggedObject obj,
@@ -71,7 +74,7 @@ public class DERUTF8String
}
/**
- * basic constructor - byte encoded string.
+ * Basic constructor - byte encoded string.
*/
DERUTF8String(byte[] string)
{
@@ -79,7 +82,7 @@ public class DERUTF8String
}
/**
- * basic constructor
+ * Basic constructor
*/
public DERUTF8String(String string)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java
index 51b0799..0d447df 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java
@@ -18,7 +18,9 @@ public class DERUniversalString
/**
* return a Universal String from the passed in object.
*
+ * @param obj a DERUniversalString or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERUniversalString instance, or null
*/
public static DERUniversalString getInstance(
Object obj)
@@ -51,6 +53,7 @@ public class DERUniversalString
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return a DERUniversalString instance, or null
*/
public static DERUniversalString getInstance(
ASN1TaggedObject obj,
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERVisibleString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERVisibleString.java
index 18e7d73..6eb282c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERVisibleString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERVisibleString.java
@@ -6,7 +6,10 @@ import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;
/**
- * DER VisibleString object.
+ * DER VisibleString object encoding ISO 646 (ASCII) character code points 32 to 126.
+ * <p>
+ * Explicit character set escape sequences are not allowed.
+ * </p>
*/
public class DERVisibleString
extends ASN1Primitive
@@ -15,9 +18,11 @@ public class DERVisibleString
private byte[] string;
/**
- * return a Visible String from the passed in object.
+ * Return a Visible String from the passed in object.
*
+ * @param obj a DERVisibleString or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
+ * @return a DERVisibleString instance, or null
*/
public static DERVisibleString getInstance(
Object obj)
@@ -43,13 +48,14 @@ public class DERVisibleString
}
/**
- * return a Visible String from a tagged object.
+ * Return a Visible String from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
+ * @return a DERVisibleString instance, or null
*/
public static DERVisibleString getInstance(
ASN1TaggedObject obj,
@@ -68,7 +74,7 @@ public class DERVisibleString
}
/**
- * basic constructor - byte encoded string.
+ * Basic constructor - byte encoded string.
*/
DERVisibleString(
byte[] string)
@@ -77,7 +83,7 @@ public class DERVisibleString
}
/**
- * basic constructor
+ * Basic constructor
*/
public DERVisibleString(
String string)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java
index 91e83fa..e3042c2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java
@@ -11,13 +11,13 @@ import java.util.Enumeration;
* <h3>8: Basic encoding rules</h3>
* <h4>8.11 Encoding of a set value </h4>
* <b>8.11.1</b> The encoding of a set value shall be constructed
- * <p/>
+ * <p>
* <b>8.11.2</b> The contents octets shall consist of the complete
* encoding of a data value from each of the types listed in the
* ASN.1 definition of the set type, in an order chosen by the sender,
* unless the type was referenced with the keyword
* <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
- * <p/>
+ * <p>
* <b>8.11.3</b> The encoding of a data value may, but need not,
* be present for a type which was referenced with the keyword
* <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java b/bcprov/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java
index a4b1492..9374ab7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/InMemoryRepresentable.java
@@ -2,8 +2,15 @@ package org.bouncycastle.asn1;
import java.io.IOException;
+/**
+ * Interface implemented by objects that can be converted from streaming to in-memory objects.
+ */
public interface InMemoryRepresentable
{
+ /**
+ * Get the in-memory representation of the ASN.1 object.
+ * @throws IOException for bad input data.
+ */
ASN1Primitive getLoadedObject()
throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
index 066cf69..8c48743 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
@@ -7,7 +7,6 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
/**
@@ -73,17 +72,6 @@ public class Attribute
attrValues = (ASN1Set)seq.getObjectAt(1);
}
- /**
- * @deprecated use ASN1ObjectIdentifier
- */
- public Attribute(
- DERObjectIdentifier attrType,
- ASN1Set attrValues)
- {
- this.attrType = new ASN1ObjectIdentifier(attrType.getId());
- this.attrValues = attrValues;
- }
-
public Attribute(
ASN1ObjectIdentifier attrType,
ASN1Set attrValues)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
index 02b6cc1..3b8e0be 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
@@ -8,7 +8,6 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSet;
/**
@@ -91,14 +90,6 @@ public class AttributeTable
}
/**
- * @deprecated use ASN1ObjectIdentifier
- */
- public Attribute get(DERObjectIdentifier oid)
- {
- return get(new ASN1ObjectIdentifier(oid.getId()));
- }
-
- /**
* Return the first attribute matching the OBJECT IDENTIFIER oid.
*
* @param oid type of attribute required.
@@ -117,14 +108,6 @@ public class AttributeTable
return (Attribute)value;
}
- /**
- * @deprecated use ASN1ObjectIdentifier
- */
- public ASN1EncodableVector getAll(DERObjectIdentifier oid)
- {
- return getAll(new ASN1ObjectIdentifier(oid.getId()));
- }
-
/**
* Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be
* empty if there are no attributes of the required type present.
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java
index 977fce6..84f12a9 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java
@@ -3,12 +3,15 @@ package org.bouncycastle.asn1.cms;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
import java.util.SimpleTimeZone;
import org.bouncycastle.asn1.ASN1Choice;
+import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.ASN1UTCTime;
import org.bouncycastle.asn1.DERGeneralizedTime;
import org.bouncycastle.asn1.DERUTCTime;
@@ -47,8 +50,8 @@ public class Time
public Time(
ASN1Primitive time)
{
- if (!(time instanceof DERUTCTime)
- && !(time instanceof DERGeneralizedTime))
+ if (!(time instanceof ASN1UTCTime)
+ && !(time instanceof ASN1GeneralizedTime))
{
throw new IllegalArgumentException("unknown object passed to Time");
}
@@ -57,28 +60,61 @@ public class Time
}
/**
- * Create a time object from a given date - if the year is in between 1950
+ * Creates a time object from a given date - if the date is between 1950
* and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
* is used.
+ *
+ * @param time a date object representing the time of interest.
*/
public Time(
- Date date)
+ Date time)
{
SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
dateF.setTimeZone(tz);
- String d = dateF.format(date) + "Z";
+ String d = dateF.format(time) + "Z";
+ int year = Integer.parseInt(d.substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ this.time = new DERGeneralizedTime(d);
+ }
+ else
+ {
+ this.time = new DERUTCTime(d.substring(2));
+ }
+ }
+
+ /**
+ * Creates a time object from a given date and locale - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used. You may need to use this constructor if the default locale
+ * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
+ *
+ * @param time a date object representing the time of interest.
+ * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
+ */
+ public Time(
+ Date time,
+ Locale locale)
+ {
+ SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale);
+
+ dateF.setTimeZone(tz);
+
+ String d = dateF.format(time) + "Z";
int year = Integer.parseInt(d.substring(0, 4));
if (year < 1950 || year > 2049)
{
- time = new DERGeneralizedTime(d);
+ this.time = new DERGeneralizedTime(d);
}
else
{
- time = new DERUTCTime(d.substring(2));
+ this.time = new DERUTCTime(d.substring(2));
}
}
@@ -103,13 +139,13 @@ public class Time
{
return (Time)obj;
}
- else if (obj instanceof DERUTCTime)
+ else if (obj instanceof ASN1UTCTime)
{
- return new Time((DERUTCTime)obj);
+ return new Time((ASN1UTCTime)obj);
}
- else if (obj instanceof DERGeneralizedTime)
+ else if (obj instanceof ASN1GeneralizedTime)
{
- return new Time((DERGeneralizedTime)obj);
+ return new Time((ASN1GeneralizedTime)obj);
}
throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
@@ -120,13 +156,13 @@ public class Time
*/
public String getTime()
{
- if (time instanceof DERUTCTime)
+ if (time instanceof ASN1UTCTime)
{
- return ((DERUTCTime)time).getAdjustedTime();
+ return ((ASN1UTCTime)time).getAdjustedTime();
}
else
{
- return ((DERGeneralizedTime)time).getTime();
+ return ((ASN1GeneralizedTime)time).getTime();
}
}
@@ -137,13 +173,13 @@ public class Time
{
try
{
- if (time instanceof DERUTCTime)
+ if (time instanceof ASN1UTCTime)
{
- return ((DERUTCTime)time).getAdjustedDate();
+ return ((ASN1UTCTime)time).getAdjustedDate();
}
else
{
- return ((DERGeneralizedTime)time).getDate();
+ return ((ASN1GeneralizedTime)time).getDate();
}
}
catch (ParseException e)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
index 77416dc..805a506 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
@@ -4,17 +4,17 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
/**
* German Federal Office for Information Security
- * (Bundesamt für Sicherheit in der Informationstechnik)
+ * (Bundesamt f&uuml;r Sicherheit in der Informationstechnik)
* <a href="http://www.bsi.bund.de/">http://www.bsi.bund.de/</a>
* <p>
* <a href="https://www.bsi.bund.de/EN/Publications/TechnicalGuidelines/TR03110/BSITR03110.html">BSI TR-03110</a>
* Technical Guideline Advanced Security Mechanisms for Machine Readable Travel Documents
* <p>
- * <a href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03110/TR-03110_v2.1_P3pdf.pdf?__blob=publicationFile">Technical Guideline TR-03110-3</a>
+ * <a href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03110/TR-03110_v2.1_P3pdf.pdf">
+ * Technical Guideline TR-03110-3</a>
* Advanced Security Mechanisms for Machine Readable Travel Documents;
* Part 3: Common Specifications.
*/
-
public interface EACObjectIdentifiers
{
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
index 6aff988..dfc3121 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
@@ -36,7 +36,7 @@ public interface MiscObjectIdentifiers
/** Verisign CZAG (Country,Zip,Age,Gender) Extension OID: 2.16.840.1.113733.1.6.3 */
static final ASN1ObjectIdentifier verisignCzagExtension = verisign.branch("6.3");
- /** Verisign D&B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15 */
+ /** Verisign D&amp;B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15 */
static final ASN1ObjectIdentifier verisignDnbDunsNumber = verisign.branch("6.15");
//
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java
index b91c1a5..0620873 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java
@@ -56,19 +56,19 @@ public class CRLBag
/**
* <pre>
- CRLBag ::= SEQUENCE {
- crlId BAG-TYPE.&id ({CRLTypes}),
- crlValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId})
- }
-
- x509CRL BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1}
- -- DER-encoded X.509 CRL stored in OCTET STRING
-
- CRLTypes BAG-TYPE ::= {
- x509CRL,
- ... -- For future extensions
- }
- </pre>
+ * CRLBag ::= SEQUENCE {
+ * crlId BAG-TYPE.&amp;id ({CRLTypes}),
+ * crlValue [0] EXPLICIT BAG-TYPE.&amp;Type ({CRLTypes}{@crlId})
+ * }
+ *
+ * x509CRL BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1}
+ * -- DER-encoded X.509 CRL stored in OCTET STRING
+ *
+ * CRLTypes BAG-TYPE ::= {
+ * x509CRL,
+ * ... -- For future extensions
+ * }
+ * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
index c9c14fe..d2acd30 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
@@ -25,8 +25,8 @@ import org.bouncycastle.asn1.x509.X509Name;
* Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
*
* Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
- * type ATTRIBUTE.&id({IOSet}),
- * values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+ * type ATTRIBUTE.&amp;id({IOSet}),
+ * values SET SIZE(1..MAX) OF ATTRIBUTE.&amp;Type({IOSet}{\@type})
* }
* </pre>
*/
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
index c885a6c..848f4fc 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
@@ -25,7 +25,7 @@ public class EncryptionScheme
this.algId = AlgorithmIdentifier.getInstance(seq);
}
- public static final EncryptionScheme getInstance(Object obj)
+ public static EncryptionScheme getInstance(Object obj)
{
if (obj instanceof EncryptionScheme)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java
index 3b40836..83804f3 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java
@@ -25,7 +25,7 @@ public class KeyDerivationFunc
this.algId = AlgorithmIdentifier.getInstance(seq);
}
- public static final KeyDerivationFunc getInstance(Object obj)
+ public static KeyDerivationFunc getInstance(Object obj)
{
if (obj instanceof KeyDerivationFunc)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
index dad8650..7f02e70 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
@@ -68,7 +68,7 @@ public class PrivateKeyInfo
}
/**
- * @deprectaed use PrivateKeyInfo.getInstance()
+ * @deprecated use PrivateKeyInfo.getInstance()
* @param seq
*/
public PrivateKeyInfo(
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
index 50a7a63..ed7a8d8 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
@@ -10,6 +10,8 @@ import org.bouncycastle.asn1.x9.X9ECParametersHolder;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism;
+import org.bouncycastle.math.ec.endo.GLVTypeBParameters;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;
@@ -17,19 +19,14 @@ public class SECNamedCurves
{
private static ECCurve configureCurve(ECCurve curve)
{
-// int coord = ECCurve.COORD_JACOBIAN_MODIFIED;
-//
-// if (curve.getCoordinateSystem() != coord && curve.supportsCoordinateSystem(coord))
-// {
-// return curve.configure()
-// .setCoordinateSystem(coord)
-//// .setMultiplier(new WNafL2RMultiplier())
-// .create();
-// }
-
return curve;
}
+ private static ECCurve configureCurveGLV(ECCurve c, GLVTypeBParameters p)
+ {
+ return c.configure().setEndomorphism(new GLVTypeBEndomorphism(c, p)).create();
+ }
+
private static BigInteger fromHex(
String hex)
{
@@ -51,7 +48,7 @@ public class SECNamedCurves
BigInteger n = fromHex("DB7C2ABF62E35E7628DFAC6561C5");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "09487239995A5EE76B55F9C2F098"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -77,7 +74,7 @@ public class SECNamedCurves
BigInteger n = fromHex("36DF0AAFD8B8D7597CA10520D04B");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "4BA30AB5E892B4E1649DD0928643"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -103,7 +100,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFE0000000075A30D1B9038A115");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "161FF7528B899B2D0C28607CA52C5B86"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -129,7 +126,7 @@ public class SECNamedCurves
BigInteger n = fromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "7B6AA5D85E572983E6FB32A7CDEBC140"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -155,7 +152,20 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a", 16),
+ new BigInteger("c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4", 16),
+ new BigInteger[]{
+ new BigInteger("9162fbe73984472a0a9e", 16),
+ new BigInteger("-96341f1138933bc2f505", 16) },
+ new BigInteger[]{
+ new BigInteger("127971af8721782ecffa3", 16),
+ new BigInteger("9162fbe73984472a0a9e", 16) },
+ new BigInteger("9162fbe73984472a0a9d0590", 16),
+ new BigInteger("96341f1138933bc2f503fd44", 16),
+ 176);
+
+ ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
// ECPoint G = curve.decodePoint(Hex.decode("02"
// + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -181,7 +191,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000000001F4C8F927AED3CA752257");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "4A96B5688EF573284664698968C38BB913CBFC82"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -207,7 +217,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000000000351EE786A818F3A1A16B");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -233,7 +243,20 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
+ new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
+ new BigInteger[]{
+ new BigInteger("71169be7330b3038edb025f1", 16),
+ new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
+ new BigInteger[]{
+ new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
+ new BigInteger("71169be7330b3038edb025f1", 16) },
+ new BigInteger("71169be7330b3038edb025f1d0f9", 16),
+ new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
+ 208);
+
+ ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -259,7 +282,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -285,7 +308,20 @@ public class SECNamedCurves
BigInteger n = fromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
+ new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
+ new BigInteger[]{
+ new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
+ new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
+ new BigInteger[]{
+ new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
+ new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
+ new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
+ new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
+ 240);
+
+ ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -311,7 +347,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -337,7 +373,20 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
+ new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
+ new BigInteger[]{
+ new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
+ new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
+ new BigInteger[]{
+ new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
+ new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
+ new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
+ new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
+ 272);
+
+ ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv);
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -363,7 +412,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -389,7 +438,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -415,7 +464,7 @@ public class SECNamedCurves
BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"));
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
index 895f5e8..2be7efe 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
@@ -41,35 +41,35 @@ public interface TeleTrusTObjectIdentifiers
static final ASN1ObjectIdentifier ecc_brainpool = teleTrusTAlgorithm.branch("3.2.8");
/** 1.3.36.3.3.2.8.1 */
static final ASN1ObjectIdentifier ellipticCurve = ecc_brainpool.branch("1");
- /** 1.3.36.3.3.2.8.1 */
+ /** 1.3.36.3.3.2.8.1.1 */
static final ASN1ObjectIdentifier versionOne = ellipticCurve.branch("1");
- /** 1.3.36.3.3.2.8.1.1 */
+ /** 1.3.36.3.3.2.8.1.1.1 */
static final ASN1ObjectIdentifier brainpoolP160r1 = versionOne.branch("1");
- /** 1.3.36.3.3.2.8.1.2 */
+ /** 1.3.36.3.3.2.8.1.1.2 */
static final ASN1ObjectIdentifier brainpoolP160t1 = versionOne.branch("2");
- /** 1.3.36.3.3.2.8.1.3 */
+ /** 1.3.36.3.3.2.8.1.1.3 */
static final ASN1ObjectIdentifier brainpoolP192r1 = versionOne.branch("3");
- /** 1.3.36.3.3.2.8.1.4 */
+ /** 1.3.36.3.3.2.8.1.1.4 */
static final ASN1ObjectIdentifier brainpoolP192t1 = versionOne.branch("4");
- /** 1.3.36.3.3.2.8.1.5 */
+ /** 1.3.36.3.3.2.8.1.1.5 */
static final ASN1ObjectIdentifier brainpoolP224r1 = versionOne.branch("5");
- /** 1.3.36.3.3.2.8.1.6 */
+ /** 1.3.36.3.3.2.8.1.1.6 */
static final ASN1ObjectIdentifier brainpoolP224t1 = versionOne.branch("6");
- /** 1.3.36.3.3.2.8.1.7 */
+ /** 1.3.36.3.3.2.8.1.1.7 */
static final ASN1ObjectIdentifier brainpoolP256r1 = versionOne.branch("7");
- /** 1.3.36.3.3.2.8.1.8 */
+ /** 1.3.36.3.3.2.8.1.1.8 */
static final ASN1ObjectIdentifier brainpoolP256t1 = versionOne.branch("8");
- /** 1.3.36.3.3.2.8.1.9 */
+ /** 1.3.36.3.3.2.8.1.1.9 */
static final ASN1ObjectIdentifier brainpoolP320r1 = versionOne.branch("9");
- /** 1.3.36.3.3.2.8.1.10 */
+ /** 1.3.36.3.3.2.8.1.1.10 */
static final ASN1ObjectIdentifier brainpoolP320t1 = versionOne.branch("10");
- /** 1.3.36.3.3.2.8.1.11 */
+ /** 1.3.36.3.3.2.8.1.1.11 */
static final ASN1ObjectIdentifier brainpoolP384r1 = versionOne.branch("11");
- /** 1.3.36.3.3.2.8.1.12 */
+ /** 1.3.36.3.3.2.8.1.1.12 */
static final ASN1ObjectIdentifier brainpoolP384t1 = versionOne.branch("12");
- /** 1.3.36.3.3.2.8.1.13 */
+ /** 1.3.36.3.3.2.8.1.1.13 */
static final ASN1ObjectIdentifier brainpoolP512r1 = versionOne.branch("13");
- /** 1.3.36.3.3.2.8.1.14 */
+ /** 1.3.36.3.3.2.8.1.1.14 */
static final ASN1ObjectIdentifier brainpoolP512t1 = versionOne.branch("14");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java b/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java
index 5302552..8a454f2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java
@@ -3,7 +3,10 @@ package org.bouncycastle.asn1.util;
import java.io.IOException;
import java.util.Enumeration;
+import org.bouncycastle.asn1.ASN1Boolean;
import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Enumerated;
+import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
@@ -11,8 +14,8 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.ASN1UTCTime;
import org.bouncycastle.asn1.BERApplicationSpecific;
-import org.bouncycastle.asn1.BERConstructedOctetString;
import org.bouncycastle.asn1.BEROctetString;
import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.BERSet;
@@ -21,16 +24,12 @@ import org.bouncycastle.asn1.BERTags;
import org.bouncycastle.asn1.DERApplicationSpecific;
import org.bouncycastle.asn1.DERBMPString;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERBoolean;
-import org.bouncycastle.asn1.DEREnumerated;
import org.bouncycastle.asn1.DERExternal;
-import org.bouncycastle.asn1.DERGeneralizedTime;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DERPrintableString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERT61String;
-import org.bouncycastle.asn1.DERUTCTime;
import org.bouncycastle.asn1.DERUTF8String;
import org.bouncycastle.asn1.DERVisibleString;
import org.bouncycastle.util.encoders.Hex;
@@ -172,7 +171,7 @@ public class ASN1Dump
{
ASN1OctetString oct = (ASN1OctetString)obj;
- if (obj instanceof BEROctetString || obj instanceof BERConstructedOctetString)
+ if (obj instanceof BEROctetString)
{
buf.append(indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] ");
}
@@ -193,9 +192,9 @@ public class ASN1Dump
{
buf.append(indent + "ObjectIdentifier(" + ((ASN1ObjectIdentifier)obj).getId() + ")" + nl);
}
- else if (obj instanceof DERBoolean)
+ else if (obj instanceof ASN1Boolean)
{
- buf.append(indent + "Boolean(" + ((DERBoolean)obj).isTrue() + ")" + nl);
+ buf.append(indent + "Boolean(" + ((ASN1Boolean)obj).isTrue() + ")" + nl);
}
else if (obj instanceof ASN1Integer)
{
@@ -238,13 +237,13 @@ public class ASN1Dump
{
buf.append(indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl);
}
- else if (obj instanceof DERUTCTime)
+ else if (obj instanceof ASN1UTCTime)
{
- buf.append(indent + "UTCTime(" + ((DERUTCTime)obj).getTime() + ") " + nl);
+ buf.append(indent + "UTCTime(" + ((ASN1UTCTime)obj).getTime() + ") " + nl);
}
- else if (obj instanceof DERGeneralizedTime)
+ else if (obj instanceof ASN1GeneralizedTime)
{
- buf.append(indent + "GeneralizedTime(" + ((DERGeneralizedTime)obj).getTime() + ") " + nl);
+ buf.append(indent + "GeneralizedTime(" + ((ASN1GeneralizedTime)obj).getTime() + ") " + nl);
}
else if (obj instanceof BERApplicationSpecific)
{
@@ -254,9 +253,9 @@ public class ASN1Dump
{
buf.append(outputApplicationSpecific("DER", indent, verbose, obj, nl));
}
- else if (obj instanceof DEREnumerated)
+ else if (obj instanceof ASN1Enumerated)
{
- DEREnumerated en = (DEREnumerated) obj;
+ ASN1Enumerated en = (ASN1Enumerated) obj;
buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl);
}
else if (obj instanceof DERExternal)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java
new file mode 100644
index 0000000..9792d40
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java
@@ -0,0 +1,192 @@
+package org.bouncycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.DERUTF8String;
+import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
+import org.bouncycastle.asn1.x500.RDN;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.X500NameStyle;
+
+/**
+ * This class provides some default behavior and common implementation for a
+ * X500NameStyle. It should be easily extendable to support implementing the
+ * desired X500NameStyle.
+ */
+public abstract class AbstractX500NameStyle
+ implements X500NameStyle
+{
+
+ /**
+ * Tool function to shallow copy a Hashtable.
+ *
+ * @param paramsMap table to copy
+ * @return the copy of the table
+ */
+ public static Hashtable copyHashTable(Hashtable paramsMap)
+ {
+ Hashtable newTable = new Hashtable();
+
+ Enumeration keys = paramsMap.keys();
+ while (keys.hasMoreElements())
+ {
+ Object key = keys.nextElement();
+ newTable.put(key, paramsMap.get(key));
+ }
+
+ return newTable;
+ }
+
+ private int calcHashCode(ASN1Encodable enc)
+ {
+ String value = IETFUtils.valueToString(enc);
+ value = IETFUtils.canonicalize(value);
+ return value.hashCode();
+ }
+
+ public int calculateHashCode(X500Name name)
+ {
+ int hashCodeValue = 0;
+ RDN[] rdns = name.getRDNs();
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != rdns.length; i++)
+ {
+ if (rdns[i].isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ hashCodeValue ^= atv[j].getType().hashCode();
+ hashCodeValue ^= calcHashCode(atv[j].getValue());
+ }
+ }
+ else
+ {
+ hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
+ hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
+ }
+ }
+
+ return hashCodeValue;
+ }
+
+
+ /**
+ * For all string values starting with '#' is assumed, that these are
+ * already valid ASN.1 objects encoded in hex.
+ * <p>
+ * All other string values are send to
+ * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)}.
+ * </p>
+ * Subclasses should overwrite
+ * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)}
+ * to change the encoding of specific types.
+ *
+ * @param oid the DN name of the value.
+ * @param value the String representation of the value.
+ */
+ public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return IETFUtils.valueFromHexString(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+
+ return encodeStringValue(oid, value);
+ }
+
+ /**
+ * Encoded every value into a UTF8String.
+ * <p>
+ * Subclasses should overwrite
+ * this method to change the encoding of specific types.
+ * </p>
+ *
+ * @param oid the DN oid of the value
+ * @param value the String representation of the value
+ * @return a the value encoded into a ASN.1 object. Never returns <code>null</code>.
+ */
+ protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid, String value)
+ {
+ return new DERUTF8String(value);
+ }
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ boolean reverse = false;
+
+ if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
+ {
+ reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!foundMatch(reverse, rdns1[i], rdns2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
+ {
+ if (reverse)
+ {
+ for (int i = possRDNs.length - 1; i >= 0; i--)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i != possRDNs.length; i++)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
+ {
+ return IETFUtils.rDNAreEqual(rdn1, rdn2);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
index 6842182..1c2a926 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
@@ -1,7 +1,5 @@
package org.bouncycastle.asn1.x500.style;
-import java.io.IOException;
-import java.util.Enumeration;
import java.util.Hashtable;
import org.bouncycastle.asn1.ASN1Encodable;
@@ -9,16 +7,14 @@ import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERUTF8String;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameStyle;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
public class BCStyle
- implements X500NameStyle
+ extends AbstractX500NameStyle
{
/**
* country code - StringType(SIZE(2))
@@ -285,42 +281,24 @@ public class BCStyle
defaultSymbols = copyHashTable(DefaultSymbols);
defaultLookUp = copyHashTable(DefaultLookUp);
}
-
- public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
- {
- if (value.length() != 0 && value.charAt(0) == '#')
+
+ protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid,
+ String value) {
+ if (oid.equals(EmailAddress) || oid.equals(DC))
{
- try
- {
- return IETFUtils.valueFromHexString(value, 1);
- }
- catch (IOException e)
- {
- throw new RuntimeException("can't recode value for oid " + oid.getId());
- }
+ return new DERIA5String(value);
}
- else
+ else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
{
- if (value.length() != 0 && value.charAt(0) == '\\')
- {
- value = value.substring(1);
- }
- if (oid.equals(EmailAddress) || oid.equals(DC))
- {
- return new DERIA5String(value);
- }
- else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
- {
- return new ASN1GeneralizedTime(value);
- }
- else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER)
- || oid.equals(TELEPHONE_NUMBER))
- {
- return new DERPrintableString(value);
- }
+ return new ASN1GeneralizedTime(value);
}
-
- return new DERUTF8String(value);
+ else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER)
+ || oid.equals(TELEPHONE_NUMBER))
+ {
+ return new DERPrintableString(value);
+ }
+
+ return super.encodeStringValue(oid, value);
}
public String oidToDisplayName(ASN1ObjectIdentifier oid)
@@ -338,109 +316,11 @@ public class BCStyle
return IETFUtils.decodeAttrName(attrName, defaultLookUp);
}
- public boolean areEqual(X500Name name1, X500Name name2)
- {
- RDN[] rdns1 = name1.getRDNs();
- RDN[] rdns2 = name2.getRDNs();
-
- if (rdns1.length != rdns2.length)
- {
- return false;
- }
-
- boolean reverse = false;
-
- if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
- {
- reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
- }
-
- for (int i = 0; i != rdns1.length; i++)
- {
- if (!foundMatch(reverse, rdns1[i], rdns2))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
- {
- if (reverse)
- {
- for (int i = possRDNs.length - 1; i >= 0; i--)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
- else
- {
- for (int i = 0; i != possRDNs.length; i++)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
-
- return false;
- }
-
- protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
- {
- return IETFUtils.rDNAreEqual(rdn1, rdn2);
- }
-
public RDN[] fromString(String dirName)
{
return IETFUtils.rDNsFromString(dirName, this);
}
- public int calculateHashCode(X500Name name)
- {
- int hashCodeValue = 0;
- RDN[] rdns = name.getRDNs();
-
- // this needs to be order independent, like equals
- for (int i = 0; i != rdns.length; i++)
- {
- if (rdns[i].isMultiValued())
- {
- AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
-
- for (int j = 0; j != atv.length; j++)
- {
- hashCodeValue ^= atv[j].getType().hashCode();
- hashCodeValue ^= calcHashCode(atv[j].getValue());
- }
- }
- else
- {
- hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
- hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
- }
- }
-
- return hashCodeValue;
- }
-
- private int calcHashCode(ASN1Encodable enc)
- {
- String value = IETFUtils.valueToString(enc);
-
- value = IETFUtils.canonicalize(value);
-
- return value.hashCode();
- }
-
public String toString(X500Name name)
{
StringBuffer buf = new StringBuffer();
@@ -465,17 +345,5 @@ public class BCStyle
return buf.toString();
}
- private static Hashtable copyHashTable(Hashtable paramsMap)
- {
- Hashtable newTable = new Hashtable();
- Enumeration keys = paramsMap.keys();
- while (keys.hasMoreElements())
- {
- Object key = keys.nextElement();
- newTable.put(key, paramsMap.get(key));
- }
-
- return newTable;
- }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
index 8c92257..13f6ef1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
@@ -1,21 +1,17 @@
package org.bouncycastle.asn1.x500.style;
-import java.io.IOException;
-import java.util.Enumeration;
import java.util.Hashtable;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameStyle;
public class RFC4519Style
- implements X500NameStyle
+ extends AbstractX500NameStyle
{
public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15");
public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6");
@@ -179,37 +175,19 @@ public class RFC4519Style
defaultLookUp = copyHashTable(DefaultLookUp);
}
- public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
- {
- if (value.length() != 0 && value.charAt(0) == '#')
+ protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid,
+ String value) {
+ if (oid.equals(dc))
{
- try
- {
- return IETFUtils.valueFromHexString(value, 1);
- }
- catch (IOException e)
- {
- throw new RuntimeException("can't recode value for oid " + oid.getId());
- }
+ return new DERIA5String(value);
}
- else
+ else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier)
+ || oid.equals(telephoneNumber))
{
- if (value.length() != 0 && value.charAt(0) == '\\')
- {
- value = value.substring(1);
- }
- if (oid.equals(dc))
- {
- return new DERIA5String(value);
- }
- else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier)
- || oid.equals(telephoneNumber))
- {
- return new DERPrintableString(value);
- }
+ return new DERPrintableString(value);
}
- return new DERUTF8String(value);
+ return super.encodeStringValue(oid, value);
}
public String oidToDisplayName(ASN1ObjectIdentifier oid)
@@ -227,67 +205,6 @@ public class RFC4519Style
return IETFUtils.decodeAttrName(attrName, defaultLookUp);
}
- public boolean areEqual(X500Name name1, X500Name name2)
- {
- RDN[] rdns1 = name1.getRDNs();
- RDN[] rdns2 = name2.getRDNs();
-
- if (rdns1.length != rdns2.length)
- {
- return false;
- }
-
- boolean reverse = false;
-
- if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
- {
- reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
- }
-
- for (int i = 0; i != rdns1.length; i++)
- {
- if (!foundMatch(reverse, rdns1[i], rdns2))
- {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
- {
- if (reverse)
- {
- for (int i = possRDNs.length - 1; i >= 0; i--)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
- else
- {
- for (int i = 0; i != possRDNs.length; i++)
- {
- if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
- {
- possRDNs[i] = null;
- return true;
- }
- }
- }
-
- return false;
- }
-
- protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
- {
- return IETFUtils.rDNAreEqual(rdn1, rdn2);
- }
-
// parse backwards
public RDN[] fromString(String dirName)
{
@@ -302,43 +219,6 @@ public class RFC4519Style
return res;
}
- public int calculateHashCode(X500Name name)
- {
- int hashCodeValue = 0;
- RDN[] rdns = name.getRDNs();
-
- // this needs to be order independent, like equals
- for (int i = 0; i != rdns.length; i++)
- {
- if (rdns[i].isMultiValued())
- {
- AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
-
- for (int j = 0; j != atv.length; j++)
- {
- hashCodeValue ^= atv[j].getType().hashCode();
- hashCodeValue ^= calcHashCode(atv[j].getValue());
- }
- }
- else
- {
- hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
- hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
- }
- }
-
- return hashCodeValue;
- }
-
- private int calcHashCode(ASN1Encodable enc)
- {
- String value = IETFUtils.valueToString(enc);
-
- value = IETFUtils.canonicalize(value);
-
- return value.hashCode();
- }
-
// convert in reverse
public String toString(X500Name name)
{
@@ -364,17 +244,5 @@ public class RFC4519Style
return buf.toString();
}
- private static Hashtable copyHashTable(Hashtable paramsMap)
- {
- Hashtable newTable = new Hashtable();
-
- Enumeration keys = paramsMap.keys();
- while (keys.hasMoreElements())
- {
- Object key = keys.nextElement();
- newTable.put(key, paramsMap.get(key));
- }
-
- return newTable;
- }
+
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java
index 2c8e3fc..b7e52f2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java
@@ -6,7 +6,7 @@ package org.bouncycastle.asn1.x500.style;
* lightweight Java environment don't support classes like
* StringTokenizer.
*/
-class X500NameTokenizer
+public class X500NameTokenizer
{
private String value;
private int index;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
index d250bf1..bb90030 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
@@ -8,7 +8,6 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
public class AlgorithmIdentifier
@@ -64,30 +63,6 @@ public class AlgorithmIdentifier
this.objectId = new ASN1ObjectIdentifier(objectId);
}
- /**
- * @deprecated use ASN1ObjectIdentifier
- * @param objectId
- */
- public AlgorithmIdentifier(
- DERObjectIdentifier objectId)
- {
- this.objectId = new ASN1ObjectIdentifier(objectId.getId());
- }
-
- /**
- * @deprecated use ASN1ObjectIdentifier
- * @param objectId
- * @param parameters
- */
- public AlgorithmIdentifier(
- DERObjectIdentifier objectId,
- ASN1Encodable parameters)
- {
- parametersDefined = true;
- this.objectId = new ASN1ObjectIdentifier(objectId.getId());
- this.parameters = parameters;
- }
-
public AlgorithmIdentifier(
ASN1ObjectIdentifier objectId,
ASN1Encodable parameters)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
index 9c5ed46..20f6ea3 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
@@ -103,7 +103,7 @@ public class AuthorityKeyIdentifier
* publicKey.getEncoded()).readObject());
* AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
* </pre>
- *
+ * @deprecated create the extension using org.bouncycastle.cert.X509ExtensionUtils
**/
public AuthorityKeyIdentifier(
SubjectPublicKeyInfo spki)
@@ -122,6 +122,7 @@ public class AuthorityKeyIdentifier
/**
* create an AuthorityKeyIdentifier with the GeneralNames tag and
* the serial number provided as well.
+ * @deprecated create the extension using org.bouncycastle.cert.X509ExtensionUtils
*/
public AuthorityKeyIdentifier(
SubjectPublicKeyInfo spki,
@@ -150,9 +151,7 @@ public class AuthorityKeyIdentifier
GeneralNames name,
BigInteger serialNumber)
{
- this.keyidentifier = null;
- this.certissuer = GeneralNames.getInstance(name.toASN1Primitive());
- this.certserno = new ASN1Integer(serialNumber);
+ this((byte[])null, name, serialNumber);
}
/**
@@ -161,9 +160,7 @@ public class AuthorityKeyIdentifier
public AuthorityKeyIdentifier(
byte[] keyIdentifier)
{
- this.keyidentifier = new DEROctetString(keyIdentifier);
- this.certissuer = null;
- this.certserno = null;
+ this(keyIdentifier, null, null);
}
/**
@@ -175,9 +172,9 @@ public class AuthorityKeyIdentifier
GeneralNames name,
BigInteger serialNumber)
{
- this.keyidentifier = new DEROctetString(keyIdentifier);
- this.certissuer = GeneralNames.getInstance(name.toASN1Primitive());
- this.certserno = new ASN1Integer(serialNumber);
+ this.keyidentifier = (keyIdentifier != null) ? new DEROctetString(keyIdentifier) : null;
+ this.certissuer = name;
+ this.certserno = (serialNumber != null) ? new ASN1Integer(serialNumber) : null;
}
public byte[] getKeyIdentifier()
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/BasicConstraints.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/BasicConstraints.java
index 4a16bd4..ba5ecf1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/BasicConstraints.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/BasicConstraints.java
@@ -9,7 +9,6 @@ import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBoolean;
import org.bouncycastle.asn1.DERSequence;
public class BasicConstraints
@@ -59,9 +58,9 @@ public class BasicConstraints
}
else
{
- if (seq.getObjectAt(0) instanceof DERBoolean)
+ if (seq.getObjectAt(0) instanceof ASN1Boolean)
{
- this.cA = DERBoolean.getInstance(seq.getObjectAt(0));
+ this.cA = ASN1Boolean.getInstance(seq.getObjectAt(0));
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java
index 1a9400d..5f0cd07 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java
@@ -5,10 +5,6 @@ import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.crypto.Digest;
-// BEGIN android-changed
-import org.bouncycastle.crypto.digests.AndroidDigestFactory;
-// END android-changed
/**
* The SubjectKeyIdentifier object.
@@ -69,71 +65,4 @@ public class SubjectKeyIdentifier
{
return new DEROctetString(keyidentifier);
}
-
-
- /**
- * Calculates the keyidentifier using a SHA1 hash over the BIT STRING
- * from SubjectPublicKeyInfo as defined in RFC3280.
- *
- * @param spki the subject public key info.
- * @deprecated
- */
- public SubjectKeyIdentifier(
- SubjectPublicKeyInfo spki)
- {
- this.keyidentifier = getDigest(spki);
- }
-
- /**
- * Return a RFC 3280 type 1 key identifier. As in:
- * <pre>
- * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
- * value of the BIT STRING subjectPublicKey (excluding the tag,
- * length, and number of unused bits).
- * </pre>
- * @param keyInfo the key info object containing the subjectPublicKey field.
- * @return the key identifier.
- * @deprecated use org.bouncycastle.cert.X509ExtensionUtils.createSubjectKeyIdentifier
- */
- public static SubjectKeyIdentifier createSHA1KeyIdentifier(SubjectPublicKeyInfo keyInfo)
- {
- return new SubjectKeyIdentifier(keyInfo);
- }
-
- /**
- * Return a RFC 3280 type 2 key identifier. As in:
- * <pre>
- * (2) The keyIdentifier is composed of a four bit type field with
- * the value 0100 followed by the least significant 60 bits of the
- * SHA-1 hash of the value of the BIT STRING subjectPublicKey.
- * </pre>
- * @param keyInfo the key info object containing the subjectPublicKey field.
- * @return the key identifier.
- * @deprecated use org.bouncycastle.cert.X509ExtensionUtils.createTruncatedSubjectKeyIdentifier
- */
- public static SubjectKeyIdentifier createTruncatedSHA1KeyIdentifier(SubjectPublicKeyInfo keyInfo)
- {
- byte[] dig = getDigest(keyInfo);
- byte[] id = new byte[8];
-
- System.arraycopy(dig, dig.length - 8, id, 0, id.length);
-
- id[0] &= 0x0f;
- id[0] |= 0x40;
-
- return new SubjectKeyIdentifier(id);
- }
-
- private static byte[] getDigest(SubjectPublicKeyInfo spki)
- {
- // BEGIN android-changed
- Digest digest = AndroidDigestFactory.getSHA1();
- // END android-changed
- byte[] resBuf = new byte[digest.getDigestSize()];
-
- byte[] bytes = spki.getPublicKeyData().getBytes();
- digest.update(bytes, 0, bytes.length);
- digest.doFinal(resBuf, 0);
- return resBuf;
- }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java
index ce657a7..5fdbcd6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java
@@ -3,15 +3,15 @@ package org.bouncycastle.asn1.x509;
import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERGeneralizedTime;
+import org.bouncycastle.asn1.ASN1UTCTime;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTCTime;
import org.bouncycastle.asn1.x500.X500Name;
/**
@@ -190,8 +190,8 @@ public class TBSCertList
thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
if (seqPos < seq.size()
- && (seq.getObjectAt(seqPos) instanceof DERUTCTime
- || seq.getObjectAt(seqPos) instanceof DERGeneralizedTime
+ && (seq.getObjectAt(seqPos) instanceof ASN1UTCTime
+ || seq.getObjectAt(seqPos) instanceof ASN1GeneralizedTime
|| seq.getObjectAt(seqPos) instanceof Time))
{
nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Time.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Time.java
index 5bffedc..77d36b3 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Time.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Time.java
@@ -3,12 +3,15 @@ package org.bouncycastle.asn1.x509;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
import java.util.SimpleTimeZone;
import org.bouncycastle.asn1.ASN1Choice;
+import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.ASN1UTCTime;
import org.bouncycastle.asn1.DERGeneralizedTime;
import org.bouncycastle.asn1.DERUTCTime;
@@ -28,8 +31,8 @@ public class Time
public Time(
ASN1Primitive time)
{
- if (!(time instanceof DERUTCTime)
- && !(time instanceof DERGeneralizedTime))
+ if (!(time instanceof ASN1UTCTime)
+ && !(time instanceof ASN1GeneralizedTime))
{
throw new IllegalArgumentException("unknown object passed to Time");
}
@@ -38,28 +41,61 @@ public class Time
}
/**
- * creates a time object from a given date - if the date is between 1950
+ * Creates a time object from a given date - if the date is between 1950
* and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
* is used.
+ *
+ * @param time a date object representing the time of interest.
*/
public Time(
- Date date)
+ Date time)
{
SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
dateF.setTimeZone(tz);
- String d = dateF.format(date) + "Z";
+ String d = dateF.format(time) + "Z";
int year = Integer.parseInt(d.substring(0, 4));
if (year < 1950 || year > 2049)
{
- time = new DERGeneralizedTime(d);
+ this.time = new DERGeneralizedTime(d);
}
else
{
- time = new DERUTCTime(d.substring(2));
+ this.time = new DERUTCTime(d.substring(2));
+ }
+ }
+
+ /**
+ * Creates a time object from a given date and locale - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used. You may need to use this constructor if the default locale
+ * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
+ *
+ * @param time a date object representing the time of interest.
+ * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
+ */
+ public Time(
+ Date time,
+ Locale locale)
+ {
+ SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale);
+
+ dateF.setTimeZone(tz);
+
+ String d = dateF.format(time) + "Z";
+ int year = Integer.parseInt(d.substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ this.time = new DERGeneralizedTime(d);
+ }
+ else
+ {
+ this.time = new DERUTCTime(d.substring(2));
}
}
@@ -70,13 +106,13 @@ public class Time
{
return (Time)obj;
}
- else if (obj instanceof DERUTCTime)
+ else if (obj instanceof ASN1UTCTime)
{
- return new Time((DERUTCTime)obj);
+ return new Time((ASN1UTCTime)obj);
}
- else if (obj instanceof DERGeneralizedTime)
+ else if (obj instanceof ASN1GeneralizedTime)
{
- return new Time((DERGeneralizedTime)obj);
+ return new Time((ASN1GeneralizedTime)obj);
}
throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
@@ -84,13 +120,13 @@ public class Time
public String getTime()
{
- if (time instanceof DERUTCTime)
+ if (time instanceof ASN1UTCTime)
{
- return ((DERUTCTime)time).getAdjustedTime();
+ return ((ASN1UTCTime)time).getAdjustedTime();
}
else
{
- return ((DERGeneralizedTime)time).getTime();
+ return ((ASN1GeneralizedTime)time).getTime();
}
}
@@ -98,13 +134,13 @@ public class Time
{
try
{
- if (time instanceof DERUTCTime)
+ if (time instanceof ASN1UTCTime)
{
- return ((DERUTCTime)time).getAdjustedDate();
+ return ((ASN1UTCTime)time).getAdjustedDate();
}
else
{
- return ((DERGeneralizedTime)time).getDate();
+ return ((ASN1GeneralizedTime)time).getDate();
}
}
catch (ParseException e)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java
index 3d923b6..d778d7f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java
@@ -2,10 +2,10 @@ package org.bouncycastle.asn1.x509;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1UTCTime;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTCTime;
import org.bouncycastle.asn1.x500.X500Name;
/**
@@ -74,7 +74,7 @@ public class V3TBSCertificateGenerator
}
public void setStartDate(
- DERUTCTime startDate)
+ ASN1UTCTime startDate)
{
this.startDate = new Time(startDate);
}
@@ -86,7 +86,7 @@ public class V3TBSCertificateGenerator
}
public void setEndDate(
- DERUTCTime endDate)
+ ASN1UTCTime endDate)
{
this.endDate = new Time(endDate);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
index f29284d..9353057 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
@@ -2,11 +2,11 @@ package org.bouncycastle.asn1.x509;
import java.io.IOException;
+import org.bouncycastle.asn1.ASN1Boolean;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERBoolean;
/**
* an object for the elements in the X.509 V3 extension block.
@@ -173,7 +173,7 @@ public class X509Extension
ASN1OctetString value;
public X509Extension(
- DERBoolean critical,
+ ASN1Boolean critical,
ASN1OctetString value)
{
this.critical = critical.isTrue();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extensions.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extensions.java
index c72e3cc..5b9ea9e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extensions.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extensions.java
@@ -4,6 +4,7 @@ import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
+import org.bouncycastle.asn1.ASN1Boolean;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -11,8 +12,6 @@ import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBoolean;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
/**
@@ -259,7 +258,7 @@ public class X509Extensions
if (s.size() == 3)
{
- extensions.put(s.getObjectAt(0), new X509Extension(DERBoolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2))));
+ extensions.put(s.getObjectAt(0), new X509Extension(ASN1Boolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2))));
}
else if (s.size() == 2)
{
@@ -369,17 +368,6 @@ public class X509Extensions
* @return the extension if it's present, null otherwise.
*/
public X509Extension getExtension(
- DERObjectIdentifier oid)
- {
- return (X509Extension)extensions.get(oid);
- }
-
- /**
- * @deprecated
- * @param oid
- * @return
- */
- public X509Extension getExtension(
ASN1ObjectIdentifier oid)
{
return (X509Extension)extensions.get(oid);
@@ -410,7 +398,7 @@ public class X509Extensions
if (ext.isCritical())
{
- v.add(DERBoolean.TRUE);
+ v.add(ASN1Boolean.TRUE);
}
v.add(ext.getValue());
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java
index 468d1b9..589d512 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java
@@ -7,7 +7,6 @@ import java.util.Vector;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
/**
@@ -29,28 +28,6 @@ public class X509ExtensionsGenerator
}
/**
- * @deprecated use ASN1ObjectIdentifier
- */
- public void addExtension(
- DERObjectIdentifier oid,
- boolean critical,
- ASN1Encodable value)
- {
- addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value);
- }
-
- /**
- * @deprecated use ASN1ObjectIdentifier
- */
- public void addExtension(
- DERObjectIdentifier oid,
- boolean critical,
- byte[] value)
- {
- addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value);
- }
-
- /**
* Add an extension with the given oid and the passed in value to be included
* in the OCTET STRING associated with the extension.
*
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509NameEntryConverter.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509NameEntryConverter.java
index 5d919e1..188af43 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509NameEntryConverter.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509NameEntryConverter.java
@@ -23,7 +23,7 @@ import org.bouncycastle.util.Strings;
* ASN1ObjectIdentifier oid,
* String value)
* {
- * if (str.length() != 0 && str.charAt(0) == '#')
+ * if (str.length() != 0 &amp;&amp; str.charAt(0) == '#')
* {
* return convertHexEncoded(str, 1);
* }
@@ -45,6 +45,7 @@ import org.bouncycastle.util.Strings;
* }
* }
* }
+ * </pre>
*/
public abstract class X509NameEntryConverter
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java
index 6a97a48..509111a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHDomainParameters.java
@@ -1,5 +1,6 @@
package org.bouncycastle.asn1.x9;
+import java.math.BigInteger;
import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Encodable;
@@ -38,6 +39,29 @@ public class DHDomainParameters
+ obj.getClass().getName());
}
+ public DHDomainParameters(BigInteger p, BigInteger g, BigInteger q, BigInteger j,
+ DHValidationParms validationParms)
+ {
+ if (p == null)
+ {
+ throw new IllegalArgumentException("'p' cannot be null");
+ }
+ if (g == null)
+ {
+ throw new IllegalArgumentException("'g' cannot be null");
+ }
+ if (q == null)
+ {
+ throw new IllegalArgumentException("'q' cannot be null");
+ }
+
+ this.p = new ASN1Integer(p);
+ this.g = new ASN1Integer(g);
+ this.q = new ASN1Integer(q);
+ this.j = new ASN1Integer(j);
+ this.validationParms = validationParms;
+ }
+
public DHDomainParameters(ASN1Integer p, ASN1Integer g, ASN1Integer q, ASN1Integer j,
DHValidationParms validationParms)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java
index 78b0979..b3020e0 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DHValidationParms.java
@@ -21,17 +21,16 @@ public class DHValidationParms extends ASN1Object
public static DHValidationParms getInstance(Object obj)
{
- if (obj == null || obj instanceof DHDomainParameters)
+ if (obj instanceof DHValidationParms)
{
return (DHValidationParms)obj;
}
-
- if (obj instanceof ASN1Sequence)
+ else if (obj != null)
{
- return new DHValidationParms((ASN1Sequence)obj);
+ return new DHValidationParms(ASN1Sequence.getInstance(obj));
}
- throw new IllegalArgumentException("Invalid DHValidationParms: " + obj.getClass().getName());
+ return null;
}
public DHValidationParms(DERBitString seed, ASN1Integer pgenCounter)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
index fef664f..cf3c760 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
@@ -48,6 +48,37 @@ public class ECNamedCurveTable
}
/**
+ * 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 ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name);
+
+ if (oid == null)
+ {
+ oid = SECNamedCurves.getOID(name);
+ }
+
+ // BEGIN android-removed
+ // if (oid == null)
+ // {
+ // oid = TeleTrusTNamedCurves.getOID(name);
+ // }
+ // END android-removed
+
+ if (oid == null)
+ {
+ oid = NISTNamedCurves.getOID(name);
+ }
+
+ return oid;
+ }
+
+ /**
* return a X9ECParameters object representing the passed in named
* curve.
*
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java
index 764017e..25312fe 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java
@@ -19,17 +19,20 @@ public class X962NamedCurves
{
protected X9ECParameters createParameters()
{
+ BigInteger n = new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
ECCurve cFp192v1 = new ECCurve.Fp(
new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
- new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16));
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16),
+ n, h);
return new X9ECParameters(
cFp192v1,
cFp192v1.decodePoint(
Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")),
- new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16),
- BigInteger.valueOf(1),
+ n, h,
Hex.decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
}
};
@@ -38,17 +41,20 @@ public class X962NamedCurves
{
protected X9ECParameters createParameters()
{
+ BigInteger n = new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
ECCurve cFp192v2 = new ECCurve.Fp(
new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
- new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16));
+ new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16),
+ n, h);
return new X9ECParameters(
cFp192v2,
cFp192v2.decodePoint(
Hex.decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")),
- new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16),
- BigInteger.valueOf(1),
+ n, h,
Hex.decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
}
};
@@ -57,17 +63,20 @@ public class X962NamedCurves
{
protected X9ECParameters createParameters()
{
+ BigInteger n = new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
ECCurve cFp192v3 = new ECCurve.Fp(
new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
- new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16));
+ new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16),
+ n, h);
return new X9ECParameters(
cFp192v3,
cFp192v3.decodePoint(
Hex.decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")),
- new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16),
- BigInteger.valueOf(1),
+ n, h,
Hex.decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
}
};
@@ -76,17 +85,20 @@ public class X962NamedCurves
{
protected X9ECParameters createParameters()
{
+ BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
ECCurve cFp239v1 = new ECCurve.Fp(
new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
- new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16));
+ new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16),
+ n, h);
return new X9ECParameters(
cFp239v1,
cFp239v1.decodePoint(
Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")),
- new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16),
- BigInteger.valueOf(1),
+ n, h,
Hex.decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
}
};
@@ -95,17 +107,20 @@ public class X962NamedCurves
{
protected X9ECParameters createParameters()
{
+ BigInteger n = new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
ECCurve cFp239v2 = new ECCurve.Fp(
new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
- new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16));
+ new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16),
+ n, h);
return new X9ECParameters(
cFp239v2,
cFp239v2.decodePoint(
Hex.decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")),
- new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16),
- BigInteger.valueOf(1),
+ n, h,
Hex.decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
}
};
@@ -114,17 +129,20 @@ public class X962NamedCurves
{
protected X9ECParameters createParameters()
{
+ BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
ECCurve cFp239v3 = new ECCurve.Fp(
new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
- new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16));
+ new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16),
+ n, h);
return new X9ECParameters(
cFp239v3,
cFp239v3.decodePoint(
Hex.decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")),
- new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16),
- BigInteger.valueOf(1),
+ n, h,
Hex.decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
}
};
@@ -133,17 +151,20 @@ public class X962NamedCurves
{
protected X9ECParameters createParameters()
{
+ BigInteger n = new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16);
+ BigInteger h = BigInteger.valueOf(1);
+
ECCurve cFp256v1 = new ECCurve.Fp(
new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"),
new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16),
- new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16));
+ new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16),
+ n, h);
return new X9ECParameters(
cFp256v1,
cFp256v1.decodePoint(
Hex.decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")),
- new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16),
- BigInteger.valueOf(1),
+ n, h,
Hex.decode("c49d360886e704936a6678e1139d26b7819f7e90"));
}
};
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java
index 1c395d2..a4348de 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java
@@ -74,7 +74,7 @@ public class X962Parameters
* <pre>
* Parameters ::= CHOICE {
* ecParameters ECParameters,
- * namedCurve CURVES.&id({CurveNames}),
+ * namedCurve CURVES.&amp;id({CurveNames}),
* implicitlyCA NULL
* }
* </pre>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java
index f233657..f1bac2b 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java
@@ -11,6 +11,7 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
/**
@@ -46,6 +47,8 @@ public class X9Curve
X9FieldID fieldID,
ASN1Sequence seq)
{
+ // TODO Is it possible to get the order(n) and cofactor(h) too?
+
fieldIdentifier = fieldID.getIdentifier();
if (fieldIdentifier.equals(prime_field))
{
@@ -86,7 +89,6 @@ public class X9Curve
}
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());
}
else
@@ -102,11 +104,11 @@ public class X9Curve
private void setFieldIdentifier()
{
- if (curve instanceof ECCurve.Fp)
+ if (ECAlgorithms.isFpCurve(curve))
{
fieldIdentifier = prime_field;
}
- else if (curve instanceof ECCurve.F2m)
+ else if (ECAlgorithms.isF2mCurve(curve))
{
fieldIdentifier = characteristic_two_field;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
index 60f9008..302c130 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
@@ -9,8 +9,10 @@ import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.field.PolynomialExtensionField;
/**
* ASN.1 def for Elliptic-Curve ECParameters structure. See
@@ -108,19 +110,31 @@ public class X9ECParameters
this.h = h;
this.seed = seed;
- if (curve instanceof ECCurve.Fp)
+ if (ECAlgorithms.isFpCurve(curve))
{
- this.fieldID = new X9FieldID(((ECCurve.Fp)curve).getQ());
+ this.fieldID = new X9FieldID(curve.getField().getCharacteristic());
}
- else
+ else if (ECAlgorithms.isF2mCurve(curve))
{
- if (curve instanceof ECCurve.F2m)
+ PolynomialExtensionField field = (PolynomialExtensionField)curve.getField();
+ int[] exponents = field.getMinimalPolynomial().getExponentsPresent();
+ if (exponents.length == 3)
+ {
+ this.fieldID = new X9FieldID(exponents[2], exponents[1]);
+ }
+ else if (exponents.length == 5)
+ {
+ this.fieldID = new X9FieldID(exponents[4], exponents[1], exponents[2], exponents[3]);
+ }
+ else
{
- ECCurve.F2m curveF2m = (ECCurve.F2m)curve;
- this.fieldID = new X9FieldID(curveF2m.getM(), curveF2m.getK1(),
- curveF2m.getK2(), curveF2m.getK3());
+ throw new IllegalArgumentException("Only trinomial and pentomial curves are supported");
}
}
+ else
+ {
+ throw new IllegalArgumentException("'curve' is of an unsupported type");
+ }
}
public ECCurve getCurve()
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
index a210352..cb74234 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
@@ -38,6 +38,20 @@ public class X9FieldID
* @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>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ */
+ public X9FieldID(int m, int k1)
+ {
+ this(m, k1, 0, 0);
+ }
+
+ /**
+ * 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> +
@@ -55,11 +69,21 @@ public class X9FieldID
if (k2 == 0)
{
+ if (k3 != 0)
+ {
+ throw new IllegalArgumentException("inconsistent k values");
+ }
+
fieldIdParams.add(tpBasis);
fieldIdParams.add(new ASN1Integer(k1));
}
else
{
+ if (k2 <= k1 || k3 <= k2)
+ {
+ throw new IllegalArgumentException("inconsistent k values");
+ }
+
fieldIdParams.add(ppBasis);
ASN1EncodableVector pentanomialParams = new ASN1EncodableVector();
pentanomialParams.add(new ASN1Integer(k1));
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
index dd056ac..8e41e49 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
@@ -48,13 +48,13 @@ public class BufferedBlockCipher
pgpCFB = (idx > 0 && name.startsWith("PGP", idx));
- if (pgpCFB)
+ if (pgpCFB || cipher instanceof StreamCipher)
{
partialBlockOkay = true;
}
else
{
- partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("GCFB", idx) ||name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
+ partialBlockOkay = (idx > 0 && (name.startsWith("OpenPGP", idx)));
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/SkippingCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/SkippingCipher.java
new file mode 100644
index 0000000..f8cc648
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/SkippingCipher.java
@@ -0,0 +1,31 @@
+package org.bouncycastle.crypto;
+
+/**
+ * Ciphers producing a key stream which can be reset to particular points in the stream implement this.
+ */
+public interface SkippingCipher
+{
+ /**
+ * Skip numberOfBytes forwards, or backwards.
+ *
+ * @param numberOfBytes the number of bytes to skip (positive forward, negative backwards).
+ * @return the number of bytes actually skipped.
+ * @throws java.lang.IllegalArgumentException if numberOfBytes is an invalid value.
+ */
+ long skip(long numberOfBytes);
+
+ /**
+ * Reset the cipher and then skip forward to a given position.
+ *
+ * @param position the number of bytes in to set the cipher state to.
+ * @return the byte position moved to.
+ */
+ long seekTo(long position);
+
+ /**
+ * Return the current "position" of the cipher
+ *
+ * @return the current byte position.
+ */
+ long getPosition();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/SkippingStreamCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/SkippingStreamCipher.java
new file mode 100644
index 0000000..a707a81
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/SkippingStreamCipher.java
@@ -0,0 +1,9 @@
+package org.bouncycastle.crypto;
+
+/**
+ * General interface for a stream cipher that supports skipping.
+ */
+public interface SkippingStreamCipher
+ extends StreamCipher, SkippingCipher
+{
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java
index 8fdd232..09aadfb 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java
@@ -1,108 +1,58 @@
package org.bouncycastle.crypto;
/**
- * a wrapper for block ciphers with a single byte block size, so that they
- * can be treated like stream ciphers.
+ * A parent class for block cipher modes that do not require block aligned data to be processed, but can function in
+ * a streaming mode.
*/
-public class StreamBlockCipher
- implements StreamCipher
+public abstract class StreamBlockCipher
+ implements BlockCipher, StreamCipher
{
- private BlockCipher cipher;
+ private final BlockCipher cipher;
- private byte[] oneByte = new byte[1];
-
- /**
- * basic constructor.
- *
- * @param cipher the block cipher to be wrapped.
- * @exception IllegalArgumentException if the cipher has a block size other than
- * one.
- */
- public StreamBlockCipher(
- BlockCipher cipher)
+ protected StreamBlockCipher(BlockCipher cipher)
{
- if (cipher.getBlockSize() != 1)
- {
- throw new IllegalArgumentException("block cipher block size != 1.");
- }
-
this.cipher = cipher;
}
/**
- * initialise the underlying cipher.
+ * return the underlying block cipher that we are wrapping.
*
- * @param forEncryption true if we are setting up for encryption, false otherwise.
- * @param params the necessary parameters for the underlying cipher to be initialised.
+ * @return the underlying block cipher that we are wrapping.
*/
- public void init(
- boolean forEncryption,
- CipherParameters params)
+ public BlockCipher getUnderlyingCipher()
{
- cipher.init(forEncryption, params);
+ return cipher;
}
- /**
- * return the name of the algorithm we are wrapping.
- *
- * @return the name of the algorithm we are wrapping.
- */
- public String getAlgorithmName()
+ public final byte returnByte(byte in)
{
- return cipher.getAlgorithmName();
+ return calculateByte(in);
}
- /**
- * encrypt/decrypt a single byte returning the result.
- *
- * @param in the byte to be processed.
- * @return the result of processing the input byte.
- */
- public byte returnByte(
- byte in)
- {
- oneByte[0] = in;
-
- cipher.processBlock(oneByte, 0, oneByte, 0);
-
- return oneByte[0];
- }
-
- /**
- * process a block of bytes from in putting the result into out.
- *
- * @param in the input byte array.
- * @param inOff the offset into the in array where the data to be processed starts.
- * @param len the number of bytes to be processed.
- * @param out the output buffer the processed bytes go into.
- * @param outOff the offset into the output byte array the processed data stars at.
- * @exception DataLengthException if the output buffer is too small.
- */
- public void processBytes(
- byte[] in,
- int inOff,
- int len,
- byte[] out,
- int outOff)
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
throws DataLengthException
{
if (outOff + len > out.length)
{
- throw new DataLengthException("output buffer too small in processBytes()");
+ throw new DataLengthException("output buffer too short");
}
- for (int i = 0; i != len; i++)
+ if (inOff + len > in.length)
{
- cipher.processBlock(in, inOff + i, out, outOff + i);
+ throw new DataLengthException("input buffer too small");
}
- }
- /**
- * reset the underlying cipher. This leaves it in the same state
- * it was at after the last init (if there was one).
- */
- public void reset()
- {
- cipher.reset();
+ int inStart = inOff;
+ int inEnd = inOff + len;
+ int outStart = outOff;
+
+ while (inStart < inEnd)
+ {
+ out[outStart++] = calculateByte(in[inStart++]);
+ }
+
+ return len;
}
-}
+
+ protected abstract byte calculateByte(byte b);
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/StreamCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/StreamCipher.java
index 2a55d4f..c1255e9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/StreamCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/StreamCipher.java
@@ -40,9 +40,10 @@ public interface StreamCipher
* @param len the number of bytes to be processed.
* @param out the output buffer the processed bytes go into.
* @param outOff the offset into the output byte array the processed data starts at.
+ * @return the number of bytes produced - should always be len.
* @exception DataLengthException if the output buffer is too small.
*/
- public void processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
throws DataLengthException;
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/EncodableDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/EncodableDigest.java
new file mode 100644
index 0000000..d79fece
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/EncodableDigest.java
@@ -0,0 +1,17 @@
+package org.bouncycastle.crypto.digests;
+
+/**
+ * Encodable digests allow you to download an encoded copy of their internal state. This is useful for the situation where
+ * you need to generate a signature on an external device and it allows for "sign with last round", so a copy of the
+ * internal state of the digest, plus the last few blocks of the message are all that needs to be sent, rather than the
+ * entire message.
+ */
+public interface EncodableDigest
+{
+ /**
+ * Return an encoded byte array for the digest's internal state
+ *
+ * @return an encoding of the digests internal state.
+ */
+ byte[] getEncodedState();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
index 15f3ebb..29692ba 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java
@@ -2,6 +2,7 @@ package org.bouncycastle.crypto.digests;
import org.bouncycastle.crypto.ExtendedDigest;
import org.bouncycastle.util.Memoable;
+import org.bouncycastle.util.Pack;
/**
* base implementation of MD4 family style digest as outlined in
@@ -11,8 +12,9 @@ public abstract class GeneralDigest
implements ExtendedDigest, Memoable
{
private static final int BYTE_LENGTH = 64;
- private byte[] xBuf;
- private int xBufOff;
+
+ private final byte[] xBuf = new byte[4];
+ private int xBufOff;
private long byteCount;
@@ -21,7 +23,6 @@ public abstract class GeneralDigest
*/
protected GeneralDigest()
{
- xBuf = new byte[4];
xBufOff = 0;
}
@@ -32,11 +33,16 @@ public abstract class GeneralDigest
*/
protected GeneralDigest(GeneralDigest t)
{
- xBuf = new byte[t.xBuf.length];
-
copyIn(t);
}
+ protected GeneralDigest(byte[] encodedState)
+ {
+ System.arraycopy(encodedState, 0, xBuf, 0, xBuf.length);
+ xBufOff = Pack.bigEndianToInt(encodedState, 4);
+ byteCount = Pack.bigEndianToLong(encodedState, 8);
+ }
+
protected void copyIn(GeneralDigest t)
{
System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
@@ -129,6 +135,13 @@ public abstract class GeneralDigest
}
}
+ protected void populateState(byte[] state)
+ {
+ System.arraycopy(xBuf, 0, state, 0, xBufOff);
+ Pack.intToBigEndian(xBufOff, state, 4);
+ Pack.longToBigEndian(byteCount, state, 8);
+ }
+
public int getByteLength()
{
return BYTE_LENGTH;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java
index 5c79e4e..8ea474b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java
@@ -1,18 +1,18 @@
package org.bouncycastle.crypto.digests;
import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.util.Memoable;
+import org.bouncycastle.util.Pack;
/**
* Base class for SHA-384 and SHA-512.
*/
public abstract class LongDigest
- implements ExtendedDigest, Memoable
+ implements ExtendedDigest, Memoable, EncodableDigest
{
private static final int BYTE_LENGTH = 128;
-
- private byte[] xBuf;
+
+ private byte[] xBuf = new byte[8];
private int xBufOff;
private long byteCount1;
@@ -28,7 +28,6 @@ public abstract class LongDigest
*/
protected LongDigest()
{
- xBuf = new byte[8];
xBufOff = 0;
reset();
@@ -41,8 +40,6 @@ public abstract class LongDigest
*/
protected LongDigest(LongDigest t)
{
- xBuf = new byte[t.xBuf.length];
-
copyIn(t);
}
@@ -67,6 +64,56 @@ public abstract class LongDigest
wOff = t.wOff;
}
+ protected void populateState(byte[] state)
+ {
+ System.arraycopy(xBuf, 0, state, 0, xBufOff);
+ Pack.intToBigEndian(xBufOff, state, 8);
+ Pack.longToBigEndian(byteCount1, state, 12);
+ Pack.longToBigEndian(byteCount2, state, 20);
+ Pack.longToBigEndian(H1, state, 28);
+ Pack.longToBigEndian(H2, state, 36);
+ Pack.longToBigEndian(H3, state, 44);
+ Pack.longToBigEndian(H4, state, 52);
+ Pack.longToBigEndian(H5, state, 60);
+ Pack.longToBigEndian(H6, state, 68);
+ Pack.longToBigEndian(H7, state, 76);
+ Pack.longToBigEndian(H8, state, 84);
+
+ Pack.intToBigEndian(wOff, state, 92);
+ for (int i = 0; i < wOff; i++)
+ {
+ Pack.longToBigEndian(W[i], state, 96 + (i * 8));
+ }
+ }
+
+ protected void restoreState(byte[] encodedState)
+ {
+ xBufOff = Pack.bigEndianToInt(encodedState, 8);
+ System.arraycopy(encodedState, 0, xBuf, 0, xBufOff);
+ byteCount1 = Pack.bigEndianToLong(encodedState, 12);
+ byteCount2 = Pack.bigEndianToLong(encodedState, 20);
+
+ H1 = Pack.bigEndianToLong(encodedState, 28);
+ H2 = Pack.bigEndianToLong(encodedState, 36);
+ H3 = Pack.bigEndianToLong(encodedState, 44);
+ H4 = Pack.bigEndianToLong(encodedState, 52);
+ H5 = Pack.bigEndianToLong(encodedState, 60);
+ H6 = Pack.bigEndianToLong(encodedState, 68);
+ H7 = Pack.bigEndianToLong(encodedState, 76);
+ H8 = Pack.bigEndianToLong(encodedState, 84);
+
+ wOff = Pack.bigEndianToInt(encodedState, 92);
+ for (int i = 0; i < wOff; i++)
+ {
+ W[i] = Pack.bigEndianToLong(encodedState, 96 + (i * 8));
+ }
+ }
+
+ protected int getEncodedStateSize()
+ {
+ return 96 + (wOff * 8);
+ }
+
public void update(
byte in)
{
@@ -165,7 +212,7 @@ public abstract class LongDigest
{
return BYTE_LENGTH;
}
-
+
protected void processWord(
byte[] in,
int inOff)
@@ -228,7 +275,7 @@ public abstract class LongDigest
long g = H7;
long h = H8;
- int t = 0;
+ int t = 0;
for(int i = 0; i < 10; i ++)
{
// t = 8 * i
@@ -271,7 +318,7 @@ public abstract class LongDigest
e += a;
a += Sum0(b) + Maj(b, c, d);
}
-
+
H1 += a;
H2 += b;
H3 += c;
@@ -358,4 +405,5 @@ public abstract class LongDigest
0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L
};
+
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java
index 21b1024..450dda4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java
@@ -1,7 +1,7 @@
package org.bouncycastle.crypto.digests;
-import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.util.Memoable;
+import org.bouncycastle.util.Pack;
/**
* implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
@@ -11,6 +11,7 @@ import org.bouncycastle.util.Memoable;
*/
public class SHA1Digest
extends GeneralDigest
+ implements EncodableDigest
{
private static final int DIGEST_LENGTH = 20;
@@ -38,6 +39,23 @@ public class SHA1Digest
copyIn(t);
}
+ public SHA1Digest(byte[] encodedState)
+ {
+ super(encodedState);
+
+ H1 = Pack.bigEndianToInt(encodedState, 16);
+ H2 = Pack.bigEndianToInt(encodedState, 20);
+ H3 = Pack.bigEndianToInt(encodedState, 24);
+ H4 = Pack.bigEndianToInt(encodedState, 28);
+ H5 = Pack.bigEndianToInt(encodedState, 32);
+
+ xOff = Pack.bigEndianToInt(encodedState, 36);
+ for (int i = 0; i != xOff; i++)
+ {
+ X[i] = Pack.bigEndianToInt(encodedState, 40 + (i * 4));
+ }
+ }
+
private void copyIn(SHA1Digest t)
{
H1 = t.H1;
@@ -302,6 +320,27 @@ public class SHA1Digest
super.copyIn(d);
copyIn(d);
}
+
+ public byte[] getEncodedState()
+ {
+ byte[] state = new byte[40 + xOff * 4];
+
+ super.populateState(state);
+
+ Pack.intToBigEndian(H1, state, 16);
+ Pack.intToBigEndian(H2, state, 20);
+ Pack.intToBigEndian(H3, state, 24);
+ Pack.intToBigEndian(H4, state, 28);
+ Pack.intToBigEndian(H5, state, 32);
+ Pack.intToBigEndian(xOff, state, 36);
+
+ for (int i = 0; i != xOff; i++)
+ {
+ Pack.intToBigEndian(X[i], state, 40 + (i * 4));
+ }
+
+ return state;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java
index d430321..4f2b284 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java
@@ -1,8 +1,8 @@
package org.bouncycastle.crypto.digests;
-import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.util.Memoable;
+import org.bouncycastle.util.Pack;
/**
@@ -18,6 +18,7 @@ import org.bouncycastle.util.Memoable;
*/
public class SHA224Digest
extends GeneralDigest
+ implements EncodableDigest
{
private static final int DIGEST_LENGTH = 28;
@@ -62,6 +63,26 @@ public class SHA224Digest
xOff = t.xOff;
}
+ public SHA224Digest(byte[] encodedState)
+ {
+ super(encodedState);
+
+ H1 = Pack.bigEndianToInt(encodedState, 16);
+ H2 = Pack.bigEndianToInt(encodedState, 20);
+ H3 = Pack.bigEndianToInt(encodedState, 24);
+ H4 = Pack.bigEndianToInt(encodedState, 28);
+ H5 = Pack.bigEndianToInt(encodedState, 32);
+ H6 = Pack.bigEndianToInt(encodedState, 36);
+ H7 = Pack.bigEndianToInt(encodedState, 40);
+ H8 = Pack.bigEndianToInt(encodedState, 44);
+
+ xOff = Pack.bigEndianToInt(encodedState, 48);
+ for (int i = 0; i != xOff; i++)
+ {
+ X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
+ }
+ }
+
public String getAlgorithmName()
{
return "SHA-224";
@@ -307,5 +328,29 @@ public class SHA224Digest
doCopy(d);
}
+
+ public byte[] getEncodedState()
+ {
+ byte[] state = new byte[52 + xOff * 4];
+
+ super.populateState(state);
+
+ Pack.intToBigEndian(H1, state, 16);
+ Pack.intToBigEndian(H2, state, 20);
+ Pack.intToBigEndian(H3, state, 24);
+ Pack.intToBigEndian(H4, state, 28);
+ Pack.intToBigEndian(H5, state, 32);
+ Pack.intToBigEndian(H6, state, 36);
+ Pack.intToBigEndian(H7, state, 40);
+ Pack.intToBigEndian(H8, state, 44);
+ Pack.intToBigEndian(xOff, state, 48);
+
+ for (int i = 0; i != xOff; i++)
+ {
+ Pack.intToBigEndian(X[i], state, 52 + (i * 4));
+ }
+
+ return state;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java
index a2ceda3..600d234 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java
@@ -1,8 +1,8 @@
package org.bouncycastle.crypto.digests;
-import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.util.Memoable;
+import org.bouncycastle.util.Pack;
/**
@@ -18,6 +18,7 @@ import org.bouncycastle.util.Memoable;
*/
public class SHA256Digest
extends GeneralDigest
+ implements EncodableDigest
{
private static final int DIGEST_LENGTH = 32;
@@ -62,6 +63,27 @@ public class SHA256Digest
xOff = t.xOff;
}
+ public SHA256Digest(byte[] encodedState)
+ {
+ super(encodedState);
+
+ H1 = Pack.bigEndianToInt(encodedState, 16);
+ H2 = Pack.bigEndianToInt(encodedState, 20);
+ H3 = Pack.bigEndianToInt(encodedState, 24);
+ H4 = Pack.bigEndianToInt(encodedState, 28);
+ H5 = Pack.bigEndianToInt(encodedState, 32);
+ H6 = Pack.bigEndianToInt(encodedState, 36);
+ H7 = Pack.bigEndianToInt(encodedState, 40);
+ H8 = Pack.bigEndianToInt(encodedState, 44);
+
+ xOff = Pack.bigEndianToInt(encodedState, 48);
+ for (int i = 0; i != xOff; i++)
+ {
+ X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
+ }
+ }
+
+
public String getAlgorithmName()
{
return "SHA-256";
@@ -310,5 +332,29 @@ public class SHA256Digest
copyIn(d);
}
+
+ public byte[] getEncodedState()
+ {
+ byte[] state = new byte[52 + xOff * 4];
+
+ super.populateState(state);
+
+ Pack.intToBigEndian(H1, state, 16);
+ Pack.intToBigEndian(H2, state, 20);
+ Pack.intToBigEndian(H3, state, 24);
+ Pack.intToBigEndian(H4, state, 28);
+ Pack.intToBigEndian(H5, state, 32);
+ Pack.intToBigEndian(H6, state, 36);
+ Pack.intToBigEndian(H7, state, 40);
+ Pack.intToBigEndian(H8, state, 44);
+ Pack.intToBigEndian(xOff, state, 48);
+
+ for (int i = 0; i != xOff; i++)
+ {
+ Pack.intToBigEndian(X[i], state, 52 + (i * 4));
+ }
+
+ return state;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java
index 75d195d..fc9fa1e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java
@@ -1,7 +1,7 @@
package org.bouncycastle.crypto.digests;
-import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.util.Memoable;
+import org.bouncycastle.util.Pack;
/**
@@ -36,6 +36,11 @@ public class SHA384Digest
super(t);
}
+ public SHA384Digest(byte[] encodedState)
+ {
+ restoreState(encodedState);
+ }
+
public String getAlgorithmName()
{
return "SHA-384";
@@ -96,4 +101,11 @@ public class SHA384Digest
super.copyIn(d);
}
+
+ public byte[] getEncodedState()
+ {
+ byte[] encoded = new byte[getEncodedStateSize()];
+ super.populateState(encoded);
+ return encoded;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java
index 7db63ad..644bafa 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java
@@ -1,7 +1,7 @@
package org.bouncycastle.crypto.digests;
-import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.util.Memoable;
+import org.bouncycastle.util.Pack;
/**
@@ -36,6 +36,11 @@ public class SHA512Digest
super(t);
}
+ public SHA512Digest(byte[] encodedState)
+ {
+ restoreState(encodedState);
+ }
+
public String getAlgorithmName()
{
return "SHA-512";
@@ -98,5 +103,12 @@ public class SHA512Digest
copyIn(d);
}
+
+ public byte[] getEncodedState()
+ {
+ byte[] encoded = new byte[getEncodedStateSize()];
+ super.populateState(encoded);
+ return encoded;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
new file mode 100644
index 0000000..3b4b2e6
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
@@ -0,0 +1,326 @@
+package org.bouncycastle.crypto.ec;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.asn1.x9.X9ECParametersHolder;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECPoint;
+// BEGIN android-removed
+// import org.bouncycastle.math.ec.custom.djb.Curve25519;
+// END android-removed
+import org.bouncycastle.math.ec.custom.sec.SecP192K1Curve;
+import org.bouncycastle.math.ec.custom.sec.SecP192R1Curve;
+import org.bouncycastle.math.ec.custom.sec.SecP224K1Curve;
+import org.bouncycastle.math.ec.custom.sec.SecP224R1Curve;
+import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve;
+import org.bouncycastle.math.ec.custom.sec.SecP256R1Curve;
+import org.bouncycastle.math.ec.custom.sec.SecP384R1Curve;
+import org.bouncycastle.math.ec.custom.sec.SecP521R1Curve;
+import org.bouncycastle.math.ec.endo.GLVTypeBEndomorphism;
+import org.bouncycastle.math.ec.endo.GLVTypeBParameters;
+import org.bouncycastle.util.Strings;
+import org.bouncycastle.util.encoders.Hex;
+
+public class CustomNamedCurves
+{
+ private static ECCurve configureCurve(ECCurve curve)
+ {
+ return curve;
+ }
+
+ private static ECCurve configureCurveGLV(ECCurve c, GLVTypeBParameters p)
+ {
+ return c.configure().setEndomorphism(new GLVTypeBEndomorphism(c, p)).create();
+ }
+
+ // BEGIN android-removed
+ // /*
+ // * curve25519
+ // */
+ // static X9ECParametersHolder curve25519 = new X9ECParametersHolder()
+ // {
+ // protected X9ECParameters createParameters()
+ // {
+ // byte[] S = null;
+ // ECCurve curve = configureCurve(new Curve25519());
+ //
+ // /*
+ // * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form
+ // * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3).
+ // *
+ // * The Curve25519 paper doesn't say which of the two possible y values the base
+ // * point has. The choice here is guided by language in the Ed25519 paper.
+ // *
+ // * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
+ // */
+ // ECPoint G = curve.decodePoint(Hex.decode("04"
+ // + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
+ // + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
+ //
+ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ // }
+ // };
+ // END android-removed
+
+ /*
+ * secp192k1
+ */
+ static X9ECParametersHolder secp192k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = null;
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
+ new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
+ new BigInteger[]{
+ new BigInteger("71169be7330b3038edb025f1", 16),
+ new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
+ new BigInteger[]{
+ new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
+ new BigInteger("71169be7330b3038edb025f1", 16) },
+ new BigInteger("71169be7330b3038edb025f1d0f9", 16),
+ new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
+ 208);
+ ECCurve curve = configureCurveGLV(new SecP192K1Curve(), glv);
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+ + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp192r1
+ */
+ static X9ECParametersHolder secp192r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
+ ECCurve curve = configureCurve(new SecP192R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+ + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp224k1
+ */
+ static X9ECParametersHolder secp224k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = null;
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
+ new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
+ new BigInteger[]{
+ new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
+ new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
+ new BigInteger[]{
+ new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
+ new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
+ new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
+ new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
+ 240);
+ ECCurve curve = configureCurveGLV(new SecP224K1Curve(), glv);
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+ + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp224r1
+ */
+ static X9ECParametersHolder secp224r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
+ ECCurve curve = configureCurve(new SecP224R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp256k1
+ */
+ static X9ECParametersHolder secp256k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = null;
+ GLVTypeBParameters glv = new GLVTypeBParameters(
+ new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
+ new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
+ new BigInteger[]{
+ new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
+ new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
+ new BigInteger[]{
+ new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
+ new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
+ new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
+ new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
+ 272);
+ ECCurve curve = configureCurveGLV(new SecP256K1Curve(), glv);
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+ + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp256r1
+ */
+ static X9ECParametersHolder secp256r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90");
+ ECCurve curve = configureCurve(new SecP256R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp384r1
+ */
+ static X9ECParametersHolder secp384r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
+ ECCurve curve = configureCurve(new SecP384R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ /*
+ * secp521r1
+ */
+ static X9ECParametersHolder secp521r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
+ ECCurve curve = configureCurve(new SecP521R1Curve());
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+ + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
+
+ static final Hashtable nameToCurve = new Hashtable();
+ static final Hashtable nameToOID = new Hashtable();
+ static final Hashtable oidToCurve = new Hashtable();
+ static final Hashtable oidToName = new Hashtable();
+
+ static void defineCurve(String name, X9ECParametersHolder holder)
+ {
+ nameToCurve.put(name, holder);
+ }
+
+ static void defineCurveWithOID(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
+ {
+ nameToCurve.put(name, holder);
+ nameToOID.put(name, oid);
+ oidToName.put(oid, name);
+ oidToCurve.put(oid, holder);
+ }
+
+ static void defineCurveAlias(String alias, ASN1ObjectIdentifier oid)
+ {
+ alias = Strings.toLowerCase(alias);
+ nameToOID.put(alias, oid);
+ nameToCurve.put(alias, oidToCurve.get(oid));
+ }
+
+ static
+ {
+ // BEGIN android-removed
+ // defineCurve("curve25519", curve25519);
+ // END android-removed
+
+ defineCurveWithOID("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1);
+ defineCurveWithOID("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1);
+ defineCurveWithOID("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1);
+ defineCurveWithOID("secp224r1", SECObjectIdentifiers.secp224r1, secp224r1);
+ defineCurveWithOID("secp256k1", SECObjectIdentifiers.secp256k1, secp256k1);
+ defineCurveWithOID("secp256r1", SECObjectIdentifiers.secp256r1, secp256r1);
+ defineCurveWithOID("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1);
+ defineCurveWithOID("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1);
+
+ defineCurveAlias("P-192", SECObjectIdentifiers.secp192r1);
+ defineCurveAlias("P-224", SECObjectIdentifiers.secp224r1);
+ defineCurveAlias("P-256", SECObjectIdentifiers.secp256r1);
+ defineCurveAlias("P-384", SECObjectIdentifiers.secp384r1);
+ defineCurveAlias("P-521", SECObjectIdentifiers.secp521r1);
+ }
+
+ public static X9ECParameters getByName(String name)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)nameToCurve.get(Strings.toLowerCase(name));
+ return holder == null ? null : holder.getParameters();
+ }
+
+ /**
+ * 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(ASN1ObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)oidToCurve.get(oid);
+ return holder == null ? null : holder.getParameters();
+ }
+
+ /**
+ * 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 ASN1ObjectIdentifier getOID(String name)
+ {
+ return (ASN1ObjectIdentifier)nameToOID.get(Strings.toLowerCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(ASN1ObjectIdentifier oid)
+ {
+ return (String)oidToName.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return nameToCurve.keys();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
index d8ec62b..c78b1a5 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
@@ -34,6 +34,8 @@ public class PKCS1Encoding
private boolean forEncryption;
private boolean forPrivateKey;
private boolean useStrictLength;
+ private int pLen = -1;
+ private byte[] fallback = null;
/**
* Basic constructor.
@@ -46,6 +48,42 @@ public class PKCS1Encoding
this.useStrictLength = useStrict();
}
+ /**
+ * Constructor for decryption with a fixed plaintext length.
+ *
+ * @param cipher The cipher to use for cryptographic operation.
+ * @param pLen Length of the expected plaintext.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ int pLen)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.pLen = pLen;
+ }
+
+ /**
+ * Constructor for decryption with a fixed plaintext length and a fallback
+ * value that is returned, if the padding is incorrect.
+ *
+ * @param cipher
+ * The cipher to use for cryptographic operation.
+ * @param fallback
+ * The fallback value, we don't to a arraycopy here.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ byte[] fallback)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.fallback = fallback;
+ this.pLen = fallback.length;
+ }
+
+
+
//
// for J2ME compatibility
//
@@ -183,6 +221,121 @@ public class PKCS1Encoding
return engine.processBlock(block, 0, block.length);
}
+
+ /**
+ * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
+ * for encryption.
+ *
+ * @param encoded The Plaintext.
+ * @param pLen Expected length of the plaintext.
+ * @return Either 0, if the encoding is correct, or -1, if it is incorrect.
+ */
+ private static int checkPkcs1Encoding(byte[] encoded, int pLen) {
+ int correct = 0;
+ /*
+ * Check if the first two bytes are 0 2
+ */
+ correct |= (encoded[0] ^ 2);
+
+ /*
+ * Now the padding check, check for no 0 byte in the padding
+ */
+ int plen = encoded.length - (
+ pLen /* Lenght of the PMS */
+ + 1 /* Final 0-byte before PMS */
+ );
+
+ for (int i = 1; i < plen; i++) {
+ int tmp = encoded[i];
+ tmp |= tmp >> 1;
+ tmp |= tmp >> 2;
+ tmp |= tmp >> 4;
+ correct |= (tmp & 1) - 1;
+ }
+
+ /*
+ * Make sure the padding ends with a 0 byte.
+ */
+ correct |= encoded[encoded.length - (pLen +1)];
+
+ /*
+ * Return 0 or 1, depending on the result.
+ */
+ correct |= correct >> 1;
+ correct |= correct >> 2;
+ correct |= correct >> 4;
+ return ~((correct & 1) - 1);
+ }
+
+
+ /**
+ * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
+ *
+ * @param in The encrypted block.
+ * @param inOff Offset in the encrypted block.
+ * @param inLen Length of the encrypted block.
+ * //@param pLen Length of the desired output.
+ * @return The plaintext without padding, or a random value if the padding was incorrect.
+ *
+ * @throws InvalidCipherTextException
+ */
+ private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+ if (!forPrivateKey)
+ {
+ throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
+ byte[] random = null;
+ if (this.fallback == null)
+ {
+ random = new byte[this.pLen];
+ this.random.nextBytes(random);
+ }
+ else
+ {
+ random = fallback;
+ }
+
+ /*
+ * TODO: This is a potential dangerous side channel. However, you can
+ * fix this by changing the RSA engine in a way, that it will always
+ * return blocks of the same length and prepend them with 0 bytes if
+ * needed.
+ */
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ /*
+ * TODO: Potential side channel. Fix it by making the engine always
+ * return blocks of the correct length.
+ */
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ /*
+ * Check the padding.
+ */
+ int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen);
+
+ /*
+ * Now, to a constant time constant memory copy of the decrypted value
+ * or the random value, depending on the validity of the padding.
+ */
+ byte[] result = new byte[this.pLen];
+ for (int i = 0; i < this.pLen; i++)
+ {
+ result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct));
+ }
+
+ return result;
+ }
/**
* @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
@@ -193,7 +346,15 @@ public class PKCS1Encoding
int inLen)
throws InvalidCipherTextException
{
- byte[] block = engine.processBlock(in, inOff, inLen);
+ /*
+ * If the length of the expected plaintext is known, we use a constant-time decryption.
+ * If the decryption fails, we return a random value.
+ */
+ if (this.pLen != -1) {
+ return this.decodeBlockOrRandom(in, inOff, inLen);
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
if (block.length < getOutputBlockSize())
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
index 756197c..a0fd084 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
@@ -473,74 +473,65 @@ private static final int[] Tinv0 =
private void encryptBlock(int[][] KW)
{
- int r, r0, r1, r2, r3;
-
- C0 ^= KW[0][0];
- C1 ^= KW[0][1];
- C2 ^= KW[0][2];
- C3 ^= KW[0][3];
-
- r = 1;
+ int t0 = this.C0 ^ KW[0][0];
+ int t1 = this.C1 ^ KW[0][1];
+ int t2 = this.C2 ^ KW[0][2];
+ int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3];
while (r < ROUNDS - 1)
{
- r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255],16) ^ shift(T0[(C3>>24)&255],8) ^ KW[r][0];
- r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1];
- r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2];
- r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3];
- C0 = T0[r0&255] ^ shift(T0[(r1>>8)&255], 24) ^ shift(T0[(r2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
- C1 = T0[r1&255] ^ shift(T0[(r2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(r0>>24)&255], 8) ^ KW[r][1];
- C2 = T0[r2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(r0>>16)&255], 16) ^ shift(T0[(r1>>24)&255], 8) ^ KW[r][2];
- C3 = T0[r3&255] ^ shift(T0[(r0>>8)&255], 24) ^ shift(T0[(r1>>16)&255], 16) ^ shift(T0[(r2>>24)&255], 8) ^ KW[r++][3];
+ r0 = T0[t0&255] ^ shift(T0[(t1>>8)&255], 24) ^ shift(T0[(t2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
+ r1 = T0[t1&255] ^ shift(T0[(t2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(t0>>24)&255], 8) ^ KW[r][1];
+ r2 = T0[t2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(t0>>16)&255], 16) ^ shift(T0[(t1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[r3&255] ^ shift(T0[(t0>>8)&255], 24) ^ shift(T0[(t1>>16)&255], 16) ^ shift(T0[(t2>>24)&255], 8) ^ KW[r++][3];
+ t0 = T0[r0&255] ^ shift(T0[(r1>>8)&255], 24) ^ shift(T0[(r2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
+ t1 = T0[r1&255] ^ shift(T0[(r2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(r0>>24)&255], 8) ^ KW[r][1];
+ t2 = T0[r2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(r0>>16)&255], 16) ^ shift(T0[(r1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[r3&255] ^ shift(T0[(r0>>8)&255], 24) ^ shift(T0[(r1>>16)&255], 16) ^ shift(T0[(r2>>24)&255], 8) ^ KW[r++][3];
}
- r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255], 16) ^ shift(T0[(C3>>24)&255], 8) ^ KW[r][0];
- r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1];
- r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2];
- r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3];
+ r0 = T0[t0&255] ^ shift(T0[(t1>>8)&255], 24) ^ shift(T0[(t2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
+ r1 = T0[t1&255] ^ shift(T0[(t2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(t0>>24)&255], 8) ^ KW[r][1];
+ r2 = T0[t2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(t0>>16)&255], 16) ^ shift(T0[(t1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[r3&255] ^ shift(T0[(t0>>8)&255], 24) ^ shift(T0[(t1>>16)&255], 16) ^ shift(T0[(t2>>24)&255], 8) ^ KW[r++][3];
// the final round's table is a simple function of S so we don't use a whole other four tables for it
- C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
- C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
- C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
- C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
-
+ this.C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
+ this.C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
+ this.C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
+ this.C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
}
private void decryptBlock(int[][] KW)
{
- int r, r0, r1, r2, r3;
-
- C0 ^= KW[ROUNDS][0];
- C1 ^= KW[ROUNDS][1];
- C2 ^= KW[ROUNDS][2];
- C3 ^= KW[ROUNDS][3];
-
- r = ROUNDS-1;
+ int t0 = this.C0 ^ KW[ROUNDS][0];
+ int t1 = this.C1 ^ KW[ROUNDS][1];
+ int t2 = this.C2 ^ KW[ROUNDS][2];
- while (r>1)
+ int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3];
+ while (r > 1)
{
- r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0];
- r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1];
- r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2];
- r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r--][3];
- C0 = Tinv0[r0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(r2>>16)&255], 16) ^ shift(Tinv0[(r1>>24)&255], 8) ^ KW[r][0];
- C1 = Tinv0[r1&255] ^ shift(Tinv0[(r0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(r2>>24)&255], 8) ^ KW[r][1];
- C2 = Tinv0[r2&255] ^ shift(Tinv0[(r1>>8)&255], 24) ^ shift(Tinv0[(r0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
- C3 = Tinv0[r3&255] ^ shift(Tinv0[(r2>>8)&255], 24) ^ shift(Tinv0[(r1>>16)&255], 16) ^ shift(Tinv0[(r0>>24)&255], 8) ^ KW[r--][3];
+ r0 = Tinv0[t0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(t2>>16)&255], 16) ^ shift(Tinv0[(t1>>24)&255], 8) ^ KW[r][0];
+ r1 = Tinv0[t1&255] ^ shift(Tinv0[(t0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(t2>>24)&255], 8) ^ KW[r][1];
+ r2 = Tinv0[t2&255] ^ shift(Tinv0[(t1>>8)&255], 24) ^ shift(Tinv0[(t0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[r3&255] ^ shift(Tinv0[(t2>>8)&255], 24) ^ shift(Tinv0[(t1>>16)&255], 16) ^ shift(Tinv0[(t0>>24)&255], 8) ^ KW[r--][3];
+ t0 = Tinv0[r0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(r2>>16)&255], 16) ^ shift(Tinv0[(r1>>24)&255], 8) ^ KW[r][0];
+ t1 = Tinv0[r1&255] ^ shift(Tinv0[(r0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(r2>>24)&255], 8) ^ KW[r][1];
+ t2 = Tinv0[r2&255] ^ shift(Tinv0[(r1>>8)&255], 24) ^ shift(Tinv0[(r0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[r3&255] ^ shift(Tinv0[(r2>>8)&255], 24) ^ shift(Tinv0[(r1>>16)&255], 16) ^ shift(Tinv0[(r0>>24)&255], 8) ^ KW[r--][3];
}
- r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0];
- r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1];
- r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2];
- r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r][3];
+ r0 = Tinv0[t0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(t2>>16)&255], 16) ^ shift(Tinv0[(t1>>24)&255], 8) ^ KW[r][0];
+ r1 = Tinv0[t1&255] ^ shift(Tinv0[(t0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(t2>>24)&255], 8) ^ KW[r][1];
+ r2 = Tinv0[t2&255] ^ shift(Tinv0[(t1>>8)&255], 24) ^ shift(Tinv0[(t0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[r3&255] ^ shift(Tinv0[(t2>>8)&255], 24) ^ shift(Tinv0[(t1>>16)&255], 16) ^ shift(Tinv0[(t0>>24)&255], 8) ^ KW[r][3];
// the final round's table is a simple function of Si so we don't use a whole other four tables for it
- C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
- C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
- C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
- C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
+ this.C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
+ this.C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
+ this.C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
+ this.C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
index ff4b2f8..e2b00d3 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
@@ -5,6 +5,7 @@ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.util.Pack;
/**
* an implementation of the AES (Rijndael), from FIPS-197.
@@ -110,8 +111,9 @@ public class AESFastEngine
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
// precomputation tables of calculations for rounds
- private static final int[] T0 =
+ private static final int[] T =
{
+ // T0
0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
@@ -163,10 +165,9 @@ public class AESFastEngine
0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
- 0x3a16162c};
+ 0x3a16162c,
- private static final int[] T1 =
- {
+ // T1
0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d,
0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203,
0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6,
@@ -218,10 +219,9 @@ public class AESFastEngine
0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da,
0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0,
0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6,
- 0x16162c3a};
+ 0x16162c3a,
- private static final int[] T2 =
- {
+ // T2
0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2,
0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301,
0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab,
@@ -273,10 +273,9 @@ public class AESFastEngine
0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf,
0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099,
0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb,
- 0x162c3a16};
+ 0x162c3a16,
- private static final int[] T3 =
- {
+ // T3
0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2,
0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101,
0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab,
@@ -330,8 +329,9 @@ public class AESFastEngine
0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb,
0x2c3a1616};
- private static final int[] Tinv0 =
+ private static final int[] Tinv =
{
+ // Tinv0
0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
@@ -383,10 +383,9 @@ public class AESFastEngine
0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
- 0x4257b8d0};
+ 0x4257b8d0,
- private static final int[] Tinv1 =
- {
+ // Tinv1
0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb,
0x459d1ff1, 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6,
0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680,
@@ -438,10 +437,9 @@ public class AESFastEngine
0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672,
0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, 0xb30c08de,
0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874,
- 0x57b8d042};
+ 0x57b8d042,
- private static final int[] Tinv2 =
- {
+ // Tinv2
0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b,
0x9d1ff145, 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d,
0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044,
@@ -493,10 +491,9 @@ public class AESFastEngine
0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3,
0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, 0x0c08deb3,
0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c,
- 0xb8d04257};
+ 0xb8d04257,
- private static final int[] Tinv3 =
- {
+ // Tinv3
0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab,
0x1ff1459d, 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76,
0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435,
@@ -586,10 +583,11 @@ public class AESFastEngine
return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
}
-
private static int subWord(int x)
{
- return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
+ int i0 = x, i1 = x >>> 8, i2 = x >>> 16, i3 = x >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ return i0 | i1 << 8 | i2 << 16 | i3 << 24;
}
/**
@@ -727,19 +725,19 @@ public class AESFastEngine
throw new OutputLengthException("output buffer too short");
}
+ unpackBlock(in, inOff);
+
if (forEncryption)
{
- unpackBlock(in, inOff);
encryptBlock(WorkingKey);
- packBlock(out, outOff);
}
else
{
- unpackBlock(in, inOff);
decryptBlock(WorkingKey);
- packBlock(out, outOff);
}
+ packBlock(out, outOff);
+
return BLOCK_SIZE;
}
@@ -747,129 +745,184 @@ public class AESFastEngine
{
}
- private void unpackBlock(
- byte[] bytes,
- int off)
+ private void unpackBlock(byte[] bytes, int off)
{
- int index = off;
-
- C0 = (bytes[index++] & 0xff);
- C0 |= (bytes[index++] & 0xff) << 8;
- C0 |= (bytes[index++] & 0xff) << 16;
- C0 |= bytes[index++] << 24;
-
- C1 = (bytes[index++] & 0xff);
- C1 |= (bytes[index++] & 0xff) << 8;
- C1 |= (bytes[index++] & 0xff) << 16;
- C1 |= bytes[index++] << 24;
-
- C2 = (bytes[index++] & 0xff);
- C2 |= (bytes[index++] & 0xff) << 8;
- C2 |= (bytes[index++] & 0xff) << 16;
- C2 |= bytes[index++] << 24;
-
- C3 = (bytes[index++] & 0xff);
- C3 |= (bytes[index++] & 0xff) << 8;
- C3 |= (bytes[index++] & 0xff) << 16;
- C3 |= bytes[index++] << 24;
+ this.C0 = Pack.littleEndianToInt(bytes, off);
+ this.C1 = Pack.littleEndianToInt(bytes, off + 4);
+ this.C2 = Pack.littleEndianToInt(bytes, off + 8);
+ this.C3 = Pack.littleEndianToInt(bytes, off + 12);
}
- private void packBlock(
- byte[] bytes,
- int off)
+ private void packBlock(byte[] bytes, int off)
{
- int index = off;
-
- bytes[index++] = (byte)C0;
- bytes[index++] = (byte)(C0 >> 8);
- bytes[index++] = (byte)(C0 >> 16);
- bytes[index++] = (byte)(C0 >> 24);
-
- bytes[index++] = (byte)C1;
- bytes[index++] = (byte)(C1 >> 8);
- bytes[index++] = (byte)(C1 >> 16);
- bytes[index++] = (byte)(C1 >> 24);
-
- bytes[index++] = (byte)C2;
- bytes[index++] = (byte)(C2 >> 8);
- bytes[index++] = (byte)(C2 >> 16);
- bytes[index++] = (byte)(C2 >> 24);
-
- bytes[index++] = (byte)C3;
- bytes[index++] = (byte)(C3 >> 8);
- bytes[index++] = (byte)(C3 >> 16);
- bytes[index++] = (byte)(C3 >> 24);
+ Pack.intToLittleEndian(this.C0, bytes, off);
+ Pack.intToLittleEndian(this.C1, bytes, off + 4);
+ Pack.intToLittleEndian(this.C2, bytes, off + 8);
+ Pack.intToLittleEndian(this.C3, bytes, off + 12);
}
private void encryptBlock(int[][] KW)
{
- int r, r0, r1, r2, r3;
-
- C0 ^= KW[0][0];
- C1 ^= KW[0][1];
- C2 ^= KW[0][2];
- C3 ^= KW[0][3];
+ int t0 = this.C0 ^ KW[0][0];
+ int t1 = this.C1 ^ KW[0][1];
+ int t2 = this.C2 ^ KW[0][2];
+
+ /*
+ * Fast engine has precomputed rotr(T0, 8/16/24) tables T1/T2/T3.
+ *
+ * Placing all precomputes in one array requires offsets additions for 8/16/24 rotations but
+ * avoids additional array range checks on 3 more arrays (which on HotSpot are more
+ * expensive than the offset additions).
+ */
+ int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3];
+ int i0, i1, i2, i3;
- r = 1;
while (r < ROUNDS - 1)
{
- r0 = T0[C0&255] ^ T1[(C1>>8)&255] ^ T2[(C2>>16)&255] ^ T3[(C3>>24)&255] ^ KW[r][0];
- r1 = T0[C1&255] ^ T1[(C2>>8)&255] ^ T2[(C3>>16)&255] ^ T3[(C0>>24)&255] ^ KW[r][1];
- r2 = T0[C2&255] ^ T1[(C3>>8)&255] ^ T2[(C0>>16)&255] ^ T3[(C1>>24)&255] ^ KW[r][2];
- r3 = T0[C3&255] ^ T1[(C0>>8)&255] ^ T2[(C1>>16)&255] ^ T3[(C2>>24)&255] ^ KW[r++][3];
- C0 = T0[r0&255] ^ T1[(r1>>8)&255] ^ T2[(r2>>16)&255] ^ T3[(r3>>24)&255] ^ KW[r][0];
- C1 = T0[r1&255] ^ T1[(r2>>8)&255] ^ T2[(r3>>16)&255] ^ T3[(r0>>24)&255] ^ KW[r][1];
- C2 = T0[r2&255] ^ T1[(r3>>8)&255] ^ T2[(r0>>16)&255] ^ T3[(r1>>24)&255] ^ KW[r][2];
- C3 = T0[r3&255] ^ T1[(r0>>8)&255] ^ T2[(r1>>16)&255] ^ T3[(r2>>24)&255] ^ KW[r++][3];
+ i0 = t0; i1 = t1 >>> 8; i2 = t2 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0];
+
+ i0 = t1; i1 = t2 >>> 8; i2 = r3 >>> 16; i3 = t0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1];
+
+ i0 = t2; i1 = r3 >>> 8; i2 = t0 >>> 16; i3 = t1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = t0 >>> 8; i2 = t1 >>> 16; i3 = t2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3];
+
+ i0 = r0; i1 = r1 >>> 8; i2 = r2 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0];
+
+ i0 = r1; i1 = r2 >>> 8; i2 = r3 >>> 16; i3 = r0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1];
+
+ i0 = r2; i1 = r3 >>> 8; i2 = r0 >>> 16; i3 = r1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = r0 >>> 8; i2 = r1 >>> 16; i3 = r2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3];
}
- r0 = T0[C0&255] ^ T1[(C1>>8)&255] ^ T2[(C2>>16)&255] ^ T3[(C3>>24)&255] ^ KW[r][0];
- r1 = T0[C1&255] ^ T1[(C2>>8)&255] ^ T2[(C3>>16)&255] ^ T3[(C0>>24)&255] ^ KW[r][1];
- r2 = T0[C2&255] ^ T1[(C3>>8)&255] ^ T2[(C0>>16)&255] ^ T3[(C1>>24)&255] ^ KW[r][2];
- r3 = T0[C3&255] ^ T1[(C0>>8)&255] ^ T2[(C1>>16)&255] ^ T3[(C2>>24)&255] ^ KW[r++][3];
-
+ i0 = t0; i1 = t1 >>> 8; i2 = t2 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0];
+
+ i0 = t1; i1 = t2 >>> 8; i2 = r3 >>> 16; i3 = t0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1];
+
+ i0 = t2; i1 = r3 >>> 8; i2 = t0 >>> 16; i3 = t1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = t0 >>> 8; i2 = t1 >>> 16; i3 = t2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3];
+
// the final round's table is a simple function of S so we don't use a whole other four tables for it
- C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
- C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
- C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
- C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
+ i0 = r0; i1 = r1 >>> 8; i2 = r2 >>> 16; i3 = r3 >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ this.C0 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][0];
+
+ i0 = r1; i1 = r2 >>> 8; i2 = r3 >>> 16; i3 = r0 >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ this.C1 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][1];
+ i0 = r2; i1 = r3 >>> 8; i2 = r0 >>> 16; i3 = r1 >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ this.C2 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][2];
+
+ i0 = r3; i1 = r0 >>> 8; i2 = r1 >>> 16; i3 = r2 >>> 24;
+ i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255;
+ this.C3 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][3];
}
private void decryptBlock(int[][] KW)
{
- int r0, r1, r2, r3;
+ int t0 = this.C0 ^ KW[ROUNDS][0];
+ int t1 = this.C1 ^ KW[ROUNDS][1];
+ int t2 = this.C2 ^ KW[ROUNDS][2];
- C0 ^= KW[ROUNDS][0];
- C1 ^= KW[ROUNDS][1];
- C2 ^= KW[ROUNDS][2];
- C3 ^= KW[ROUNDS][3];
+ int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3];
+ int i0, i1, i2, i3;
- int r = ROUNDS-1;
-
- while (r>1)
+ while (r > 1)
{
- r0 = Tinv0[C0&255] ^ Tinv1[(C3>>8)&255] ^ Tinv2[(C2>>16)&255] ^ Tinv3[(C1>>24)&255] ^ KW[r][0];
- r1 = Tinv0[C1&255] ^ Tinv1[(C0>>8)&255] ^ Tinv2[(C3>>16)&255] ^ Tinv3[(C2>>24)&255] ^ KW[r][1];
- r2 = Tinv0[C2&255] ^ Tinv1[(C1>>8)&255] ^ Tinv2[(C0>>16)&255] ^ Tinv3[(C3>>24)&255] ^ KW[r][2];
- r3 = Tinv0[C3&255] ^ Tinv1[(C2>>8)&255] ^ Tinv2[(C1>>16)&255] ^ Tinv3[(C0>>24)&255] ^ KW[r--][3];
- C0 = Tinv0[r0&255] ^ Tinv1[(r3>>8)&255] ^ Tinv2[(r2>>16)&255] ^ Tinv3[(r1>>24)&255] ^ KW[r][0];
- C1 = Tinv0[r1&255] ^ Tinv1[(r0>>8)&255] ^ Tinv2[(r3>>16)&255] ^ Tinv3[(r2>>24)&255] ^ KW[r][1];
- C2 = Tinv0[r2&255] ^ Tinv1[(r1>>8)&255] ^ Tinv2[(r0>>16)&255] ^ Tinv3[(r3>>24)&255] ^ KW[r][2];
- C3 = Tinv0[r3&255] ^ Tinv1[(r2>>8)&255] ^ Tinv2[(r1>>16)&255] ^ Tinv3[(r0>>24)&255] ^ KW[r--][3];
+ i0 = t0; i1 = r3 >>> 8; i2 = t2 >>> 16; i3 = t1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][0];
+
+ i0 = t1; i1 = t0 >>> 8; i2 = r3 >>> 16; i3 = t2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][1];
+
+ i0 = t2; i1 = t1 >>> 8; i2 = t0 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = t2 >>> 8; i2 = t1 >>> 16; i3 = t0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r--][3];
+
+ i0 = r0; i1 = r3 >>> 8; i2 = r2 >>> 16; i3 = r1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][0];
+
+ i0 = r1; i1 = r0 >>> 8; i2 = r3 >>> 16; i3 = r2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][1];
+
+ i0 = r2; i1 = r1 >>> 8; i2 = r0 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ t2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][2];
+
+ i0 = r3; i1 = r2 >>> 8; i2 = r1 >>> 16; i3 = r0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r--][3];
}
- r0 = Tinv0[C0&255] ^ Tinv1[(C3>>8)&255] ^ Tinv2[(C2>>16)&255] ^ Tinv3[(C1>>24)&255] ^ KW[r][0];
- r1 = Tinv0[C1&255] ^ Tinv1[(C0>>8)&255] ^ Tinv2[(C3>>16)&255] ^ Tinv3[(C2>>24)&255] ^ KW[r][1];
- r2 = Tinv0[C2&255] ^ Tinv1[(C1>>8)&255] ^ Tinv2[(C0>>16)&255] ^ Tinv3[(C3>>24)&255] ^ KW[r][2];
- r3 = Tinv0[C3&255] ^ Tinv1[(C2>>8)&255] ^ Tinv2[(C1>>16)&255] ^ Tinv3[(C0>>24)&255] ^ KW[r][3];
-
+ i0 = t0; i1 = r3 >>> 8; i2 = t2 >>> 16; i3 = t1 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][0];
+
+ i0 = t1; i1 = t0 >>> 8; i2 = r3 >>> 16; i3 = t2 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][1];
+
+ i0 = t2; i1 = t1 >>> 8; i2 = t0 >>> 16; i3 = r3 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][2];
+
+ i0 = r3; i1 = t2 >>> 8; i2 = t1 >>> 16; i3 = t0 >>> 24;
+ i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255;
+ r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][3];
+
// the final round's table is a simple function of Si so we don't use a whole other four tables for it
- C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
- C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
- C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
- C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
+ i0 = r0; i1 = r3 >>> 8; i2 = r2 >>> 16; i3 = r1 >>> 24;
+ i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
+ this.C0 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][0];
+
+ i0 = r1; i1 = r0 >>> 8; i2 = r3 >>> 16; i3 = r2 >>> 24;
+ i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
+ this.C1 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][1];
+
+ i0 = r2; i1 = r1 >>> 8; i2 = r0 >>> 16; i3 = r3 >>> 24;
+ i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
+ this.C2 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][2];
+
+ i0 = r3; i1 = r2 >>> 8; i2 = r1 >>> 16; i3 = r0 >>> 24;
+ i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255;
+ this.C3 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][3];
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java
index 9b1e404..6980fd0 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java
@@ -301,7 +301,7 @@ public class DESEngine
* generate an integer based working key based on our secret key
* and what we processing we are planning to do.
*
- * Acknowledgements for this routine go to James Gillogly & Phil Karn.
+ * Acknowledgements for this routine go to James Gillogly &amp; Phil Karn.
* (whoever, and wherever they are!).
*/
protected int[] generateWorkingKey(
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
index d0c04f2..197b151 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
@@ -62,8 +62,8 @@ public class DESedeWrapEngine
/**
* Method init
*
- * @param forWrapping
- * @param param
+ * @param forWrapping true if for wrapping, false otherwise.
+ * @param param necessary parameters, may include KeyParameter, ParametersWithRandom, and ParametersWithIV
*/
public void init(boolean forWrapping, CipherParameters param)
{
@@ -132,9 +132,9 @@ public class DESedeWrapEngine
/**
* Method wrap
*
- * @param in
- * @param inOff
- * @param inLen
+ * @param in byte array containing the encoded key.
+ * @param inOff off set into in that the data starts at.
+ * @param inLen length of the data.
* @return the wrapped bytes.
*/
public byte[] wrap(byte[] in, int inOff, int inLen)
@@ -203,9 +203,9 @@ public class DESedeWrapEngine
/**
* Method unwrap
*
- * @param in
- * @param inOff
- * @param inLen
+ * @param in byte array containing the wrapped key.
+ * @param inOff off set into in that the data starts at.
+ * @param inLen length of the data.
* @return the unwrapped bytes.
* @throws InvalidCipherTextException
*/
@@ -309,10 +309,11 @@ public class DESedeWrapEngine
* - Compute the 20 octet SHA-1 hash on the key being wrapped.
* - Use the first 8 octets of this hash as the checksum value.
*
- * @param key
+ * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum.
+ *
+ * @param key the key to check,
* @return the CMS checksum.
* @throws RuntimeException
- * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
*/
private byte[] calculateCMSKeyChecksum(
byte[] key)
@@ -328,10 +329,11 @@ public class DESedeWrapEngine
}
/**
- * @param key
- * @param checksum
+ * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+ *
+ * @param key key to be validated.
+ * @param checksum the checksum.
* @return true if okay, false otherwise.
- * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
*/
private boolean checkCMSKeyChecksum(
byte[] key,
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java
index 4de7ea6..c1ceaa4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java
@@ -68,7 +68,7 @@ public class RC4Engine implements StreamCipher
return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
}
- public void processBytes(
+ public int processBytes(
byte[] in,
int inOff,
int len,
@@ -99,6 +99,8 @@ public class RC4Engine implements StreamCipher
out[i+outOff] = (byte)(in[i + inOff]
^ engineState[(engineState[x] + engineState[y]) & 0xff]);
}
+
+ return len;
}
public void reset()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java
index e0d86fc..6795ec9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java
@@ -4,6 +4,7 @@ import java.math.BigInteger;
import java.security.SecureRandom;
import org.bouncycastle.crypto.params.DHParameters;
+import org.bouncycastle.math.ec.WNafUtil;
import org.bouncycastle.util.BigIntegers;
class DHKeyGeneratorHelper
@@ -19,12 +20,19 @@ class DHKeyGeneratorHelper
BigInteger calculatePrivate(DHParameters dhParams, SecureRandom random)
{
- BigInteger p = dhParams.getP();
int limit = dhParams.getL();
if (limit != 0)
{
- return new BigInteger(limit, random).setBit(limit - 1);
+ int minWeight = limit >>> 2;
+ for (;;)
+ {
+ BigInteger x = new BigInteger(limit, random).setBit(limit - 1);
+ if (WNafUtil.getNafWeight(x) >= minWeight)
+ {
+ return x;
+ }
+ }
}
BigInteger min = TWO;
@@ -34,14 +42,22 @@ class DHKeyGeneratorHelper
min = ONE.shiftLeft(m - 1);
}
- BigInteger max = p.subtract(TWO);
BigInteger q = dhParams.getQ();
- if (q != null)
+ if (q == null)
{
- max = q.subtract(TWO);
+ q = dhParams.getP();
}
+ BigInteger max = q.subtract(TWO);
- return BigIntegers.createRandomInRange(min, max, random);
+ int minWeight = max.bitLength() >>> 2;
+ for (;;)
+ {
+ BigInteger x = BigIntegers.createRandomInRange(min, max, random);
+ if (WNafUtil.getNafWeight(x) >= minWeight)
+ {
+ return x;
+ }
+ }
}
BigInteger calculatePublic(DHParameters dhParams, BigInteger x)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java
index 05c7839..a0728b2 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java
@@ -6,6 +6,7 @@ import java.security.SecureRandom;
// BEGIN android-added
import java.util.logging.Logger;
// END android-added
+import org.bouncycastle.math.ec.WNafUtil;
import org.bouncycastle.util.BigIntegers;
class DHParametersHelper
@@ -31,6 +32,7 @@ class DHParametersHelper
// END android-added
BigInteger p, q;
int qLength = size - 1;
+ int minWeight = size >>> 2;
for (;;)
{
@@ -42,10 +44,28 @@ class DHParametersHelper
// p <- 2q + 1
p = q.shiftLeft(1).add(ONE);
- if (p.isProbablePrime(certainty) && (certainty <= 2 || q.isProbablePrime(certainty)))
+ if (!p.isProbablePrime(certainty))
{
- break;
+ continue;
}
+
+ if (certainty > 2 && !q.isProbablePrime(certainty - 2))
+ {
+ continue;
+ }
+
+ /*
+ * Require a minimum weight of the NAF representation, since low-weight primes may be
+ * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
+ *
+ * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+ */
+ if (WNafUtil.getNafWeight(p) < minWeight)
+ {
+ continue;
+ }
+
+ break;
}
// BEGIN android-added
long end = System.currentTimeMillis();
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java
index 93f49cf..ff3df35 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java
@@ -1,5 +1,8 @@
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;
@@ -7,11 +10,9 @@ import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+import org.bouncycastle.math.ec.WNafUtil;
import org.bouncycastle.util.BigIntegers;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
/**
* a DSA key pair generator.
*
@@ -45,13 +46,20 @@ public class DSAKeyPairGenerator
private static BigInteger generatePrivateKey(BigInteger q, SecureRandom random)
{
- // TODO Prefer this method? (change test cases that used fixed random)
- // B.1.1 Key Pair Generation Using Extra Random Bits
-// BigInteger c = new BigInteger(q.bitLength() + 64, random);
-// return c.mod(q.subtract(ONE)).add(ONE);
-
// B.1.2 Key Pair Generation by Testing Candidates
- return BigIntegers.createRandomInRange(ONE, q.subtract(ONE), random);
+ int minWeight = q.bitLength() >>> 2;
+ for (;;)
+ {
+ // TODO Prefer this method? (change test cases that used fixed random)
+ // B.1.1 Key Pair Generation Using Extra Random Bits
+// BigInteger x = new BigInteger(q.bitLength() + 64, random).mod(q.subtract(ONE)).add(ONE);
+
+ BigInteger x = BigIntegers.createRandomInRange(ONE, q.subtract(ONE), random);
+ if (WNafUtil.getNafWeight(x) >= minWeight)
+ {
+ return x;
+ }
+ }
}
private static BigInteger calculatePublicKey(BigInteger p, BigInteger g, BigInteger x)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
index d70ee8f..36b41cc 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
@@ -46,7 +46,7 @@ public class DSAParametersGenerator
/**
* initialise the key generator.
*
- * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments)
+ * @param size size of the key (range 2^512 -&gt; 2^1024 - 64 bit increments)
* @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
* @param random random byte source.
*/
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
index d5f5fc8..4f46a38 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
@@ -11,7 +11,10 @@ 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.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
+import org.bouncycastle.math.ec.WNafUtil;
public class ECKeyPairGenerator
implements AsymmetricCipherKeyPairGenerator, ECConstants
@@ -40,19 +43,42 @@ public class ECKeyPairGenerator
public AsymmetricCipherKeyPair generateKeyPair()
{
BigInteger n = params.getN();
- int nBitLength = n.bitLength();
- BigInteger d;
+ int nBitLength = n.bitLength();
+ int minWeight = nBitLength >>> 2;
- do
+ BigInteger d;
+ for (;;)
{
d = new BigInteger(nBitLength, random);
+
+ if (d.compareTo(TWO) < 0 || (d.compareTo(n) >= 0))
+ {
+ continue;
+ }
+
+ /*
+ * Require a minimum weight of the NAF representation, since low-weight primes may be
+ * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
+ *
+ * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+ */
+ if (WNafUtil.getNafWeight(d) < minWeight)
+ {
+ continue;
+ }
+
+ break;
}
- while (d.equals(ZERO) || (d.compareTo(n) >= 0));
- ECPoint Q = params.getG().multiply(d);
+ ECPoint Q = createBasePointMultiplier().multiply(params.getG(), d);
return new AsymmetricCipherKeyPair(
new ECPublicKeyParameters(Q, params),
new ECPrivateKeyParameters(d, params));
}
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
index f58069d..928c6a6 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
@@ -6,6 +6,7 @@ import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.bouncycastle.math.ec.WNafUtil;
import java.math.BigInteger;
@@ -19,83 +20,43 @@ public class RSAKeyPairGenerator
private RSAKeyGenerationParameters param;
- public void init(
- KeyGenerationParameters param)
+ public void init(KeyGenerationParameters param)
{
this.param = (RSAKeyGenerationParameters)param;
}
public AsymmetricCipherKeyPair generateKeyPair()
{
- BigInteger p, q, n, d, e, pSub1, qSub1, phi;
+ BigInteger p, q, n, d, e, pSub1, qSub1, phi;
//
// p and q values should have a length of half the strength in bits
//
int strength = param.getStrength();
- int pbitlength = (strength + 1) / 2;
- int qbitlength = strength - pbitlength;
+ int qBitlength = strength >>> 1;
+ int pBitlength = strength - qBitlength;
int mindiffbits = strength / 3;
+ int minWeight = strength >>> 2;
e = param.getPublicExponent();
// TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
// (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
- //
- // generate p, prime and (p-1) relatively prime to e
- //
- for (;;)
- {
- p = new BigInteger(pbitlength, 1, param.getRandom());
-
- if (p.mod(e).equals(ONE))
- {
- continue;
- }
-
- if (!p.isProbablePrime(param.getCertainty()))
- {
- continue;
- }
-
- if (e.gcd(p.subtract(ONE)).equals(ONE))
- {
- break;
- }
- }
+ p = chooseRandomPrime(pBitlength, e);
//
// generate a modulus of the required length
//
for (;;)
{
- // generate q, prime and (q-1) relatively prime to e,
- // and not equal to p
- //
- for (;;)
+ q = chooseRandomPrime(qBitlength, e);
+
+ // p and q should not be too close together (or equal!)
+ BigInteger diff = q.subtract(p).abs();
+ if (diff.bitLength() < mindiffbits)
{
- q = new BigInteger(qbitlength, 1, param.getRandom());
-
- if (q.subtract(p).abs().bitLength() < mindiffbits)
- {
- continue;
- }
-
- if (q.mod(e).equals(ONE))
- {
- continue;
- }
-
- if (!q.isProbablePrime(param.getCertainty()))
- {
- continue;
- }
-
- if (e.gcd(q.subtract(ONE)).equals(ONE))
- {
- break;
- }
+ continue;
}
//
@@ -103,16 +64,29 @@ public class RSAKeyPairGenerator
//
n = p.multiply(q);
- if (n.bitLength() == param.getStrength())
+ if (n.bitLength() != strength)
{
- break;
+ //
+ // if we get here our primes aren't big enough, make the largest
+ // of the two p and try again
+ //
+ p = p.max(q);
+ continue;
}
- //
- // if we get here our primes aren't big enough, make the largest
- // of the two p and try again
- //
- p = p.max(q);
+ /*
+ * Require a minimum weight of the NAF representation, since low-weight composites may
+ * be weak against a version of the number-field-sieve for factoring.
+ *
+ * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+ */
+ if (WNafUtil.getNafWeight(n) < minWeight)
+ {
+ p = chooseRandomPrime(pBitlength, e);
+ continue;
+ }
+
+ break;
}
if (p.compareTo(q) < 0)
@@ -134,14 +108,46 @@ public class RSAKeyPairGenerator
//
// calculate the CRT factors
//
- BigInteger dP, dQ, qInv;
+ BigInteger dP, dQ, qInv;
dP = d.remainder(pSub1);
dQ = d.remainder(qSub1);
qInv = q.modInverse(p);
return new AsymmetricCipherKeyPair(
- new RSAKeyParameters(false, n, e),
- new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
+ new RSAKeyParameters(false, n, e),
+ new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
+ }
+
+ /**
+ * Choose a random prime value for use with RSA
+ *
+ * @param bitlength the bit-length of the returned prime
+ * @param e the RSA public exponent
+ * @return a prime p, with (p-1) relatively prime to e
+ */
+ protected BigInteger chooseRandomPrime(int bitlength, BigInteger e)
+ {
+ for (;;)
+ {
+ BigInteger p = new BigInteger(bitlength, 1, param.getRandom());
+
+ if (p.mod(e).equals(ONE))
+ {
+ continue;
+ }
+
+ if (!p.isProbablePrime(param.getCertainty()))
+ {
+ continue;
+ }
+
+ if (!e.gcd(p.subtract(ONE)).equals(ONE))
+ {
+ continue;
+ }
+
+ return p;
+ }
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java
index 71b7595..fe46119 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java
@@ -7,6 +7,16 @@ import org.bouncycastle.crypto.InvalidCipherTextException;
/**
* A block cipher mode that includes authenticated encryption with a streaming mode and optional associated data.
+ * <p>
+ * Implementations of this interface may operate in a packet mode (where all input data is buffered and
+ * processed dugin the call to {@link #doFinal(byte[], int)}), or in a streaming mode (where output data is
+ * incrementally produced with each call to {@link #processByte(byte, byte[], int)} or
+ * {@link #processBytes(byte[], int, int, byte[], int)}.
+ * </p>
+ * This is important to consider during decryption: in a streaming mode, unauthenticated plaintext data
+ * may be output prior to the call to {@link #doFinal(byte[], int)} that results in an authentication
+ * failure. The higher level protocol utilising this cipher must ensure the plaintext data is handled
+ * appropriately until the end of data is reached and the entire ciphertext is authenticated.
* @see org.bouncycastle.crypto.params.AEADParameters
*/
public interface AEADBlockCipher
@@ -101,6 +111,11 @@ public interface AEADBlockCipher
/**
* return the size of the output buffer required for a processBytes
* an input of len bytes.
+ * <p>
+ * The returned size may be dependent on the initialisation of this cipher
+ * and may not be accurate once subsequent input data is processed - this method
+ * should be invoked immediately prior to input data being processed.
+ * </p>
*
* @param len the length of the input.
* @return the space required to accommodate a call to processBytes
@@ -111,7 +126,12 @@ public interface AEADBlockCipher
/**
* return the size of the output buffer required for a processBytes plus a
* doFinal with an input of len bytes.
- *
+ * <p>
+ * The returned size may be dependent on the initialisation of this cipher
+ * and may not be accurate once subsequent input data is processed - this method
+ * should be invoked immediately prior to a call to final processing of input data
+ * and a call to {@link #doFinal(byte[], int)}.
+ * </p>
* @param len the length of the input.
* @return the space required to accommodate a call to processBytes and doFinal
* with len bytes of input.
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
index fef51fd..7f870ca 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
@@ -7,6 +7,7 @@ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.ParametersWithIV;
@@ -42,7 +43,7 @@ public class CCMBlockCipher
this.cipher = c;
this.blockSize = c.getBlockSize();
this.macBlock = new byte[blockSize];
-
+
if (blockSize != 16)
{
throw new IllegalArgumentException("cipher required with a block size of 16.");
@@ -99,7 +100,7 @@ public class CCMBlockCipher
{
throw new IllegalArgumentException("nonce must have length from 7 to 13 octets");
}
-
+
reset();
}
@@ -130,6 +131,10 @@ public class CCMBlockCipher
public int processBytes(byte[] in, int inOff, int inLen, byte[] out, int outOff)
throws DataLengthException, IllegalStateException
{
+ if (in.length < (inOff + inLen))
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
data.write(in, inOff, inLen);
return 0;
@@ -155,15 +160,15 @@ public class CCMBlockCipher
/**
* Returns a byte array containing the mac calculated as part of the
* last encrypt or decrypt operation.
- *
+ *
* @return the last mac calculated.
*/
public byte[] getMac()
{
byte[] mac = new byte[macSize];
-
+
System.arraycopy(macBlock, 0, mac, 0, mac.length);
-
+
return mac;
}
@@ -267,7 +272,7 @@ public class CCMBlockCipher
outputLen = inLen + macSize;
if (output.length < (outputLen + outOff))
{
- throw new DataLengthException("Output buffer too short.");
+ throw new OutputLengthException("Output buffer too short.");
}
calculateMac(in, inOff, inLen, macBlock);
@@ -300,7 +305,7 @@ public class CCMBlockCipher
outputLen = inLen - macSize;
if (output.length < (outputLen + outOff))
{
- throw new DataLengthException("Output buffer too short.");
+ throw new OutputLengthException("Output buffer too short.");
}
System.arraycopy(in, inOff + outputLen, macBlock, 0, macSize);
@@ -350,18 +355,18 @@ public class CCMBlockCipher
// build b0
//
byte[] b0 = new byte[16];
-
+
if (hasAssociatedText())
{
b0[0] |= 0x40;
}
-
+
b0[0] |= (((cMac.getMacSize() - 2) / 2) & 0x7) << 3;
b0[0] |= ((15 - nonce.length) - 1) & 0x7;
-
+
System.arraycopy(nonce, 0, b0, 1, nonce.length);
-
+
int q = dataLen;
int count = 1;
while (q > 0)
@@ -370,22 +375,22 @@ public class CCMBlockCipher
q >>>= 8;
count++;
}
-
+
cMac.update(b0, 0, b0.length);
-
+
//
// process associated text
//
if (hasAssociatedText())
{
int extra;
-
+
int textLength = getAssociatedTextLength();
if (textLength < ((1 << 16) - (1 << 8)))
{
cMac.update((byte)(textLength >> 8));
cMac.update((byte)textLength);
-
+
extra = 2;
}
else // can't go any higher than 2^32
@@ -396,7 +401,7 @@ public class CCMBlockCipher
cMac.update((byte)(textLength >> 16));
cMac.update((byte)(textLength >> 8));
cMac.update((byte)textLength);
-
+
extra = 6;
}
@@ -418,7 +423,7 @@ public class CCMBlockCipher
}
}
}
-
+
//
// add the text
//
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
index a885169..6167d25 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
@@ -3,6 +3,7 @@ package org.bouncycastle.crypto.modes;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Arrays;
@@ -10,15 +11,17 @@ import org.bouncycastle.util.Arrays;
* implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
*/
public class CFBBlockCipher
- implements BlockCipher
+ extends StreamBlockCipher
{
private byte[] IV;
private byte[] cfbV;
private byte[] cfbOutV;
+ private byte[] inBuf;
private int blockSize;
private BlockCipher cipher = null;
private boolean encrypting;
+ private int byteCount;
/**
* Basic constructor.
@@ -31,22 +34,15 @@ public class CFBBlockCipher
BlockCipher cipher,
int bitBlockSize)
{
+ super(cipher);
+
this.cipher = cipher;
this.blockSize = bitBlockSize / 8;
this.IV = new byte[cipher.getBlockSize()];
this.cfbV = new byte[cipher.getBlockSize()];
this.cfbOutV = new byte[cipher.getBlockSize()];
- }
-
- /**
- * return the underlying block cipher that we are wrapping.
- *
- * @return the underlying block cipher that we are wrapping.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
+ this.inBuf = new byte[blockSize];
}
/**
@@ -117,6 +113,54 @@ public class CFBBlockCipher
return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8);
}
+ protected byte calculateByte(byte in)
+ throws DataLengthException, IllegalStateException
+ {
+ return (encrypting) ? encryptByte(in) : decryptByte(in);
+ }
+
+ private byte encryptByte(byte in)
+ {
+ if (byteCount == 0)
+ {
+ cipher.processBlock(cfbV, 0, cfbOutV, 0);
+ }
+
+ byte rv = (byte)(cfbOutV[byteCount] ^ in);
+ inBuf[byteCount++] = rv;
+
+ if (byteCount == blockSize)
+ {
+ byteCount = 0;
+
+ System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
+ System.arraycopy(inBuf, 0, cfbV, cfbV.length - blockSize, blockSize);
+ }
+
+ return rv;
+ }
+
+ private byte decryptByte(byte in)
+ {
+ if (byteCount == 0)
+ {
+ cipher.processBlock(cfbV, 0, cfbOutV, 0);
+ }
+
+ inBuf[byteCount] = in;
+ byte rv = (byte)(cfbOutV[byteCount++] ^ in);
+
+ if (byteCount == blockSize)
+ {
+ byteCount = 0;
+
+ System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
+ System.arraycopy(inBuf, 0, cfbV, cfbV.length - blockSize, blockSize);
+ }
+
+ return rv;
+ }
+
/**
* return the block size we are operating at.
*
@@ -147,7 +191,9 @@ public class CFBBlockCipher
int outOff)
throws DataLengthException, IllegalStateException
{
- return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ processBytes(in, inOff, blockSize, out, outOff);
+
+ return blockSize;
}
/**
@@ -169,31 +215,7 @@ public class CFBBlockCipher
int outOff)
throws DataLengthException, IllegalStateException
{
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- cipher.processBlock(cfbV, 0, cfbOutV, 0);
-
- //
- // XOR the cfbV with the plaintext producing the ciphertext
- //
- for (int i = 0; i < blockSize; i++)
- {
- out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]);
- }
-
- //
- // change over the input block.
- //
- System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
- System.arraycopy(out, outOff, cfbV, cfbV.length - blockSize, blockSize);
+ processBytes(in, inOff, blockSize, out, outOff);
return blockSize;
}
@@ -217,31 +239,7 @@ public class CFBBlockCipher
int outOff)
throws DataLengthException, IllegalStateException
{
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- cipher.processBlock(cfbV, 0, cfbOutV, 0);
-
- //
- // change over the input block.
- //
- System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
- System.arraycopy(in, inOff, cfbV, cfbV.length - blockSize, blockSize);
-
- //
- // XOR the cfbV with the ciphertext producing the plaintext
- //
- for (int i = 0; i < blockSize; i++)
- {
- out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]);
- }
+ processBytes(in, inOff, blockSize, out, outOff);
return blockSize;
}
@@ -263,6 +261,8 @@ public class CFBBlockCipher
public void reset()
{
System.arraycopy(IV, 0, cfbV, 0, IV.length);
+ Arrays.fill(inBuf, (byte)0);
+ byteCount = 0;
cipher.reset();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
index 9e617ec..024eb86 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
@@ -4,6 +4,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.modes.gcm.GCMExponentiator;
import org.bouncycastle.crypto.modes.gcm.GCMMultiplier;
import org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
@@ -11,8 +12,8 @@ import org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Pack;
/**
* Implements the Galois/Counter mode (GCM) detailed in
@@ -23,7 +24,7 @@ public class GCMBlockCipher
{
private static final int BLOCK_SIZE = 16;
- // not final due to a compiler bug
+ // not final due to a compiler bug
private BlockCipher cipher;
private GCMMultiplier multiplier;
private GCMExponentiator exp;
@@ -81,6 +82,10 @@ public class GCMBlockCipher
return cipher.getAlgorithmName() + "/GCM";
}
+ /**
+ * NOTE: MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits.
+ * Sizes less than 96 are not recommended, but are supported for specialized applications.
+ */
public void init(boolean forEncryption, CipherParameters params)
throws IllegalArgumentException
{
@@ -97,12 +102,12 @@ public class GCMBlockCipher
initialAssociatedText = param.getAssociatedText();
int macSizeBits = param.getMacSize();
- if (macSizeBits < 96 || macSizeBits > 128 || macSizeBits % 8 != 0)
+ if (macSizeBits < 32 || macSizeBits > 128 || macSizeBits % 8 != 0)
{
throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits);
}
- macSize = macSizeBits / 8;
+ macSize = macSizeBits / 8;
keyParam = param.getKey();
}
else if (params instanceof ParametersWithIV)
@@ -119,7 +124,7 @@ public class GCMBlockCipher
throw new IllegalArgumentException("invalid parameters passed to GCM");
}
- int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize);
+ int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize);
this.bufBlock = new byte[bufLength];
if (nonce == null || nonce.length < 1)
@@ -127,9 +132,7 @@ public class GCMBlockCipher
throw new IllegalArgumentException("IV must be at least 1 byte");
}
- // TODO This should be configurable by init parameters
- // (but must be 16 if nonce length not 12) (BLOCK_SIZE?)
-// this.tagLength = 16;
+ // TODO Restrict macSize to 16 if nonce length not 12?
// Cipher always used in forward mode
// if keyParam is null we're reusing the last key.
@@ -144,6 +147,10 @@ public class GCMBlockCipher
multiplier.init(H);
exp = null;
}
+ else if (this.H == null)
+ {
+ throw new IllegalArgumentException("Key must be specified in initial init");
+ }
this.J0 = new byte[BLOCK_SIZE];
@@ -188,7 +195,7 @@ public class GCMBlockCipher
if (forEncryption)
{
- return totalData + macSize;
+ return totalData + macSize;
}
return totalData < macSize ? 0 : totalData - macSize;
@@ -271,6 +278,10 @@ public class GCMBlockCipher
public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
throws DataLengthException
{
+ if (in.length < (inOff + len))
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
int resultLen = 0;
for (int i = 0; i < len; ++i)
@@ -288,6 +299,10 @@ public class GCMBlockCipher
private void outputBlock(byte[] output, int offset)
{
+ if (output.length < (offset + BLOCK_SIZE))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
if (totalLength == 0)
{
initCipher();
@@ -324,6 +339,10 @@ public class GCMBlockCipher
if (extra > 0)
{
+ if (out.length < (outOff + extra))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
gCTRPartial(bufBlock, 0, extra, out, outOff);
}
@@ -376,7 +395,6 @@ public class GCMBlockCipher
gHASHBlock(S, X);
- // TODO Fix this if tagLength becomes configurable
// T = MSBt(GCTRk(J0,S))
byte[] tag = new byte[BLOCK_SIZE];
cipher.processBlock(J0, 0, tag, 0);
@@ -390,6 +408,10 @@ public class GCMBlockCipher
if (forEncryption)
{
+ if (out.length < (outOff + extra + macSize))
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
// Append T to the message
System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize);
resultLen += macSize;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java
index 5297698..d9ff428 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java
@@ -3,14 +3,16 @@ package org.bouncycastle.crypto.modes;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.params.ParametersWithIV;
/**
* implements a Output-FeedBack (OFB) mode on top of a simple cipher.
*/
public class OFBBlockCipher
- implements BlockCipher
+ extends StreamBlockCipher
{
+ private int byteCount;
private byte[] IV;
private byte[] ofbV;
private byte[] ofbOutV;
@@ -29,6 +31,8 @@ public class OFBBlockCipher
BlockCipher cipher,
int blockSize)
{
+ super(cipher);
+
this.cipher = cipher;
this.blockSize = blockSize / 8;
@@ -38,16 +42,6 @@ public class OFBBlockCipher
}
/**
- * return the underlying block cipher that we are wrapping.
- *
- * @return the underlying block cipher that we are wrapping.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
- /**
* Initialise the cipher and, possibly, the initialisation vector (IV).
* If an IV isn't passed as part of the parameter, the IV will be all zeros.
* An IV which is too short is handled in FIPS compliant fashion.
@@ -113,7 +107,7 @@ public class OFBBlockCipher
return cipher.getAlgorithmName() + "/OFB" + (blockSize * 8);
}
-
+
/**
* return the block size we are operating at (in bytes).
*
@@ -144,32 +138,7 @@ public class OFBBlockCipher
int outOff)
throws DataLengthException, IllegalStateException
{
- if ((inOff + blockSize) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
-
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
- cipher.processBlock(ofbV, 0, ofbOutV, 0);
-
- //
- // XOR the ofbV with the plaintext producing the cipher text (and
- // the next input block).
- //
- for (int i = 0; i < blockSize; i++)
- {
- out[outOff + i] = (byte)(ofbOutV[i] ^ in[inOff + i]);
- }
-
- //
- // change over the input block.
- //
- System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize);
- System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize);
+ processBytes(in, inOff, blockSize, out, outOff);
return blockSize;
}
@@ -181,7 +150,29 @@ public class OFBBlockCipher
public void reset()
{
System.arraycopy(IV, 0, ofbV, 0, IV.length);
+ byteCount = 0;
cipher.reset();
}
+
+ protected byte calculateByte(byte in)
+ throws DataLengthException, IllegalStateException
+ {
+ if (byteCount == 0)
+ {
+ cipher.processBlock(ofbV, 0, ofbOutV, 0);
+ }
+
+ byte rv = (byte)(ofbOutV[byteCount++] ^ in);
+
+ if (byteCount == blockSize)
+ {
+ byteCount = 0;
+
+ System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize);
+ System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize);
+ }
+
+ return rv;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
index da8c4ae..5dd47ae 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
@@ -3,14 +3,18 @@ package org.bouncycastle.crypto.modes;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.SkippingStreamCipher;
+import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.Pack;
/**
* Implements the Segmented Integer Counter (SIC) mode on top of a simple
* block cipher. This mode is also known as CTR mode.
*/
public class SICBlockCipher
- implements BlockCipher
+ extends StreamBlockCipher
+ implements SkippingStreamCipher
{
private final BlockCipher cipher;
private final int blockSize;
@@ -18,7 +22,7 @@ public class SICBlockCipher
private byte[] IV;
private byte[] counter;
private byte[] counterOut;
-
+ private int byteCount;
/**
* Basic constructor.
@@ -27,25 +31,16 @@ public class SICBlockCipher
*/
public SICBlockCipher(BlockCipher c)
{
+ super(c);
+
this.cipher = c;
this.blockSize = cipher.getBlockSize();
this.IV = new byte[blockSize];
this.counter = new byte[blockSize];
this.counterOut = new byte[blockSize];
+ this.byteCount = 0;
}
-
- /**
- * return the underlying block cipher that we are wrapping.
- *
- * @return the underlying block cipher that we are wrapping.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
-
public void init(
boolean forEncryption, //ignored by this CTR mode
CipherParameters params)
@@ -53,17 +48,17 @@ public class SICBlockCipher
{
if (params instanceof ParametersWithIV)
{
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
- System.arraycopy(iv, 0, IV, 0, IV.length);
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+ System.arraycopy(iv, 0, IV, 0, IV.length);
- reset();
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
- // if null it's an IV changed only.
- if (ivParam.getParameters() != null)
- {
- cipher.init(true, ivParam.getParameters());
- }
+ reset();
}
else
{
@@ -81,33 +76,150 @@ public class SICBlockCipher
return cipher.getBlockSize();
}
-
public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
throws DataLengthException, IllegalStateException
{
- cipher.processBlock(counter, 0, counterOut, 0);
+ processBytes(in, inOff, blockSize, out, outOff);
- //
- // XOR the counterOut with the plaintext producing the cipher text
- //
- for (int i = 0; i < counterOut.length; i++)
+ return blockSize;
+ }
+
+ protected byte calculateByte(byte in)
+ throws DataLengthException, IllegalStateException
+ {
+ if (byteCount == 0)
{
- out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]);
+ cipher.processBlock(counter, 0, counterOut, 0);
+
+ return (byte)(counterOut[byteCount++] ^ in);
+ }
+
+ byte rv = (byte)(counterOut[byteCount++] ^ in);
+
+ if (byteCount == counter.length)
+ {
+ byteCount = 0;
+
+ incrementCounter();
}
+ return rv;
+ }
+
+ private void incrementCounter()
+ {
// increment counter by 1.
for (int i = counter.length - 1; i >= 0 && ++counter[i] == 0; i--)
{
; // do nothing - pre-increment and test for 0 in counter does the job.
}
+ }
- return counter.length;
+ private void decrementCounter()
+ {
+ if (counter[0] == 0)
+ {
+ boolean nonZero = false;
+
+ for (int i = counter.length - 1; i > 0; i--)
+ {
+ if (counter[i] != 0)
+ {
+ nonZero = true;
+ }
+ }
+
+ if (!nonZero)
+ {
+ throw new IllegalStateException("attempt to reduce counter past zero.");
+ }
+ }
+
+ // decrement counter by 1.
+ for (int i = counter.length - 1; i >= 0 && --counter[i] == -1; i--)
+ {
+ ;
+ }
}
+ private void adjustCounter(long n)
+ {
+ if (n >= 0)
+ {
+ long numBlocks = (n + byteCount) / blockSize;
+
+ for (long i = 0; i != numBlocks; i++)
+ {
+ incrementCounter();
+ }
+
+ byteCount = (int)((n + byteCount) - (blockSize * numBlocks));
+ }
+ else
+ {
+ long numBlocks = (-n - byteCount) / blockSize;
+
+ for (long i = 0; i != numBlocks; i++)
+ {
+ decrementCounter();
+ }
+
+ int gap = (int)(byteCount + n + (blockSize * numBlocks));
+
+ if (gap >= 0)
+ {
+ byteCount = 0;
+ }
+ else
+ {
+ decrementCounter();
+ byteCount = blockSize + gap;
+ }
+ }
+ }
public void reset()
{
System.arraycopy(IV, 0, counter, 0, counter.length);
cipher.reset();
+ this.byteCount = 0;
+ }
+
+ public long skip(long numberOfBytes)
+ {
+ adjustCounter(numberOfBytes);
+
+ cipher.processBlock(counter, 0, counterOut, 0);
+
+ return numberOfBytes;
+ }
+
+ public long seekTo(long position)
+ {
+ reset();
+
+ return skip(position);
+ }
+
+ public long getPosition()
+ {
+ byte[] res = new byte[IV.length];
+
+ System.arraycopy(counter, 0, res, 0, res.length);
+
+ for (int i = res.length - 1; i >= 1; i--)
+ {
+ int v = (res[i] - IV[i]);
+
+ if (v < 0)
+ {
+ res[i - 1]--;
+ v += 256;
+ }
+
+ res[i] = (byte)v;
+ }
+
+ return Pack.bigEndianToLong(res, res.length - 8) * blockSize + byteCount;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
index 3031a44..f5ed7e4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
@@ -1,7 +1,7 @@
package org.bouncycastle.crypto.modes.gcm;
-import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Pack;
abstract class GCMUtil
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
index 8535db5..69c1dce 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
@@ -1,7 +1,7 @@
package org.bouncycastle.crypto.modes.gcm;
-import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Pack;
public class Tables8kGCMMultiplier implements GCMMultiplier
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
index ee3fd60..d5928f7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
@@ -125,7 +125,7 @@ public class PaddedBufferedBlockCipher
if (leftOver == 0)
{
- return total - buf.length;
+ return Math.max(0, total - buf.length);
}
return total - leftOver;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java
new file mode 100644
index 0000000..5b694be
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java
@@ -0,0 +1,35 @@
+package org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECPoint;
+
+public class ECNamedDomainParameters
+ extends ECDomainParameters
+{
+ private ASN1ObjectIdentifier name;
+
+ public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n)
+ {
+ this(name, curve, G, n, null, null);
+ }
+
+ public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h)
+ {
+ this(name, curve, G, n, h, null);
+ }
+
+ public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h, byte[] seed)
+ {
+ super(curve, G, n, h, seed);
+
+ this.name = name;
+ }
+
+ public ASN1ObjectIdentifier getName()
+ {
+ return name;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
index 292c408..f3614f3 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
@@ -45,18 +45,19 @@ public class DSASigner
boolean forSigning,
CipherParameters param)
{
+ SecureRandom providedRandom = null;
+
if (forSigning)
{
if (param instanceof ParametersWithRandom)
{
- ParametersWithRandom rParam = (ParametersWithRandom)param;
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
- this.random = rParam.getRandom();
this.key = (DSAPrivateKeyParameters)rParam.getParameters();
+ providedRandom = rParam.getRandom();
}
else
{
- this.random = new SecureRandom();
this.key = (DSAPrivateKeyParameters)param;
}
}
@@ -64,6 +65,8 @@ public class DSASigner
{
this.key = (DSAPublicKeyParameters)param;
}
+
+ this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom);
}
/**
@@ -157,4 +160,9 @@ public class DSASigner
return new BigInteger(1, trunc);
}
}
+
+ protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
+ {
+ return !needed ? null : (provided != null) ? provided : new SecureRandom();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
index 2a1f98e..5fce112 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
@@ -5,13 +5,16 @@ import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DSA;
+import org.bouncycastle.crypto.params.ECDomainParameters;
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.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.ec.FixedPointCombMultiplier;
/**
* EC-DSA as described in X9.62
@@ -46,18 +49,19 @@ public class ECDSASigner
boolean forSigning,
CipherParameters param)
{
+ SecureRandom providedRandom = null;
+
if (forSigning)
{
if (param instanceof ParametersWithRandom)
{
- ParametersWithRandom rParam = (ParametersWithRandom)param;
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
- this.random = rParam.getRandom();
this.key = (ECPrivateKeyParameters)rParam.getParameters();
+ providedRandom = rParam.getRandom();
}
else
{
- this.random = new SecureRandom();
this.key = (ECPrivateKeyParameters)param;
}
}
@@ -65,6 +69,8 @@ public class ECDSASigner
{
this.key = (ECPublicKeyParameters)param;
}
+
+ this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom);
}
// 5.3 pg 28
@@ -78,50 +84,44 @@ public class ECDSASigner
public BigInteger[] generateSignature(
byte[] message)
{
- BigInteger n = key.getParameters().getN();
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
BigInteger e = calculateE(n, message);
- BigInteger r = null;
- BigInteger s = null;
+ BigInteger d = ((ECPrivateKeyParameters)key).getD();
if (kCalculator.isDeterministic())
{
- kCalculator.init(n, ((ECPrivateKeyParameters)key).getD(), message);
+ kCalculator.init(n, d, message);
}
else
{
kCalculator.init(n, random);
}
+ BigInteger r, s;
+
+ ECMultiplier basePointMultiplier = createBasePointMultiplier();
+
// 5.3.2
do // generate s
{
- BigInteger k = null;
-
+ BigInteger k;
do // generate r
{
k = kCalculator.nextK();
- ECPoint p = key.getParameters().getG().multiply(k).normalize();
+ ECPoint p = basePointMultiplier.multiply(ec.getG(), k).normalize();
// 5.3.3
- BigInteger x = p.getAffineXCoord().toBigInteger();
-
- r = x.mod(n);
+ r = p.getAffineXCoord().toBigInteger().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;
+ return new BigInteger[]{ r, s };
}
// 5.4 pg 29
@@ -135,7 +135,8 @@ public class ECDSASigner
BigInteger r,
BigInteger s)
{
- BigInteger n = key.getParameters().getN();
+ ECDomainParameters ec = key.getParameters();
+ BigInteger n = ec.getN();
BigInteger e = calculateE(n, message);
// r in the range [1,n-1]
@@ -155,7 +156,7 @@ public class ECDSASigner
BigInteger u1 = e.multiply(c).mod(n);
BigInteger u2 = r.multiply(c).mod(n);
- ECPoint G = key.getParameters().getG();
+ ECPoint G = ec.getG();
ECPoint Q = ((ECPublicKeyParameters)key).getQ();
ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2).normalize();
@@ -171,7 +172,7 @@ public class ECDSASigner
return v.equals(r);
}
- private BigInteger calculateE(BigInteger n, byte[] message)
+ protected BigInteger calculateE(BigInteger n, byte[] message)
{
int log2n = n.bitLength();
int messageBitLength = message.length * 8;
@@ -183,4 +184,14 @@ public class ECDSASigner
}
return e;
}
+
+ protected ECMultiplier createBasePointMultiplier()
+ {
+ return new FixedPointCombMultiplier();
+ }
+
+ protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
+ {
+ return !needed ? null : (provided != null) ? provided : new SecureRandom();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
index 18dd84e..2a32278 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
@@ -50,6 +50,8 @@ public class RSADigestSigner
oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256);
oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384);
oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512);
+ oidMap.put("SHA-512/224", NISTObjectIdentifiers.id_sha512_224);
+ oidMap.put("SHA-512/256", NISTObjectIdentifiers.id_sha512_256);
// BEGIN android-removed
// oidMap.put("MD2", PKCSObjectIdentifiers.md2);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/Pack.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/Pack.java
index f0da0bf..2ded8ef 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/Pack.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/Pack.java
@@ -1,5 +1,8 @@
package org.bouncycastle.crypto.util;
+/**
+ * @deprecated use org.bouncycastle.util.pack
+ */
public abstract class Pack
{
public static int bigEndianToInt(byte[] bs, int off)
@@ -114,6 +117,15 @@ public abstract class Pack
}
}
+ public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ ns[nOff + i] = littleEndianToInt(bs, bOff);
+ bOff += 4;
+ }
+ }
+
public static byte[] intToLittleEndian(int n)
{
byte[] bs = new byte[4];
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
index d997db7..0175aa1 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
@@ -9,7 +9,6 @@ import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
// BEGIN android-removed
// import org.bouncycastle.asn1.oiw.ElGamalParameter;
// END android-removed
@@ -25,12 +24,14 @@ import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import org.bouncycastle.crypto.ec.CustomNamedCurves;
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.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
// BEGIN android-removed
// import org.bouncycastle.crypto.params.ElGamalParameters;
@@ -104,8 +105,8 @@ public class PrivateKeyFactory
// BEGIN android-removed
// else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
// {
- // ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
- // ASN1Integer = (ASN1Integer)keyInfo.parsePrivateKey();
+ // ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
+ // ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
//
// return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(
// params.getP(), params.getG()));
@@ -130,24 +131,30 @@ public class PrivateKeyFactory
X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters());
X9ECParameters x9;
+ ECDomainParameters dParams;
+
if (params.isNamedCurve())
{
- ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
- x9 = ECNamedCurveTable.getByOID(oid);
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
+
+ x9 = CustomNamedCurves.getByOID(oid);
+ if (x9 == null)
+ {
+ x9 = ECNamedCurveTable.getByOID(oid);
+ }
+ dParams = new ECNamedDomainParameters(
+ oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
}
else
{
x9 = X9ECParameters.getInstance(params.getParameters());
+ dParams = new ECDomainParameters(
+ x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
}
ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey());
BigInteger d = ec.getKey();
- // TODO We lose any named parameters here
-
- ECDomainParameters dParams = new ECDomainParameters(
- x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
-
return new ECPrivateKeyParameters(d, dParams);
}
else
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
index 7ade197..2b33321 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
@@ -10,7 +10,6 @@ import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
// BEGIN android-removed
// import org.bouncycastle.asn1.oiw.ElGamalParameter;
@@ -31,6 +30,7 @@ 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.ec.CustomNamedCurves;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.crypto.params.DHPublicKeyParameters;
@@ -38,6 +38,7 @@ import org.bouncycastle.crypto.params.DHValidationParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
// BEGIN android-removed
// import org.bouncycastle.crypto.params.ElGamalParameters;
@@ -139,7 +140,7 @@ public class PublicKeyFactory
// BEGIN android-removed
// else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
// {
- // ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
+ // ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
// ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
//
// return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
@@ -166,24 +167,30 @@ public class PublicKeyFactory
X962Parameters params = X962Parameters.getInstance(algId.getParameters());
X9ECParameters x9;
+ ECDomainParameters dParams;
+
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
- x9 = ECNamedCurveTable.getByOID(oid);
+
+ x9 = CustomNamedCurves.getByOID(oid);
+ if (x9 == null)
+ {
+ x9 = ECNamedCurveTable.getByOID(oid);
+ }
+ dParams = new ECNamedDomainParameters(
+ oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
}
else
{
x9 = X9ECParameters.getInstance(params.getParameters());
+ dParams = new ECDomainParameters(
+ x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
}
ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes());
X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key);
- // TODO We lose any named parameters here
-
- ECDomainParameters dParams = new ECDomainParameters(
- x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
-
return new ECPublicKeyParameters(derQ.getPoint(), dParams);
}
else
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java
deleted file mode 100644
index d7677f3..0000000
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.jcajce;
-
-import java.io.IOException;
-import java.security.AlgorithmParameters;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Primitive;
-
-public class JcaJceUtils
-{
- private JcaJceUtils()
- {
-
- }
-
- /**
- * Extract an ASN.1 encodable from an AlgorithmParameters object.
- *
- * @param params the object to get the encoding used to create the return value.
- * @return an ASN.1 object representing the primitives making up the params parameter.
- * @throws IOException if an encoding cannot be extracted.
- */
- public static ASN1Encodable extractParameters(AlgorithmParameters params)
- throws IOException
- {
- // we try ASN.1 explicitly first just in case and then role back to the default.
- ASN1Encodable asn1Params;
- try
- {
- asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
- }
- catch (Exception ex)
- {
- asn1Params = ASN1Primitive.fromByteArray(params.getEncoded());
- }
-
- return asn1Params;
- }
-
- public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams)
- throws IOException
- {
- // we try ASN.1 explicitly first just in case and then role back to the default.
- try
- {
- params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1");
- }
- catch (Exception ex)
- {
- params.init(sParams.toASN1Primitive().getEncoded());
- }
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java
index bfedc81..d43924d 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java
@@ -1,14 +1,10 @@
package org.bouncycastle.jcajce.provider.asymmetric;
-// BEGIN android-added
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jcajce.provider.asymmetric.dh.KeyFactorySpi;
-// END android-added
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.util.AsymmetricAlgorithmProvider;
-// BEGIN android-added
-import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
-// END android-added
public class DH
{
@@ -31,10 +27,6 @@ public class DH
provider.addAlgorithm("KeyFactory.DH", PREFIX + "KeyFactorySpi");
provider.addAlgorithm("Alg.Alias.KeyFactory.DIFFIEHELLMAN", "DH");
- // BEGIN android-added
- AsymmetricKeyInfoConverter keyFact = new KeyFactorySpi();
- registerOid(provider, PKCSObjectIdentifiers.dhKeyAgreement, "DH", keyFact);
- // END android-added
provider.addAlgorithm("AlgorithmParameters.DH", PREFIX + "AlgorithmParametersSpi");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters.DIFFIEHELLMAN", "DH");
@@ -49,6 +41,9 @@ public class DH
// provider.addAlgorithm("Cipher.DHIESWITHAES", PREFIX + "IESCipher$IESwithAES");
// provider.addAlgorithm("Cipher.DHIESWITHDESEDE", PREFIX + "IESCipher$IESwithDESede");
// END android-removed
+
+ registerOid(provider, PKCSObjectIdentifiers.dhKeyAgreement, "DH", new KeyFactorySpi());
+ registerOid(provider, X9ObjectIdentifiers.dhpublicnumber, "DH", new KeyFactorySpi());
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java
index 43e5861..bd83a8a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java
@@ -1,6 +1,7 @@
package org.bouncycastle.jcajce.provider.asymmetric;
// BEGIN android-removed
+// import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
// import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
// import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
// END android-removed
@@ -28,6 +29,7 @@ public class EC
// provider.addAlgorithm("KeyAgreement.ECMQV", PREFIX + "KeyAgreementSpi$MQV");
// provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA1KDF");
// provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA1KDF");
+ // provider.addAlgorithm("KeyAgreement.ECDHWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHwithSHA1KDF");
// END android-removed
registerOid(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC", new KeyFactorySpi.EC());
@@ -37,10 +39,10 @@ public class EC
// registerOid(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV());
// END android-removed
+ registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
+ // TODO Should this be an alias for ECDH?
+ registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
// BEGIN android-removed
- // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
- // // TODO Should this be an alias for ECDH?
- // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
// registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "EC");
// END android-removed
@@ -56,6 +58,7 @@ public class EC
// BEGIN android-removed
// provider.addAlgorithm("KeyPairGenerator.ECDSA", PREFIX + "KeyPairGeneratorSpi$ECDSA");
// provider.addAlgorithm("KeyPairGenerator.ECDH", PREFIX + "KeyPairGeneratorSpi$ECDH");
+ // provider.addAlgorithm("KeyPairGenerator.ECDHWITHSHA1KDF", PREFIX + "KeyPairGeneratorSpi$ECDH");
// provider.addAlgorithm("KeyPairGenerator.ECDHC", PREFIX + "KeyPairGeneratorSpi$ECDHC");
// provider.addAlgorithm("KeyPairGenerator.ECIES", PREFIX + "KeyPairGeneratorSpi$ECDH");
// provider.addAlgorithm("KeyPairGenerator.ECMQV", PREFIX + "KeyPairGeneratorSpi$ECMQV");
@@ -65,6 +68,10 @@ public class EC
// provider.addAlgorithm("Cipher.ECIESWITHAES", PREFIX + "IESCipher$ECIESwithAES");
// provider.addAlgorithm("Cipher.ECIESwithDESEDE", PREFIX + "IESCipher$ECIESwithDESede");
// provider.addAlgorithm("Cipher.ECIESWITHDESEDE", PREFIX + "IESCipher$ECIESwithDESede");
+ // provider.addAlgorithm("Cipher.ECIESwithAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC");
+ // provider.addAlgorithm("Cipher.ECIESWITHAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC");
+ // provider.addAlgorithm("Cipher.ECIESwithDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC");
+ // provider.addAlgorithm("Cipher.ECIESWITHDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC");
// END android-removed
provider.addAlgorithm("Signature.ECDSA", PREFIX + "SignatureSpi$ecDSA");
@@ -106,6 +113,13 @@ public class EC
// addSignatureAlgorithm(provider, "SHA256", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA256", EACObjectIdentifiers.id_TA_ECDSA_SHA_256);
// addSignatureAlgorithm(provider, "SHA384", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA384", EACObjectIdentifiers.id_TA_ECDSA_SHA_384);
// addSignatureAlgorithm(provider, "SHA512", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA512", EACObjectIdentifiers.id_TA_ECDSA_SHA_512);
+ //
+ // addSignatureAlgorithm(provider, "SHA1", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA", BSIObjectIdentifiers.ecdsa_plain_SHA1);
+ // addSignatureAlgorithm(provider, "SHA224", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA224", BSIObjectIdentifiers.ecdsa_plain_SHA224);
+ // addSignatureAlgorithm(provider, "SHA256", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA256", BSIObjectIdentifiers.ecdsa_plain_SHA256);
+ // addSignatureAlgorithm(provider, "SHA384", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA384", BSIObjectIdentifiers.ecdsa_plain_SHA384);
+ // addSignatureAlgorithm(provider, "SHA512", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA512", BSIObjectIdentifiers.ecdsa_plain_SHA512);
+ // addSignatureAlgorithm(provider, "RIPEMD160", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecPlainDSARP160", BSIObjectIdentifiers.ecdsa_plain_RIPEMD160);
// END android-removed
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java
index 901e27d..2265199 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java
@@ -91,6 +91,10 @@ public class RSA
// provider.addAlgorithm("Signature." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA");
// provider.addAlgorithm("Signature.OID." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA");
//
+ // provider.addAlgorithm("Signature.SHA224WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA224withRSA");
+ // provider.addAlgorithm("Signature.SHA256WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA256withRSA");
+ // provider.addAlgorithm("Signature.SHA384WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA384withRSA");
+ // provider.addAlgorithm("Signature.SHA512WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA512withRSA");
// provider.addAlgorithm("Signature.SHA224withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA224withRSA");
// provider.addAlgorithm("Signature.SHA256withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA256withRSA");
// provider.addAlgorithm("Signature.SHA384withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA384withRSA");
@@ -112,10 +116,6 @@ public class RSA
// provider.addAlgorithm("Alg.Alias.Signature.SHA256withRSAandMGF1", "SHA256withRSA/PSS");
// provider.addAlgorithm("Alg.Alias.Signature.SHA384withRSAandMGF1", "SHA384withRSA/PSS");
// provider.addAlgorithm("Alg.Alias.Signature.SHA512withRSAandMGF1", "SHA512withRSA/PSS");
- // provider.addAlgorithm("Alg.Alias.Signature.SHA224WITHRSAANDMGF1", "SHA224withRSA/PSS");
- // provider.addAlgorithm("Alg.Alias.Signature.SHA256WITHRSAANDMGF1", "SHA256withRSA/PSS");
- // provider.addAlgorithm("Alg.Alias.Signature.SHA384WITHRSAANDMGF1", "SHA384withRSA/PSS");
- // provider.addAlgorithm("Alg.Alias.Signature.SHA512WITHRSAANDMGF1", "SHA512withRSA/PSS");
//
// if (provider.hasAlgorithm("MessageDigest", "MD2"))
// {
@@ -131,7 +131,7 @@ public class RSA
if (provider.hasAlgorithm("MessageDigest", "MD5"))
{
addDigestSignature(provider, "MD5", PREFIX + "DigestSignatureSpi$MD5", PKCSObjectIdentifiers.md5WithRSAEncryption);
- // BEGIN android-removed
+ // END android-removed
// provider.addAlgorithm("Signature.MD5withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$MD5WithRSAEncryption");
// provider.addAlgorithm("Alg.Alias.Signature.MD5WithRSA/ISO9796-2", "MD5withRSA/ISO9796-2");
// END android-removed
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java
index c6ddf9b..d2c2c71 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java
@@ -34,9 +34,9 @@ public class KeyPairGeneratorSpi
int strength,
SecureRandom random)
{
- if (strength < 512 || strength > 1024 || strength % 64 != 0)
+ if (strength < 512 || strength > 4096 || ((strength < 1024) && strength % 64 != 0) || (strength >= 1024 && strength % 1024 != 0))
{
- throw new InvalidParameterException("strength must be from 512 - 1024 and a multiple of 64");
+ throw new InvalidParameterException("strength must be from 512 - 4096 and a multiple of 1024 above 1024");
}
this.strength = strength;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java
index 0eaae1d..ac0ddf5 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java
@@ -34,6 +34,8 @@ import org.bouncycastle.jce.interfaces.ECPointEncoder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.custom.sec.SecP256K1Point;
+import org.bouncycastle.math.ec.custom.sec.SecP256R1Point;
public class BCECPublicKey
implements ECPublicKey, org.bouncycastle.jce.interfaces.ECPublicKey, ECPointEncoder
@@ -82,6 +84,8 @@ public class BCECPublicKey
ECCurve curve = spec.getParams().getCurve();
EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed());
+ // this may seem a little long-winded but it's how we pick up the custom curve.
+ this.q = EC5Util.convertCurve(ellipticCurve).createPoint(spec.getQ().getAffineXCoord().toBigInteger(), spec.getQ().getAffineYCoord().toBigInteger());
this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams());
}
else
@@ -132,7 +136,6 @@ public class BCECPublicKey
ECDomainParameters dp = params.getParameters();
this.algorithm = algorithm;
- this.q = params.getQ();
if (spec == null)
{
@@ -147,6 +150,8 @@ public class BCECPublicKey
this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec);
}
+ this.q = EC5Util.convertCurve(ecSpec.getCurve()).createPoint(params.getQ().getAffineXCoord().toBigInteger(), params.getQ().getAffineYCoord().toBigInteger());
+
this.configuration = configuration;
}
@@ -369,14 +374,7 @@ public class BCECPublicKey
{
if (ecSpec == null)
{
- if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp)
- {
- return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord());
- }
- else
- {
- return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord());
- }
+ return q.getDetachedPoint();
}
return q;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
index ea36dfd..3dbe004 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
@@ -17,6 +17,7 @@ import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x9.X9IntegerConverter;
import org.bouncycastle.crypto.BasicAgreement;
@@ -30,6 +31,7 @@ import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
// import org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator;
// END android-removed
import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.crypto.params.DESParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
@@ -45,6 +47,7 @@ import org.bouncycastle.jce.interfaces.ECPublicKey;
// import org.bouncycastle.jce.interfaces.MQVPublicKey;
// END android-removed
import org.bouncycastle.util.Integers;
+import org.bouncycastle.util.Strings;
/**
* Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363
@@ -57,9 +60,12 @@ public class KeyAgreementSpi
{
private static final X9IntegerConverter converter = new X9IntegerConverter();
private static final Hashtable algorithms = new Hashtable();
+ private static final Hashtable oids = new Hashtable();
+ private static final Hashtable des = new Hashtable();
static
{
+ Integer i64 = Integers.valueOf(64);
Integer i128 = Integers.valueOf(128);
Integer i192 = Integers.valueOf(192);
Integer i256 = Integers.valueOf(256);
@@ -71,6 +77,18 @@ public class KeyAgreementSpi
algorithms.put(NISTObjectIdentifiers.id_aes192_wrap.getId(), i192);
algorithms.put(NISTObjectIdentifiers.id_aes256_wrap.getId(), i256);
algorithms.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), i192);
+ algorithms.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), i192);
+ algorithms.put(OIWObjectIdentifiers.desCBC.getId(), i64);
+
+ oids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC);
+ oids.put("AES", NISTObjectIdentifiers.id_aes256_CBC);
+ oids.put("DES", OIWObjectIdentifiers.desCBC);
+
+ des.put("DES", "DES");
+ des.put("DESEDE", "DES");
+ des.put(OIWObjectIdentifiers.desCBC.getId(), "DES");
+ des.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DES");
+ des.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DES");
}
private String kaAlgorithm;
@@ -84,7 +102,7 @@ public class KeyAgreementSpi
private byte[] bigIntToBytes(
BigInteger r)
{
- return converter.integerToBytes(r, converter.getByteLength(parameters.getG().getAffineXCoord()));
+ return converter.integerToBytes(r, converter.getByteLength(parameters.getCurve()));
}
protected KeyAgreementSpi(
@@ -189,18 +207,25 @@ public class KeyAgreementSpi
throws NoSuchAlgorithmException
{
byte[] secret = bigIntToBytes(result);
+ String algKey = Strings.toUpperCase(algorithm);
+ String oidAlgorithm = algorithm;
+
+ if (oids.containsKey(algKey))
+ {
+ oidAlgorithm = ((ASN1ObjectIdentifier)oids.get(algKey)).getId();
+ }
// BEGIN android-removed
// if (kdf != null)
// {
- // if (!algorithms.containsKey(algorithm))
+ // if (!algorithms.containsKey(oidAlgorithm))
// {
// throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm);
// }
//
- // int keySize = ((Integer)algorithms.get(algorithm)).intValue();
+ // int keySize = ((Integer)algorithms.get(oidAlgorithm)).intValue();
//
- // DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(algorithm), keySize, secret);
+ // DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(oidAlgorithm), keySize, secret);
//
// byte[] keyBytes = new byte[keySize / 8];
// kdf.init(params);
@@ -210,7 +235,21 @@ public class KeyAgreementSpi
// else
// END android-removed
{
- // TODO Should we be ensuring the key is the right length?
+ if (algorithms.containsKey(oidAlgorithm))
+ {
+ Integer length = (Integer)algorithms.get(oidAlgorithm);
+
+ byte[] key = new byte[length.intValue() / 8];
+
+ System.arraycopy(secret, 0, key, 0, key.length);
+
+ secret = key;
+ }
+ }
+
+ if (des.containsKey(oidAlgorithm))
+ {
+ DESParameters.setOddParity(secret);
}
return new SecretKeySpec(secret, algorithm);
@@ -222,12 +261,11 @@ public class KeyAgreementSpi
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
- // BEGIN android-added
if (params != null)
{
throw new InvalidAlgorithmParameterException("No algorithm parameters supported");
}
- // END android-added
+
initFromKey(key);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
index 42bb895..1239609 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
@@ -91,22 +91,20 @@ public abstract class KeyPairGeneratorSpi
// BEGIN android-added
}
// END android-added
+
ECGenParameterSpec ecParams = (ECGenParameterSpec)ecParameters.get(Integers.valueOf(strength));
+ if (ecParams == null)
+ {
+ throw new InvalidParameterException("unknown key size.");
+ }
- if (ecParams != null)
+ try
{
- try
- {
- initialize(ecParams, random);
- }
- catch (InvalidAlgorithmParameterException e)
- {
- throw new InvalidParameterException("key size not configurable.");
- }
+ initialize(ecParams, random);
}
- else
+ catch (InvalidAlgorithmParameterException e)
{
- throw new InvalidParameterException("unknown key size.");
+ throw new InvalidParameterException("key size not configurable.");
}
}
@@ -120,97 +118,42 @@ public abstract class KeyPairGeneratorSpi
random = this.random;
}
// END android-added
- if (params instanceof ECParameterSpec)
+ if (params == null)
{
- ECParameterSpec p = (ECParameterSpec)params;
- this.ecParams = params;
-
- param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random);
+ ECParameterSpec implicitCA = configuration.getEcImplicitlyCa();
+ if (implicitCA == null)
+ {
+ throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set");
+ }
- engine.init(param);
- initialised = true;
+ this.ecParams = null;
+ this.param = createKeyGenParamsBC(implicitCA, random);
}
- else if (params instanceof java.security.spec.ECParameterSpec)
+ else if (params instanceof 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;
+ this.param = createKeyGenParamsBC((ECParameterSpec)params, random);
}
- else if (params instanceof ECGenParameterSpec || params instanceof ECNamedCurveGenParameterSpec)
+ else if (params instanceof java.security.spec.ECParameterSpec)
{
- String curveName;
-
- if (params instanceof ECGenParameterSpec)
- {
- curveName = ((ECGenParameterSpec)params).getName();
- }
- else
- {
- curveName = ((ECNamedCurveGenParameterSpec)params).getName();
- }
-
- X9ECParameters ecP = ECNamedCurveTable.getByName(curveName);
- if (ecP == null)
- {
- // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug)
- try
- {
- ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(curveName);
- ecP = ECNamedCurveTable.getByOID(oid);
- 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;
+ this.ecParams = params;
+ this.param = createKeyGenParamsJCE((java.security.spec.ECParameterSpec)params, random);
}
- else if (params == null && configuration.getEcImplicitlyCa() != null)
+ else if (params instanceof ECGenParameterSpec)
{
- ECParameterSpec p = configuration.getEcImplicitlyCa();
- this.ecParams = params;
-
- param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random);
-
- engine.init(param);
- initialised = true;
+ initializeNamedCurve(((ECGenParameterSpec)params).getName(), random);
}
- else if (params == null && configuration.getEcImplicitlyCa() == null)
+ else if (params instanceof ECNamedCurveGenParameterSpec)
{
- throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set");
+ initializeNamedCurve(((ECNamedCurveGenParameterSpec)params).getName(), random);
}
else
{
throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec");
}
+
+ engine.init(param);
+ initialised = true;
}
public KeyPair generateKeyPair()
@@ -246,6 +189,58 @@ public abstract class KeyPairGeneratorSpi
return new KeyPair(pubKey, new BCECPrivateKey(algorithm, priv, pubKey, p, configuration));
}
}
+
+ protected ECKeyGenerationParameters createKeyGenParamsBC(ECParameterSpec p, SecureRandom r)
+ {
+ return new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), r);
+ }
+
+ protected ECKeyGenerationParameters createKeyGenParamsJCE(java.security.spec.ECParameterSpec p, SecureRandom r)
+ {
+ ECCurve curve = EC5Util.convertCurve(p.getCurve());
+ ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false);
+ BigInteger n = p.getOrder();
+ BigInteger h = BigInteger.valueOf(p.getCofactor());
+ ECDomainParameters dp = new ECDomainParameters(curve, g, n, h);
+ return new ECKeyGenerationParameters(dp, r);
+ }
+
+ protected ECNamedCurveSpec createNamedCurveSpec(String curveName)
+ throws InvalidAlgorithmParameterException
+ {
+ // NOTE: Don't bother with custom curves here as the curve will be converted to JCE type shortly
+
+ X9ECParameters p = ECNamedCurveTable.getByName(curveName);
+ if (p == null)
+ {
+ try
+ {
+ // Check whether it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug)
+ p = ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(curveName));
+ if (p == null)
+ {
+ throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName);
+ }
+ }
+ catch (IllegalArgumentException ex)
+ {
+ throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
+ }
+ }
+
+ // Work-around for JDK bug -- it won't look up named curves properly if seed is present
+ byte[] seed = null; //p.getSeed();
+
+ return new ECNamedCurveSpec(curveName, p.getCurve(), p.getG(), p.getN(), p.getH(), seed);
+ }
+
+ protected void initializeNamedCurve(String curveName, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ ECNamedCurveSpec namedCurve = createNamedCurveSpec(curveName);
+ this.ecParams = namedCurve;
+ this.param = createKeyGenParamsJCE(namedCurve, random);
+ }
}
public static class ECDSA
@@ -283,4 +278,4 @@ public abstract class KeyPairGeneratorSpi
super("ECMQV", BouncyCastleProvider.CONFIGURATION);
}
}
-} \ No newline at end of file
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
index 3757229..26811d1 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
@@ -249,7 +249,7 @@ public class SignatureSpi
// {
// public ecCVCDSA()
// {
- // super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder());
+ // super(new SHA1Digest(), new ECDSASigner(), new PlainDSAEncoder());
// }
// }
//
@@ -258,7 +258,7 @@ public class SignatureSpi
// {
// public ecCVCDSA224()
// {
- // super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder());
+ // super(new SHA224Digest(), new ECDSASigner(), new PlainDSAEncoder());
// }
// }
//
@@ -267,7 +267,7 @@ public class SignatureSpi
// {
// public ecCVCDSA256()
// {
- // super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder());
+ // super(new SHA256Digest(), new ECDSASigner(), new PlainDSAEncoder());
// }
// }
//
@@ -276,7 +276,7 @@ public class SignatureSpi
// {
// public ecCVCDSA384()
// {
- // super(new SHA384Digest(), new ECDSASigner(), new CVCDSAEncoder());
+ // super(new SHA384Digest(), new ECDSASigner(), new PlainDSAEncoder());
// }
// }
//
@@ -285,7 +285,16 @@ public class SignatureSpi
// {
// public ecCVCDSA512()
// {
- // super(new SHA512Digest(), new ECDSASigner(), new CVCDSAEncoder());
+ // super(new SHA512Digest(), new ECDSASigner(), new PlainDSAEncoder());
+ // }
+ // }
+ //
+ // static public class ecPlainDSARP160
+ // extends SignatureSpi
+ // {
+ // public ecPlainDSARP160()
+ // {
+ // super(new RIPEMD160Digest(), new ECDSASigner(), new PlainDSAEncoder());
// }
// }
// END android-removed
@@ -320,66 +329,68 @@ public class SignatureSpi
}
}
- 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;
- }
- }
+ // BEGIN android-removed
+ // private static class PlainDSAEncoder
+ // 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;
+ // }
+ // }
+ // END android-removed
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java
index 0aa81b4..b82c5f8 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java
@@ -55,6 +55,12 @@ public class BCRSAPrivateKey
this.privateExponent = key.getPrivateExponent();
}
+ BCRSAPrivateKey(org.bouncycastle.asn1.pkcs.RSAPrivateKey key)
+ {
+ this.modulus = key.getModulus();
+ this.privateExponent = key.getPrivateExponent();
+ }
+
public BigInteger getModulus()
{
return modulus;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java
index a2114fa..6f5292c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java
@@ -1,5 +1,6 @@
package org.bouncycastle.jcajce.provider.asymmetric.rsa;
+import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@@ -156,6 +157,10 @@ public class BCRSAPublicKey
{
algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
}
+ catch (EOFException e)
+ {
+ algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
+ }
}
private void writeObject(
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
index ae40cbe..dcb9c23 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
@@ -311,7 +311,7 @@ public class CipherSpi
}
else
{
- throw new IllegalArgumentException("unknown parameter type.");
+ throw new InvalidAlgorithmParameterException("unknown parameter type: " + params.getClass().getName());
}
if (!(cipher instanceof RSABlindedEngine))
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java
index d8eb539..80690f7 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java
@@ -137,7 +137,16 @@ public class KeyFactorySpi
if (RSAUtil.isRsaOid(algOid))
{
- return new BCRSAPrivateCrtKey(keyInfo);
+ RSAPrivateKey rsaPrivKey = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey());
+
+ if (rsaPrivKey.getCoefficient().intValue() == 0)
+ {
+ return new BCRSAPrivateKey(rsaPrivKey);
+ }
+ else
+ {
+ return new BCRSAPrivateCrtKey(keyInfo);
+ }
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java
index 490bf4e..cb34f44 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java
@@ -1,6 +1,5 @@
package org.bouncycastle.jcajce.provider.asymmetric.util;
-import java.io.IOException;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java
index 5eea1b9..d5b62fe 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java
@@ -7,22 +7,46 @@ import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import org.bouncycastle.asn1.x9.ECNamedCurveTable;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
+import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
public class EC5Util
{
+ private static Map customCurves = new HashMap();
+
+ static
+ {
+ Enumeration e = CustomNamedCurves.getNames();
+ while (e.hasMoreElements())
+ {
+ String name = (String)e.nextElement();
+
+ X9ECParameters curveParams = ECNamedCurveTable.getByName(name);
+ if (curveParams != null) // there may not be a regular curve, may just be a custom curve.
+ {
+ customCurves.put(curveParams.getCurve(), CustomNamedCurves.getByName(name).getCurve());
+ }
+ }
+ }
+
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)
+ if (ECAlgorithms.isFpCurve(curve))
{
- return new EllipticCurve(new ECFieldFp(((ECCurve.Fp)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null);
+ return new EllipticCurve(new ECFieldFp(curve.getField().getCharacteristic()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null);
}
else
{
@@ -53,7 +77,14 @@ public class EC5Util
if (field instanceof ECFieldFp)
{
- return new ECCurve.Fp(((ECFieldFp)field).getP(), a, b);
+ ECCurve.Fp curve = new ECCurve.Fp(((ECFieldFp)field).getP(), a, b);
+
+ if (customCurves.containsKey(curve))
+ {
+ return (ECCurve)customCurves.get(curve);
+ }
+
+ return curve;
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java
index 442b340..06a93e5 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java
@@ -17,6 +17,7 @@ import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962NamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
@@ -247,11 +248,15 @@ public class ECUtil
public static X9ECParameters getNamedCurveByOid(
ASN1ObjectIdentifier oid)
{
- X9ECParameters params = X962NamedCurves.getByOID(oid);
-
+ X9ECParameters params = CustomNamedCurves.getByOID(oid);
+
if (params == null)
{
- params = SECNamedCurves.getByOID(oid);
+ params = X962NamedCurves.getByOID(oid);
+ if (params == null)
+ {
+ params = SECNamedCurves.getByOID(oid);
+ }
if (params == null)
{
params = NISTNamedCurves.getByOID(oid);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/PKCS12BagAttributeCarrierImpl.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/PKCS12BagAttributeCarrierImpl.java
index 532554d..3e328da 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/PKCS12BagAttributeCarrierImpl.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/PKCS12BagAttributeCarrierImpl.java
@@ -12,7 +12,6 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
public class PKCS12BagAttributeCarrierImpl
@@ -90,7 +89,7 @@ public class PKCS12BagAttributeCarrierImpl
while (e.hasMoreElements())
{
- DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
aOut.writeObject(oid);
aOut.writeObject((ASN1Encodable)pkcs12Attributes.get(oid));
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil.java
index 8699c3c..e4aaf30 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil.java
@@ -33,11 +33,6 @@ public class PEMUtil
{
while (((c = in.read()) != '\r') && c != '\n' && (c >= 0))
{
- if (c == '\r')
- {
- continue;
- }
-
l.append((char)c);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
index 4ca9e89..a6959ba 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
@@ -11,9 +11,9 @@ import java.security.spec.PSSParameterSpec;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Null;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
// BEGIN android-removed
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
// END android-removed
@@ -80,7 +80,7 @@ class X509SignatureUtil
{
ASN1Sequence ecDsaParams = ASN1Sequence.getInstance(params);
- return getDigestAlgName((DERObjectIdentifier)ecDsaParams.getObjectAt(0)) + "withECDSA";
+ return getDigestAlgName((ASN1ObjectIdentifier)ecDsaParams.getObjectAt(0)) + "withECDSA";
}
}
@@ -92,7 +92,7 @@ class X509SignatureUtil
* representations rather the the algorithm identifier (if possible).
*/
private static String getDigestAlgName(
- DERObjectIdentifier digestAlgOID)
+ ASN1ObjectIdentifier digestAlgOID)
{
if (PKCSObjectIdentifiers.md5.equals(digestAlgOID))
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java
index 05bfa1c..123ff7d 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java
@@ -15,7 +15,7 @@ public interface ConfigurableProvider
static final String THREAD_LOCAL_EC_IMPLICITLY_CA = "threadLocalEcImplicitlyCa";
/**
- * Elliptic Curve CA parameters - thread local version
+ * Elliptic Curve CA parameters - VM wide version
*/
static final String EC_IMPLICITLY_CA = "ecImplicitlyCa";
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
index 24dac19..f986734 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
@@ -86,6 +86,8 @@ import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.jcajce.provider.config.PKCS12StoreParameter;
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
// BEGIN android-removed
@@ -213,7 +215,7 @@ public class PKCS12KeyStoreSpi
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
(ASN1Sequence)ASN1Primitive.fromByteArray(pubKey.getEncoded()));
- return new SubjectKeyIdentifier(info);
+ return new SubjectKeyIdentifier(getDigest(info));
}
catch (Exception e)
{
@@ -221,6 +223,17 @@ public class PKCS12KeyStoreSpi
}
}
+ private static byte[] getDigest(SubjectPublicKeyInfo spki)
+ {
+ Digest digest = new SHA1Digest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ byte[] bytes = spki.getPublicKeyData().getBytes();
+ digest.update(bytes, 0, bytes.length);
+ digest.doFinal(resBuf, 0);
+ return resBuf;
+ }
+
public void setRandom(
SecureRandom rand)
{
@@ -667,6 +680,7 @@ public class PKCS12KeyStoreSpi
throws IOException
{
ASN1ObjectIdentifier algorithm = algId.getAlgorithm();
+ int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds))
{
@@ -684,7 +698,7 @@ public class PKCS12KeyStoreSpi
key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
Cipher cipher = Cipher.getInstance(algorithm.getId(), bcProvider);
- int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
+
cipher.init(mode, key, defParams);
return cipher.doFinal(data);
}
@@ -697,7 +711,7 @@ public class PKCS12KeyStoreSpi
{
try
{
- Cipher cipher = createCipher(Cipher.DECRYPT_MODE, password, algId);
+ Cipher cipher = createCipher(mode, password, algId);
return cipher.doFinal(data);
}
@@ -1027,9 +1041,9 @@ public class PKCS12KeyStoreSpi
Enumeration e = b.getBagAttributes().getObjects();
while (e.hasMoreElements())
{
- ASN1Sequence sq = (ASN1Sequence)e.nextElement();
- ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
- ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1);
+ ASN1Sequence sq = ASN1Sequence.getInstance(e.nextElement());
+ ASN1ObjectIdentifier aOid = ASN1ObjectIdentifier.getInstance(sq.getObjectAt(0));
+ ASN1Set attrSet = ASN1Set.getInstance(sq.getObjectAt(1));
ASN1Primitive attr = null;
if (attrSet.size() > 0)
@@ -1050,16 +1064,16 @@ public class PKCS12KeyStoreSpi
{
bagAttr.setBagAttribute(aOid, attr);
}
- }
- if (aOid.equals(pkcs_9_at_friendlyName))
- {
- alias = ((DERBMPString)attr).getString();
- keys.put(alias, privKey);
- }
- else if (aOid.equals(pkcs_9_at_localKeyId))
- {
- localId = (ASN1OctetString)attr;
+ if (aOid.equals(pkcs_9_at_friendlyName))
+ {
+ alias = ((DERBMPString)attr).getString();
+ keys.put(alias, privKey);
+ }
+ else if (aOid.equals(pkcs_9_at_localKeyId))
+ {
+ localId = (ASN1OctetString)attr;
+ }
}
}
@@ -1127,38 +1141,43 @@ public class PKCS12KeyStoreSpi
Enumeration e = b.getBagAttributes().getObjects();
while (e.hasMoreElements())
{
- ASN1Sequence sq = (ASN1Sequence)e.nextElement();
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)sq.getObjectAt(0);
- ASN1Primitive attr = (ASN1Primitive)((ASN1Set)sq.getObjectAt(1)).getObjectAt(0);
- PKCS12BagAttributeCarrier bagAttr = null;
+ ASN1Sequence sq = ASN1Sequence.getInstance(e.nextElement());
+ ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(sq.getObjectAt(0));
+ ASN1Set attrSet = ASN1Set.getInstance(sq.getObjectAt(1));
- if (cert instanceof PKCS12BagAttributeCarrier)
+ if (attrSet.size() > 0) // sometimes this is empty!
{
- bagAttr = (PKCS12BagAttributeCarrier)cert;
+ ASN1Primitive attr = (ASN1Primitive)attrSet.getObjectAt(0);
+ PKCS12BagAttributeCarrier bagAttr = null;
- ASN1Encodable existing = bagAttr.getBagAttribute(oid);
- if (existing != null)
+ if (cert instanceof PKCS12BagAttributeCarrier)
{
- // OK, but the value has to be the same
- if (!existing.toASN1Primitive().equals(attr))
+ bagAttr = (PKCS12BagAttributeCarrier)cert;
+
+ ASN1Encodable existing = bagAttr.getBagAttribute(oid);
+ if (existing != null)
+ {
+ // OK, but the value has to be the same
+ if (!existing.toASN1Primitive().equals(attr))
+ {
+ throw new IOException(
+ "attempt to add existing attribute with different value");
+ }
+ }
+ else
{
- throw new IOException(
- "attempt to add existing attribute with different value");
+ bagAttr.setBagAttribute(oid, attr);
}
}
- else
+
+ if (oid.equals(pkcs_9_at_friendlyName))
{
- bagAttr.setBagAttribute(oid, attr);
+ alias = ((DERBMPString)attr).getString();
+ }
+ else if (oid.equals(pkcs_9_at_localKeyId))
+ {
+ localId = (ASN1OctetString)attr;
}
- }
-
- if (oid.equals(pkcs_9_at_friendlyName))
- {
- alias = ((DERBMPString)attr).getString();
- }
- else if (oid.equals(pkcs_9_at_localKeyId))
- {
- localId = (ASN1OctetString)attr;
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java
index 500bf2d..55f5ace 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java
@@ -25,6 +25,7 @@ import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.engines.AESWrapEngine;
// BEGIN android-removed
// import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
+// import org.bouncycastle.crypto.engines.RFC5649WrapEngine;
// import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
// import org.bouncycastle.crypto.macs.CMac;
// import org.bouncycastle.crypto.macs.GMac;
@@ -157,7 +158,7 @@ public final class AES
super(new AESWrapEngine());
}
}
-
+
// BEGIN android-removed
// public static class RFC3211Wrap
// extends BaseWrapCipher
@@ -167,9 +168,17 @@ public final class AES
// super(new RFC3211WrapEngine(new AESFastEngine()), 16);
// }
// }
+ //
+ // public static class RFC5649Wrap
+ // extends BaseWrapCipher
+ // {
+ // public RFC5649Wrap()
+ // {
+ // super(new RFC5649WrapEngine(new AESFastEngine()));
+ // }
+ // }
// END android-removed
-
/**
* PBEWithAES-CBC
*/
@@ -453,9 +462,9 @@ public final class AES
{
try
{
- Constructor constructor = gcmSpecClass.getConstructor(new Class[] { byte[].class, Integer.class });
+ Constructor constructor = gcmSpecClass.getConstructor(new Class[] { Integer.TYPE, byte[].class });
- return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { gcmParams.getNonce(), Integers.valueOf(gcmParams.getIcvLen()) });
+ return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(gcmParams.getIcvLen()), gcmParams.getNonce() });
}
catch (NoSuchMethodException e)
{
@@ -536,8 +545,10 @@ public final class AES
provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_wrap, "AESWRAP");
provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes192_wrap, "AESWRAP");
provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_wrap, "AESWRAP");
+
// BEGIN android-removed
// provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap");
+ // provider.addAlgorithm("Cipher.AESRFC5649WRAP", PREFIX + "$RFC5649Wrap");
// END android-removed
provider.addAlgorithm("Cipher.GCM", PREFIX + "$GCM");
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
index 5b85ef5..faf31b3 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
@@ -1,5 +1,6 @@
package org.bouncycastle.jcajce.provider.symmetric.util;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
@@ -178,11 +179,11 @@ public class BaseBlockCipher
protected byte[] engineGetIV()
{
- // BEGIN android-added
- if (aeadParams != null) {
+ if (aeadParams != null)
+ {
return aeadParams.getNonce();
}
- // END android-added
+
return (ivParam != null) ? ivParam.getIV() : null;
}
@@ -360,7 +361,9 @@ public class BaseBlockCipher
// {
// if (engineProvider != null)
// {
- // // Nonce restricted to max 120 bits over 128 bit block cipher since draft-irtf-cfrg-ocb-03
+ // /*
+ // * RFC 7253 4.2. Nonce is a string of no more than 120 bits
+ // */
// ivLength = 15;
// cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get()));
// }
@@ -849,10 +852,6 @@ public class BaseBlockCipher
{
throw new IllegalBlockSizeException(e.getMessage());
}
- catch (InvalidCipherTextException e)
- {
- throw new BadPaddingException(e.getMessage());
- }
if (len == tmp.length)
{
@@ -893,10 +892,6 @@ public class BaseBlockCipher
{
throw new IllegalBlockSizeException(e.getMessage());
}
- catch (InvalidCipherTextException e)
- {
- throw new BadPaddingException(e.getMessage());
- }
}
private boolean isAEADModeName(
@@ -935,7 +930,8 @@ public class BaseBlockCipher
throws DataLengthException;
public int doFinal(byte[] out, int outOff)
- throws IllegalStateException, InvalidCipherTextException;
+ throws IllegalStateException,
+ BadPaddingException;
}
private static class BufferedGenericBlockCipher
@@ -1004,15 +1000,48 @@ public class BaseBlockCipher
return cipher.processBytes(in, inOff, len, out, outOff);
}
- public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException
+ public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException
{
- return cipher.doFinal(out, outOff);
+ try
+ {
+ return cipher.doFinal(out, outOff);
+ }
+ catch (InvalidCipherTextException e)
+ {
+ throw new BadPaddingException(e.getMessage());
+ }
}
}
private static class AEADGenericBlockCipher
implements GenericBlockCipher
{
+ private static final Constructor aeadBadTagConstructor;
+
+ static {
+ Class aeadBadTagClass = lookup("javax.crypto.AEADBadTagException");
+ if (aeadBadTagClass != null)
+ {
+ aeadBadTagConstructor = findExceptionConstructor(aeadBadTagClass);
+ }
+ else
+ {
+ aeadBadTagConstructor = null;
+ }
+ }
+
+ private static Constructor findExceptionConstructor(Class clazz)
+ {
+ try
+ {
+ return clazz.getConstructor(new Class[]{String.class});
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
private AEADBlockCipher cipher;
AEADGenericBlockCipher(AEADBlockCipher cipher)
@@ -1066,9 +1095,33 @@ public class BaseBlockCipher
return cipher.processBytes(in, inOff, len, out, outOff);
}
- public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException
+ public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException
{
- return cipher.doFinal(out, outOff);
+ try
+ {
+ return cipher.doFinal(out, outOff);
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (aeadBadTagConstructor != null)
+ {
+ BadPaddingException aeadBadTag = null;
+ try
+ {
+ aeadBadTag = (BadPaddingException)aeadBadTagConstructor
+ .newInstance(new Object[]{e.getMessage()});
+ }
+ catch (Exception i)
+ {
+ // Shouldn't happen, but fall through to BadPaddingException
+ }
+ if (aeadBadTag != null)
+ {
+ throw aeadBadTag;
+ }
+ }
+ throw new BadPaddingException(e.getMessage());
+ }
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
index eb045bf..b37a9fe 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
@@ -19,10 +19,8 @@ import javax.crypto.spec.PBEParameterSpec;
// import javax.crypto.spec.RC5ParameterSpec;
// END android-removed
-import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
@@ -61,15 +59,6 @@ public class BaseStreamCipher
this.ivLength = ivLength;
}
- protected BaseStreamCipher(
- BlockCipher engine,
- int ivLength)
- {
- this.ivLength = ivLength;
-
- cipher = new StreamBlockCipher(engine);
- }
-
protected int engineGetBlockSize()
{
return 0;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
index 98e5771..5be73e5 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
@@ -34,6 +34,7 @@ import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.Wrapper;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public abstract class BaseWrapCipher
@@ -168,6 +169,11 @@ public abstract class BaseWrapCipher
param = new ParametersWithIV(param, iv);
}
+ if (random != null)
+ {
+ param = new ParametersWithRandom(param, random);
+ }
+
switch (opmode)
{
case Cipher.WRAP_MODE:
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java
index 214a5eb..09a9bd0 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java
@@ -4,11 +4,23 @@ import javax.crypto.spec.PBEKeySpec;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+/**
+ * Extension of PBEKeySpec which takes into account the PRF algorithm setting available in PKCS#5 PBKDF2.
+ */
public class PBKDF2KeySpec
extends PBEKeySpec
{
private AlgorithmIdentifier prf;
+ /**
+ * Base constructor.
+ *
+ * @param password password to use as the seed of the PBE key generator.
+ * @param salt salt to use in the generator,
+ * @param iterationCount iteration count to use in the generator.
+ * @param keySize size of the key to be generated.
+ * @param prf identifier and parameters for the PRF algorithm to use.
+ */
public PBKDF2KeySpec(char[] password, byte[] salt, int iterationCount, int keySize, AlgorithmIdentifier prf)
{
super(password, salt, iterationCount, keySize);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/DefaultJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java
index 6a7b4e2..43a97f3 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/DefaultJcaJceHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java
@@ -1,4 +1,4 @@
-package org.bouncycastle.jcajce;
+package org.bouncycastle.jcajce.util;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
@@ -17,6 +17,10 @@ import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
+/**
+ * {@link JcaJceHelper} that obtains all algorithms using the default JCA/JCE mechanism (i.e.
+ * without specifying a provider).
+ */
public class DefaultJcaJceHelper
implements JcaJceHelper
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java
index 645b440..f5da335 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java
@@ -1,4 +1,4 @@
-package org.bouncycastle.jcajce;
+package org.bouncycastle.jcajce.util;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
@@ -18,6 +18,9 @@ import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
+/**
+ * Factory interface for instantiating JCA/JCE primitives.
+ */
public interface JcaJceHelper
{
Cipher createCipher(
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceUtils.java
new file mode 100644
index 0000000..a082d89
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceUtils.java
@@ -0,0 +1,130 @@
+package org.bouncycastle.jcajce.util;
+
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1Primitive;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// END android-removed
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+// END android-removed
+
+/**
+ * General JCA/JCE utility methods.
+ */
+public class JcaJceUtils
+{
+ private JcaJceUtils()
+ {
+
+ }
+
+ /**
+ * Extract an ASN.1 encodable from an AlgorithmParameters object.
+ *
+ * @param params the object to get the encoding used to create the return value.
+ * @return an ASN.1 object representing the primitives making up the params parameter.
+ * @throws IOException if an encoding cannot be extracted.
+ */
+ public static ASN1Encodable extractParameters(AlgorithmParameters params)
+ throws IOException
+ {
+ // we try ASN.1 explicitly first just in case and then role back to the default.
+ ASN1Encodable asn1Params;
+ try
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
+ }
+ catch (Exception ex)
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded());
+ }
+
+ return asn1Params;
+ }
+
+ /**
+ * Load an AlgorithmParameters object with the passed in ASN.1 encodable - if possible.
+ *
+ * @param params the AlgorithmParameters object to be initialised.
+ * @param sParams the ASN.1 encodable to initialise params with.
+ * @throws IOException if the parameters cannot be initialised.
+ */
+ public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams)
+ throws IOException
+ {
+ // we try ASN.1 explicitly first just in case and then role back to the default.
+ try
+ {
+ params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1");
+ }
+ catch (Exception ex)
+ {
+ params.init(sParams.toASN1Primitive().getEncoded());
+ }
+ }
+
+ /**
+ * Attempt to find a standard JCA name for the digest represented by the past in OID.
+ *
+ * @param digestAlgOID the OID of the digest algorithm of interest.
+ * @return a string representing the standard name - the OID as a string if none available.
+ */
+ public static String getDigestAlgName(
+ ASN1ObjectIdentifier digestAlgOID)
+ {
+ if (PKCSObjectIdentifiers.md5.equals(digestAlgOID))
+ {
+ return "MD5";
+ }
+ else if (OIWObjectIdentifiers.idSHA1.equals(digestAlgOID))
+ {
+ return "SHA1";
+ }
+ else if (NISTObjectIdentifiers.id_sha224.equals(digestAlgOID))
+ {
+ return "SHA224";
+ }
+ else if (NISTObjectIdentifiers.id_sha256.equals(digestAlgOID))
+ {
+ return "SHA256";
+ }
+ else if (NISTObjectIdentifiers.id_sha384.equals(digestAlgOID))
+ {
+ return "SHA384";
+ }
+ else if (NISTObjectIdentifiers.id_sha512.equals(digestAlgOID))
+ {
+ return "SHA512";
+ }
+ // BEGIN android-removed
+ // else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID))
+ // {
+ // return "RIPEMD128";
+ // }
+ // else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID))
+ // {
+ // return "RIPEMD160";
+ // }
+ // else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID))
+ // {
+ // return "RIPEMD256";
+ // }
+ // else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID))
+ // {
+ // return "GOST3411";
+ // }
+ // END android-removed
+ else
+ {
+ return digestAlgOID.getId();
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/NamedJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java
index 03f1006..ebbfacc 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/NamedJcaJceHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java
@@ -1,4 +1,4 @@
-package org.bouncycastle.jcajce;
+package org.bouncycastle.jcajce.util;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
@@ -18,6 +18,9 @@ import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
+/**
+ * {@link JcaJceHelper} that obtains all algorithms using a specific named provider.
+ */
public class NamedJcaJceHelper
implements JcaJceHelper
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/ProviderJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java
index 90a8f68..fad1048 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/ProviderJcaJceHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java
@@ -1,4 +1,4 @@
-package org.bouncycastle.jcajce;
+package org.bouncycastle.jcajce.util;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
@@ -18,6 +18,9 @@ import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
+/**
+ * {@link JcaJceHelper} that obtains all algorithms from a specific {@link Provider} instance.
+ */
public class ProviderJcaJceHelper
implements JcaJceHelper
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java b/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java
index 941f476..5ad207a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java
@@ -21,19 +21,35 @@ public class ECNamedCurveTable
public static ECNamedCurveParameterSpec getParameterSpec(
String name)
{
- X9ECParameters ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByName(name);
+ X9ECParameters ecP = org.bouncycastle.crypto.ec.CustomNamedCurves.getByName(name);
if (ecP == null)
{
try
{
- ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(name));
+ ecP = org.bouncycastle.crypto.ec.CustomNamedCurves.getByOID(new ASN1ObjectIdentifier(name));
}
catch (IllegalArgumentException e)
{
// ignore - not an oid
}
+
+ if (ecP == null)
+ {
+ ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByName(name);
+ if (ecP == null)
+ {
+ try
+ {
+ ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(name));
+ }
+ catch (IllegalArgumentException e)
+ {
+ // ignore - not an oid
+ }
+ }
+ }
}
-
+
if (ecP == null)
{
return null;
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java b/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java
index 4c34850..3670695 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java
@@ -24,12 +24,12 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
// BEGIN android-removed
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
// END android-removed
@@ -87,14 +87,14 @@ public class PKCS10CertificationRequest
{
// BEGIN android-removed
// Dropping MD2
- // algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
- // algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
+ // algorithms.put("MD2WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"));
+ // algorithms.put("MD2WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"));
// END android-removed
- algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
- algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
- algorithms.put("RSAWITHMD5", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
- algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
- algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
+ algorithms.put("MD5WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"));
+ algorithms.put("MD5WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"));
+ algorithms.put("RSAWITHMD5", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"));
+ algorithms.put("SHA1WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"));
+ algorithms.put("SHA1WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"));
algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption);
algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption);
algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption);
@@ -108,7 +108,7 @@ public class PKCS10CertificationRequest
algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
- algorithms.put("RSAWITHSHA1", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
+ algorithms.put("RSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"));
// BEGIN android-removed
// algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
// algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
@@ -117,8 +117,8 @@ public class PKCS10CertificationRequest
// algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
// algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
// END android-removed
- algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3"));
- algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3"));
+ algorithms.put("SHA1WITHDSA", new ASN1ObjectIdentifier("1.2.840.10040.4.3"));
+ algorithms.put("DSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.10040.4.3"));
algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224);
algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256);
algorithms.put("SHA384WITHDSA", NISTObjectIdentifiers.dsa_with_sha384);
@@ -140,7 +140,7 @@ public class PKCS10CertificationRequest
//
// reverse mappings
//
- oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA");
+ oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA");
oids.put(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224WITHRSA");
oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA");
oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA");
@@ -150,12 +150,11 @@ public class PKCS10CertificationRequest
// oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, "GOST3411WITHECGOST3410");
// END android-removed
- oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
+ oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
// BEGIN android-removed
- // Dropping MD2
- // oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA");
+ // oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA");
// END android-removed
- oids.put(new DERObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA");
+ oids.put(new ASN1ObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA");
oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1WITHECDSA");
oids.put(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224WITHECDSA");
oids.put(X9ObjectIdentifiers.ecdsa_with_SHA256, "SHA256WITHECDSA");
@@ -324,13 +323,13 @@ public class PKCS10CertificationRequest
InvalidKeyException, SignatureException
{
String algorithmName = Strings.toUpperCase(signatureAlgorithm);
- DERObjectIdentifier sigOID = (DERObjectIdentifier)algorithms.get(algorithmName);
+ ASN1ObjectIdentifier sigOID = (ASN1ObjectIdentifier)algorithms.get(algorithmName);
if (sigOID == null)
{
try
{
- sigOID = new DERObjectIdentifier(algorithmName);
+ sigOID = new ASN1ObjectIdentifier(algorithmName);
}
catch (Exception e)
{
@@ -608,7 +607,7 @@ public class PKCS10CertificationRequest
}
private static String getDigestAlgName(
- DERObjectIdentifier digestAlgOID)
+ ASN1ObjectIdentifier digestAlgOID)
{
if (PKCSObjectIdentifiers.md5.equals(digestAlgOID))
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java b/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java
index ddd38e8..b1daa98 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java
@@ -129,7 +129,7 @@ public class X509Principal
* Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
* some such, converting it into an ordered set of name attributes. lookUp
* should provide a table of lookups, indexed by lowercase only strings and
- * yielding a DERObjectIdentifier, other than that OID. and numeric oids
+ * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids
* will be processed automatically.
* <p>
* If reverse is true, create the encoded version of the sequence starting
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
index ab6c42f..145186a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
@@ -44,7 +44,7 @@ import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
public final class BouncyCastleProvider extends Provider
implements ConfigurableProvider
{
- private static String info = "BouncyCastle Security Provider v1.50";
+ private static String info = "BouncyCastle Security Provider v1.51";
public static final String PROVIDER_NAME = "BC";
@@ -139,7 +139,7 @@ public final class BouncyCastleProvider extends Provider
*/
public BouncyCastleProvider()
{
- super(PROVIDER_NAME, 1.50, info);
+ super(PROVIDER_NAME, 1.51, info);
AccessController.doPrivileged(new PrivilegedAction()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
index eb663dc..b4338f6 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
@@ -38,16 +38,16 @@ import java.util.Set;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Enumerated;
+import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1OutputStream;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREnumerated;
-import org.bouncycastle.asn1.DERGeneralizedTime;
import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.isismtt.ISISMTTObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
@@ -461,7 +461,7 @@ public class CertPathValidatorUtilities
protected static boolean processCertD1i(
int index,
List[] policyNodes,
- DERObjectIdentifier pOid,
+ ASN1ObjectIdentifier pOid,
Set pq)
{
List policyNodeVec = policyNodes[index - 1];
@@ -496,7 +496,7 @@ public class CertPathValidatorUtilities
protected static void processCertD1ii(
int index,
List[] policyNodes,
- DERObjectIdentifier _poid,
+ ASN1ObjectIdentifier _poid,
Set _pq)
{
List policyNodeVec = policyNodes[index - 1];
@@ -1029,12 +1029,12 @@ public class CertPathValidatorUtilities
}
}
- DEREnumerated reasonCode = null;
+ ASN1Enumerated reasonCode = null;
if (crl_entry.hasExtensions())
{
try
{
- reasonCode = DEREnumerated
+ reasonCode = ASN1Enumerated
.getInstance(CertPathValidatorUtilities
.getExtensionValue(crl_entry,
X509Extension.reasonCode.getId()));
@@ -1255,13 +1255,13 @@ public class CertPathValidatorUtilities
{
if (index - 1 == 0)
{
- DERGeneralizedTime dateOfCertgen = null;
+ ASN1GeneralizedTime dateOfCertgen = null;
try
{
byte[] extBytes = ((X509Certificate)certPath.getCertificates().get(index - 1)).getExtensionValue(ISISMTTObjectIdentifiers.id_isismtt_at_dateOfCertGen.getId());
if (extBytes != null)
{
- dateOfCertgen = DERGeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes));
+ dateOfCertgen = ASN1GeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes));
}
}
catch (IOException e)
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPrivateKey.java
index b38f60b..a30b2df 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPrivateKey.java
@@ -12,10 +12,9 @@ import javax.crypto.spec.DHPrivateKeySpec;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
@@ -61,8 +60,8 @@ public class JCEDHPrivateKey
throws IOException
{
ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithmId().getParameters());
- DERInteger derX = DERInteger.getInstance(info.parsePrivateKey());
- DERObjectIdentifier id = info.getAlgorithmId().getAlgorithm();
+ ASN1Integer derX = ASN1Integer.getInstance(info.parsePrivateKey());
+ ASN1ObjectIdentifier id = info.getAlgorithmId().getAlgorithm();
this.info = info;
this.x = derX.getValue();
@@ -129,7 +128,7 @@ public class JCEDHPrivateKey
return info.getEncoded(ASN1Encoding.DER);
}
- PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new DERInteger(getX()));
+ PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new ASN1Integer(getX()));
return info.getEncoded(ASN1Encoding.DER);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPublicKey.java
index 6ff1e08..3e6a09a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPublicKey.java
@@ -9,9 +9,9 @@ import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPublicKeySpec;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
@@ -64,10 +64,10 @@ public class JCEDHPublicKey
{
this.info = info;
- DERInteger derY;
+ ASN1Integer derY;
try
{
- derY = (DERInteger)info.parsePublicKey();
+ derY = (ASN1Integer)info.parsePublicKey();
}
catch (IOException e)
{
@@ -77,7 +77,7 @@ public class JCEDHPublicKey
this.y = derY.getValue();
ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithmId().getParameters());
- DERObjectIdentifier id = info.getAlgorithmId().getAlgorithm();
+ ASN1ObjectIdentifier id = info.getAlgorithmId().getAlgorithm();
// we need the PKCS check to handle older keys marked with the X9 oid.
if (id.equals(PKCSObjectIdentifiers.dhKeyAgreement) || isPKCSParam(seq))
@@ -122,7 +122,7 @@ public class JCEDHPublicKey
return KeyUtil.getEncodedSubjectPublicKeyInfo(info);
}
- return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new DERInteger(y));
+ return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new ASN1Integer(y));
}
public DHParameterSpec getParams()
@@ -147,8 +147,8 @@ public class JCEDHPublicKey
return false;
}
- DERInteger l = DERInteger.getInstance(seq.getObjectAt(2));
- DERInteger p = DERInteger.getInstance(seq.getObjectAt(0));
+ ASN1Integer l = ASN1Integer.getInstance(seq.getObjectAt(2));
+ ASN1Integer p = ASN1Integer.getInstance(seq.getObjectAt(0));
if (l.getValue().compareTo(BigInteger.valueOf(p.getValue().bitLength())) > 0)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
index 53f4ec7..f5af73a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
@@ -13,13 +13,12 @@ import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
// BEGIN android-removed
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
@@ -254,9 +253,9 @@ public class JCEECPrivateKey
}
ASN1Encodable privKey = info.parsePrivateKey();
- if (privKey instanceof DERInteger)
+ if (privKey instanceof ASN1Integer)
{
- DERInteger derD = DERInteger.getInstance(privKey);
+ ASN1Integer derD = ASN1Integer.getInstance(privKey);
this.d = derD.getValue();
}
@@ -296,10 +295,10 @@ public class JCEECPrivateKey
if (ecSpec instanceof ECNamedCurveSpec)
{
- DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
+ ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
if (curveOid == null) // guess it's the OID
{
- curveOid = new DERObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
+ curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
}
params = new X962Parameters(curveOid);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
index 6fff8a6..10dfb48 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
@@ -44,6 +44,8 @@ import org.bouncycastle.jce.interfaces.ECPointEncoder;
// END android-removed
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.custom.sec.SecP256K1Point;
+import org.bouncycastle.math.ec.custom.sec.SecP256R1Point;
public class JCEECPublicKey
implements ECPublicKey, org.bouncycastle.jce.interfaces.ECPublicKey, ECPointEncoder
@@ -452,14 +454,7 @@ public class JCEECPublicKey
{
if (ecSpec == null)
{
- if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp)
- {
- return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord());
- }
- else
- {
- return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord());
- }
+ return q.getDetachedPoint();
}
return q;
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java
index 7471b0b..c5b6292 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java
@@ -30,18 +30,13 @@ import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.StreamCipher;
// BEGIN android-removed
// import org.bouncycastle.crypto.engines.BlowfishEngine;
// import org.bouncycastle.crypto.engines.DESEngine;
// import org.bouncycastle.crypto.engines.DESedeEngine;
-// END android-removed
-import org.bouncycastle.crypto.engines.RC4Engine;
-// BEGIN android-removed
// import org.bouncycastle.crypto.engines.SkipjackEngine;
// import org.bouncycastle.crypto.engines.TwofishEngine;
// END android-removed
@@ -86,15 +81,6 @@ public class JCEStreamCipher
cipher = engine;
this.ivLength = ivLength;
}
-
- protected JCEStreamCipher(
- BlockCipher engine,
- int ivLength)
- {
- this.ivLength = ivLength;
-
- cipher = new StreamBlockCipher(engine);
- }
protected int engineGetBlockSize()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPrivateKey.java
index 50a714c..3bd6d30 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPrivateKey.java
@@ -14,8 +14,6 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
@@ -57,7 +55,7 @@ public class JDKDSAPrivateKey
throws IOException
{
DSAParameter params = DSAParameter.getInstance(info.getPrivateKeyAlgorithm().getParameters());
- DERInteger derX = ASN1Integer.getInstance(info.parsePrivateKey());
+ ASN1Integer derX = ASN1Integer.getInstance(info.parsePrivateKey());
this.x = derX.getValue();
this.dsaSpec = new DSAParameterSpec(params.getP(), params.getQ(), params.getG());
@@ -95,7 +93,7 @@ public class JDKDSAPrivateKey
{
try
{
- PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG())), new DERInteger(getX()));
+ PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG())), new ASN1Integer(getX()));
return info.getEncoded(ASN1Encoding.DER);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPublicKey.java
index 85a39a4..80bbf3c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JDKDSAPublicKey.java
@@ -11,8 +11,7 @@ import java.security.spec.DSAPublicKeySpec;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
@@ -61,11 +60,11 @@ public class JDKDSAPublicKey
SubjectPublicKeyInfo info)
{
- DERInteger derY;
+ ASN1Integer derY;
try
{
- derY = (DERInteger)info.parsePublicKey();
+ derY = (ASN1Integer)info.parsePublicKey();
}
catch (IOException e)
{
@@ -103,10 +102,10 @@ public class JDKDSAPublicKey
{
if (dsaSpec == null)
{
- return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new DERInteger(y)).getEncoded(ASN1Encoding.DER);
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(y)).getEncoded(ASN1Encoding.DER);
}
- return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG())), new DERInteger(y)).getEncoded(ASN1Encoding.DER);
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG())), new ASN1Integer(y)).getEncoded(ASN1Encoding.DER);
}
catch (IOException e)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
index af764f3..8ed42a1 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
@@ -24,7 +24,7 @@ import java.util.Set;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.jce.exception.ExtCertPathValidatorException;
import org.bouncycastle.x509.ExtendedPKIXParameters;
@@ -240,7 +240,7 @@ public class PKIXCertPathValidatorSpi
throw new ExtCertPathValidatorException(
"Algorithm identifier of public key of trust anchor could not be read.", e, certPath, -1);
}
- DERObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.getObjectId();
+ ASN1ObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.getAlgorithm();
ASN1Encodable workingPublicKeyParameters = workingAlgId.getParameters();
//
@@ -402,7 +402,7 @@ public class PKIXCertPathValidatorSpi
workingAlgId = CertPathValidatorUtilities.getAlgorithmIdentifier(workingPublicKey);
// (f)
- workingPublicKeyAlgorithm = workingAlgId.getObjectId();
+ workingPublicKeyAlgorithm = workingAlgId.getAlgorithm();
// (e)
workingPublicKeyParameters = workingAlgId.getParameters();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java
index 769edb8..881ceeb 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java
@@ -14,6 +14,7 @@ import java.security.cert.PKIXCertPathChecker;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.security.cert.X509Extension;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -24,6 +25,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TimeZone;
import java.util.Vector;
import javax.security.auth.x500.X500Principal;
@@ -31,11 +33,11 @@ import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.CRLDistPoint;
@@ -891,8 +893,8 @@ public class RFC3280CertPathUtilities
for (int j = 0; j < mappings.size(); j++)
{
ASN1Sequence mapping = (ASN1Sequence)mappings.getObjectAt(j);
- String id_p = ((DERObjectIdentifier)mapping.getObjectAt(0)).getId();
- String sd_p = ((DERObjectIdentifier)mapping.getObjectAt(1)).getId();
+ String id_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(0)).getId();
+ String sd_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(1)).getId();
Set tmp;
if (!m_idp.containsKey(id_p))
@@ -1070,14 +1072,14 @@ public class RFC3280CertPathUtilities
for (int j = 0; j < mappings.size(); j++)
{
- DERObjectIdentifier issuerDomainPolicy = null;
- DERObjectIdentifier subjectDomainPolicy = null;
+ ASN1ObjectIdentifier issuerDomainPolicy = null;
+ ASN1ObjectIdentifier subjectDomainPolicy = null;
try
{
ASN1Sequence mapping = DERSequence.getInstance(mappings.getObjectAt(j));
- issuerDomainPolicy = DERObjectIdentifier.getInstance(mapping.getObjectAt(0));
- subjectDomainPolicy = DERObjectIdentifier.getInstance(mapping.getObjectAt(1));
+ issuerDomainPolicy = ASN1ObjectIdentifier.getInstance(mapping.getObjectAt(0));
+ subjectDomainPolicy = ASN1ObjectIdentifier.getInstance(mapping.getObjectAt(1));
}
catch (Exception e)
{
@@ -1284,7 +1286,7 @@ public class RFC3280CertPathUtilities
while (e.hasMoreElements())
{
PolicyInformation pInfo = PolicyInformation.getInstance(e.nextElement());
- DERObjectIdentifier pOid = pInfo.getPolicyIdentifier();
+ ASN1ObjectIdentifier pOid = pInfo.getPolicyIdentifier();
pols.add(pOid.getId());
@@ -1363,9 +1365,9 @@ public class RFC3280CertPathUtilities
{
_policy = (String)_tmp;
}
- else if (_tmp instanceof DERObjectIdentifier)
+ else if (_tmp instanceof ASN1ObjectIdentifier)
{
- _policy = ((DERObjectIdentifier)_tmp).getId();
+ _policy = ((ASN1ObjectIdentifier)_tmp).getId();
}
else
{
@@ -1565,7 +1567,7 @@ public class RFC3280CertPathUtilities
ASN1TaggedObject constraint = ASN1TaggedObject.getInstance(policyConstraints.nextElement());
if (constraint.getTagNo() == 0)
{
- tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue();
+ tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue();
if (tmpInt < explicitPolicy)
{
return tmpInt;
@@ -1619,7 +1621,7 @@ public class RFC3280CertPathUtilities
ASN1TaggedObject constraint = ASN1TaggedObject.getInstance(policyConstraints.nextElement());
if (constraint.getTagNo() == 1)
{
- tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue();
+ tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue();
if (tmpInt < policyMapping)
{
return tmpInt;
@@ -2004,7 +2006,9 @@ public class RFC3280CertPathUtilities
}
if (certStatus.getCertStatus() != CertStatus.UNREVOKED)
{
- String message = "Certificate revocation after " + certStatus.getRevocationDate();
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
+ df.setTimeZone(TimeZone.getTimeZone("UTC"));
+ String message = "Certificate revocation after " + df.format(certStatus.getRevocationDate());
message += ", reason: " + crlReasons[certStatus.getCertStatus()];
throw new AnnotatedException(message);
}
@@ -2029,10 +2033,10 @@ public class RFC3280CertPathUtilities
//
// (j)
//
- DERInteger iap = null;
+ ASN1Integer iap = null;
try
{
- iap = DERInteger.getInstance(CertPathValidatorUtilities.getExtensionValue(cert,
+ iap = ASN1Integer.getInstance(CertPathValidatorUtilities.getExtensionValue(cert,
RFC3280CertPathUtilities.INHIBIT_ANY_POLICY));
}
catch (Exception e)
@@ -2335,7 +2339,7 @@ public class RFC3280CertPathUtilities
case 0:
try
{
- tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue();
+ tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue();
}
catch (Exception e)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509SignatureUtil.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509SignatureUtil.java
index b8b0097..b12b1df 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509SignatureUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509SignatureUtil.java
@@ -11,9 +11,9 @@ import java.security.spec.PSSParameterSpec;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Null;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
// BEGIN android-removed
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
// END android-removed
@@ -69,22 +69,22 @@ class X509SignatureUtil
if (params != null && !derNull.equals(params))
{
// BEGIN android-removed
- // if (sigAlgId.getObjectId().equals(PKCSObjectIdentifiers.id_RSASSA_PSS))
+ // if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS))
// {
// RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params);
- //
- // return getDigestAlgName(rsaParams.getHashAlgorithm().getObjectId()) + "withRSAandMGF1";
+ //
+ // return getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "withRSAandMGF1";
// }
// END android-removed
- if (sigAlgId.getObjectId().equals(X9ObjectIdentifiers.ecdsa_with_SHA2))
+ if (sigAlgId.getAlgorithm().equals(X9ObjectIdentifiers.ecdsa_with_SHA2))
{
ASN1Sequence ecDsaParams = ASN1Sequence.getInstance(params);
- return getDigestAlgName((DERObjectIdentifier)ecDsaParams.getObjectAt(0)) + "withECDSA";
+ return getDigestAlgName(ASN1ObjectIdentifier.getInstance(ecDsaParams.getObjectAt(0))) + "withECDSA";
}
}
- return sigAlgId.getObjectId().getId();
+ return sigAlgId.getAlgorithm().getId();
}
/**
@@ -92,7 +92,7 @@ class X509SignatureUtil
* representations rather the the algorithm identifier (if possible).
*/
private static String getDigestAlgName(
- DERObjectIdentifier digestAlgOID)
+ ASN1ObjectIdentifier digestAlgOID)
{
if (PKCSObjectIdentifiers.md5.equals(digestAlgOID))
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java
index 47416a2..4e749a5 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java
@@ -7,9 +7,9 @@ import org.bouncycastle.math.ec.ECPoint;
/**
* specification signifying that the curve parameters can also be
- * refered to by name.
+ * referred to by name.
* <p>
- * If you are using JDK 1.5 you should be looking at ECNamedCurveSpec.
+ * If you are using JDK 1.5 you should be looking at {@link ECNamedCurveSpec}.
*/
public class ECNamedCurveParameterSpec
extends ECParameterSpec
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
index b3d239e..c1b5ccc 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
@@ -6,6 +6,7 @@ import java.security.spec.ECFieldFp;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
+import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
/**
@@ -21,9 +22,9 @@ public class ECNamedCurveSpec
ECCurve curve,
byte[] seed)
{
- if (curve instanceof ECCurve.Fp)
+ if (ECAlgorithms.isFpCurve(curve))
{
- return new EllipticCurve(new ECFieldFp(((ECCurve.Fp)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), seed);
+ return new EllipticCurve(new ECFieldFp(curve.getField().getCharacteristic()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), seed);
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
index 69ab797..d1f35c5 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
@@ -13,7 +13,13 @@ public abstract class AbstractECMultiplier implements ECMultiplier
}
ECPoint positive = multiplyPositive(p, k.abs());
- return sign > 0 ? positive : positive.negate();
+ ECPoint result = sign > 0 ? positive : positive.negate();
+
+ /*
+ * Although the various multipliers ought not to produce invalid output under normal
+ * circumstances, a final check here is advised to guard against fault attacks.
+ */
+ return ECAlgorithms.validatePoint(result);
}
protected abstract ECPoint multiplyPositive(ECPoint p, BigInteger k);
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
index d640b5f..3b334d2 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
@@ -2,8 +2,62 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
+import org.bouncycastle.math.ec.endo.ECEndomorphism;
+import org.bouncycastle.math.ec.endo.GLVEndomorphism;
+import org.bouncycastle.math.field.FiniteField;
+import org.bouncycastle.math.field.PolynomialExtensionField;
+
public class ECAlgorithms
{
+ public static boolean isF2mCurve(ECCurve c)
+ {
+ FiniteField field = c.getField();
+ return field.getDimension() > 1 && field.getCharacteristic().equals(ECConstants.TWO)
+ && field instanceof PolynomialExtensionField;
+ }
+
+ public static boolean isFpCurve(ECCurve c)
+ {
+ return c.getField().getDimension() == 1;
+ }
+
+ public static ECPoint sumOfMultiplies(ECPoint[] ps, BigInteger[] ks)
+ {
+ if (ps == null || ks == null || ps.length != ks.length || ps.length < 1)
+ {
+ throw new IllegalArgumentException("point and scalar arrays should be non-null, and of equal, non-zero, length");
+ }
+
+ int count = ps.length;
+ switch (count)
+ {
+ case 1:
+ return ps[0].multiply(ks[0]);
+ case 2:
+ return sumOfTwoMultiplies(ps[0], ks[0], ps[1], ks[1]);
+ default:
+ break;
+ }
+
+ ECPoint p = ps[0];
+ ECCurve c = p.getCurve();
+
+ ECPoint[] imported = new ECPoint[count];
+ imported[0] = p;
+ for (int i = 1; i < count; ++i)
+ {
+ imported[i] = importPoint(c, ps[i]);
+ }
+
+ ECEndomorphism endomorphism = c.getEndomorphism();
+ if (endomorphism instanceof GLVEndomorphism)
+ {
+ return validatePoint(implSumOfMultipliesGLV(imported, ks, (GLVEndomorphism)endomorphism));
+ }
+
+ return validatePoint(implSumOfMultiplies(imported, ks));
+ }
+
public static ECPoint sumOfTwoMultiplies(ECPoint P, BigInteger a,
ECPoint Q, BigInteger b)
{
@@ -16,11 +70,18 @@ public class ECAlgorithms
ECCurve.F2m f2mCurve = (ECCurve.F2m)cp;
if (f2mCurve.isKoblitz())
{
- return P.multiply(a).add(Q.multiply(b));
+ return validatePoint(P.multiply(a).add(Q.multiply(b)));
}
}
- return implShamirsTrick(P, a, Q, b);
+ ECEndomorphism endomorphism = cp.getEndomorphism();
+ if (endomorphism instanceof GLVEndomorphism)
+ {
+ return validatePoint(
+ implSumOfMultipliesGLV(new ECPoint[]{ P, Q }, new BigInteger[]{ a, b }, (GLVEndomorphism)endomorphism));
+ }
+
+ return validatePoint(implShamirsTrickWNaf(P, a, Q, b));
}
/*
@@ -48,7 +109,7 @@ public class ECAlgorithms
ECCurve cp = P.getCurve();
Q = importPoint(cp, Q);
- return implShamirsTrick(P, k, Q, l);
+ return validatePoint(implShamirsTrickJsf(P, k, Q, l));
}
public static ECPoint importPoint(ECCurve c, ECPoint p)
@@ -61,7 +122,7 @@ public class ECAlgorithms
return c.importPoint(p);
}
- static void implMontgomeryTrick(ECFieldElement[] zs, int off, int len)
+ public static void montgomeryTrick(ECFieldElement[] zs, int off, int len)
{
/*
* Uses the "Montgomery Trick" to invert many field elements, with only a single actual
@@ -92,7 +153,50 @@ public class ECAlgorithms
zs[off] = u;
}
- static ECPoint implShamirsTrick(ECPoint P, BigInteger k,
+ /**
+ * Simple shift-and-add multiplication. Serves as reference implementation
+ * to verify (possibly faster) implementations, and for very small scalars.
+ *
+ * @param p
+ * The point to multiply.
+ * @param k
+ * The multiplier.
+ * @return The result of the point multiplication <code>kP</code>.
+ */
+ public static ECPoint referenceMultiply(ECPoint p, BigInteger k)
+ {
+ BigInteger x = k.abs();
+ ECPoint q = p.getCurve().getInfinity();
+ int t = x.bitLength();
+ if (t > 0)
+ {
+ if (x.testBit(0))
+ {
+ q = p;
+ }
+ for (int i = 1; i < t; i++)
+ {
+ p = p.twice();
+ if (x.testBit(i))
+ {
+ q = q.add(p);
+ }
+ }
+ }
+ return k.signum() < 0 ? q.negate() : q;
+ }
+
+ public static ECPoint validatePoint(ECPoint p)
+ {
+ if (!p.isValid())
+ {
+ throw new IllegalArgumentException("Invalid point");
+ }
+
+ return p;
+ }
+
+ static ECPoint implShamirsTrickJsf(ECPoint P, BigInteger k,
ECPoint Q, BigInteger l)
{
ECCurve curve = P.getCurve();
@@ -118,7 +222,9 @@ public class ECAlgorithms
while (--i >= 0)
{
int jsfi = jsf[i];
- int kDigit = (jsfi >> 4), lDigit = ((jsfi << 28) >> 28);
+
+ // NOTE: The shifting ensures the sign is extended correctly
+ int kDigit = ((jsfi << 24) >> 28), lDigit = ((jsfi << 28) >> 28);
int index = 4 + (kDigit * 3) + lDigit;
R = R.twicePlus(table[index]);
@@ -126,4 +232,238 @@ public class ECAlgorithms
return R;
}
+
+ static ECPoint implShamirsTrickWNaf(ECPoint P, BigInteger k,
+ ECPoint Q, BigInteger l)
+ {
+ boolean negK = k.signum() < 0, negL = l.signum() < 0;
+
+ k = k.abs();
+ l = l.abs();
+
+ int widthP = Math.max(2, Math.min(16, WNafUtil.getWindowSize(k.bitLength())));
+ int widthQ = Math.max(2, Math.min(16, WNafUtil.getWindowSize(l.bitLength())));
+
+ WNafPreCompInfo infoP = WNafUtil.precompute(P, widthP, true);
+ WNafPreCompInfo infoQ = WNafUtil.precompute(Q, widthQ, true);
+
+ ECPoint[] preCompP = negK ? infoP.getPreCompNeg() : infoP.getPreComp();
+ ECPoint[] preCompQ = negL ? infoQ.getPreCompNeg() : infoQ.getPreComp();
+ ECPoint[] preCompNegP = negK ? infoP.getPreComp() : infoP.getPreCompNeg();
+ ECPoint[] preCompNegQ = negL ? infoQ.getPreComp() : infoQ.getPreCompNeg();
+
+ byte[] wnafP = WNafUtil.generateWindowNaf(widthP, k);
+ byte[] wnafQ = WNafUtil.generateWindowNaf(widthQ, l);
+
+ return implShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
+ }
+
+ static ECPoint implShamirsTrickWNaf(ECPoint P, BigInteger k, ECPointMap pointMapQ, BigInteger l)
+ {
+ boolean negK = k.signum() < 0, negL = l.signum() < 0;
+
+ k = k.abs();
+ l = l.abs();
+
+ int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(Math.max(k.bitLength(), l.bitLength()))));
+
+ ECPoint Q = WNafUtil.mapPointWithPrecomp(P, width, true, pointMapQ);
+ WNafPreCompInfo infoP = WNafUtil.getWNafPreCompInfo(P);
+ WNafPreCompInfo infoQ = WNafUtil.getWNafPreCompInfo(Q);
+
+ ECPoint[] preCompP = negK ? infoP.getPreCompNeg() : infoP.getPreComp();
+ ECPoint[] preCompQ = negL ? infoQ.getPreCompNeg() : infoQ.getPreComp();
+ ECPoint[] preCompNegP = negK ? infoP.getPreComp() : infoP.getPreCompNeg();
+ ECPoint[] preCompNegQ = negL ? infoQ.getPreComp() : infoQ.getPreCompNeg();
+
+ byte[] wnafP = WNafUtil.generateWindowNaf(width, k);
+ byte[] wnafQ = WNafUtil.generateWindowNaf(width, l);
+
+ return implShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
+ }
+
+ private static ECPoint implShamirsTrickWNaf(ECPoint[] preCompP, ECPoint[] preCompNegP, byte[] wnafP,
+ ECPoint[] preCompQ, ECPoint[] preCompNegQ, byte[] wnafQ)
+ {
+ int len = Math.max(wnafP.length, wnafQ.length);
+
+ ECCurve curve = preCompP[0].getCurve();
+ ECPoint infinity = curve.getInfinity();
+
+ ECPoint R = infinity;
+ int zeroes = 0;
+
+ for (int i = len - 1; i >= 0; --i)
+ {
+ int wiP = i < wnafP.length ? wnafP[i] : 0;
+ int wiQ = i < wnafQ.length ? wnafQ[i] : 0;
+
+ if ((wiP | wiQ) == 0)
+ {
+ ++zeroes;
+ continue;
+ }
+
+ ECPoint r = infinity;
+ if (wiP != 0)
+ {
+ int nP = Math.abs(wiP);
+ ECPoint[] tableP = wiP < 0 ? preCompNegP : preCompP;
+ r = r.add(tableP[nP >>> 1]);
+ }
+ if (wiQ != 0)
+ {
+ int nQ = Math.abs(wiQ);
+ ECPoint[] tableQ = wiQ < 0 ? preCompNegQ : preCompQ;
+ r = r.add(tableQ[nQ >>> 1]);
+ }
+
+ if (zeroes > 0)
+ {
+ R = R.timesPow2(zeroes);
+ zeroes = 0;
+ }
+
+ R = R.twicePlus(r);
+ }
+
+ if (zeroes > 0)
+ {
+ R = R.timesPow2(zeroes);
+ }
+
+ return R;
+ }
+
+ static ECPoint implSumOfMultiplies(ECPoint[] ps, BigInteger[] ks)
+ {
+ int count = ps.length;
+ boolean[] negs = new boolean[count];
+ WNafPreCompInfo[] infos = new WNafPreCompInfo[count];
+ byte[][] wnafs = new byte[count][];
+
+ for (int i = 0; i < count; ++i)
+ {
+ BigInteger ki = ks[i]; negs[i] = ki.signum() < 0; ki = ki.abs();
+
+ int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(ki.bitLength())));
+ infos[i] = WNafUtil.precompute(ps[i], width, true);
+ wnafs[i] = WNafUtil.generateWindowNaf(width, ki);
+ }
+
+ return implSumOfMultiplies(negs, infos, wnafs);
+ }
+
+ static ECPoint implSumOfMultipliesGLV(ECPoint[] ps, BigInteger[] ks, GLVEndomorphism glvEndomorphism)
+ {
+ BigInteger n = ps[0].getCurve().getOrder();
+
+ int len = ps.length;
+
+ BigInteger[] abs = new BigInteger[len << 1];
+ for (int i = 0, j = 0; i < len; ++i)
+ {
+ BigInteger[] ab = glvEndomorphism.decomposeScalar(ks[i].mod(n));
+ abs[j++] = ab[0];
+ abs[j++] = ab[1];
+ }
+
+ ECPointMap pointMap = glvEndomorphism.getPointMap();
+ if (glvEndomorphism.hasEfficientPointMap())
+ {
+ return ECAlgorithms.implSumOfMultiplies(ps, pointMap, abs);
+ }
+
+ ECPoint[] pqs = new ECPoint[len << 1];
+ for (int i = 0, j = 0; i < len; ++i)
+ {
+ ECPoint p = ps[i], q = pointMap.map(p);
+ pqs[j++] = p;
+ pqs[j++] = q;
+ }
+
+ return ECAlgorithms.implSumOfMultiplies(pqs, abs);
+
+ }
+
+ static ECPoint implSumOfMultiplies(ECPoint[] ps, ECPointMap pointMap, BigInteger[] ks)
+ {
+ int halfCount = ps.length, fullCount = halfCount << 1;
+
+ boolean[] negs = new boolean[fullCount];
+ WNafPreCompInfo[] infos = new WNafPreCompInfo[fullCount];
+ byte[][] wnafs = new byte[fullCount][];
+
+ for (int i = 0; i < halfCount; ++i)
+ {
+ int j0 = i << 1, j1 = j0 + 1;
+
+ BigInteger kj0 = ks[j0]; negs[j0] = kj0.signum() < 0; kj0 = kj0.abs();
+ BigInteger kj1 = ks[j1]; negs[j1] = kj1.signum() < 0; kj1 = kj1.abs();
+
+ int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(Math.max(kj0.bitLength(), kj1.bitLength()))));
+
+ ECPoint P = ps[i], Q = WNafUtil.mapPointWithPrecomp(P, width, true, pointMap);
+ infos[j0] = WNafUtil.getWNafPreCompInfo(P);
+ infos[j1] = WNafUtil.getWNafPreCompInfo(Q);
+ wnafs[j0] = WNafUtil.generateWindowNaf(width, kj0);
+ wnafs[j1] = WNafUtil.generateWindowNaf(width, kj1);
+ }
+
+ return implSumOfMultiplies(negs, infos, wnafs);
+ }
+
+ private static ECPoint implSumOfMultiplies(boolean[] negs, WNafPreCompInfo[] infos, byte[][] wnafs)
+ {
+ int len = 0, count = wnafs.length;
+ for (int i = 0; i < count; ++i)
+ {
+ len = Math.max(len, wnafs[i].length);
+ }
+
+ ECCurve curve = infos[0].getPreComp()[0].getCurve();
+ ECPoint infinity = curve.getInfinity();
+
+ ECPoint R = infinity;
+ int zeroes = 0;
+
+ for (int i = len - 1; i >= 0; --i)
+ {
+ ECPoint r = infinity;
+
+ for (int j = 0; j < count; ++j)
+ {
+ byte[] wnaf = wnafs[j];
+ int wi = i < wnaf.length ? wnaf[i] : 0;
+ if (wi != 0)
+ {
+ int n = Math.abs(wi);
+ WNafPreCompInfo info = infos[j];
+ ECPoint[] table = (wi < 0 == negs[j]) ? info.getPreComp() : info.getPreCompNeg();
+ r = r.add(table[n >>> 1]);
+ }
+ }
+
+ if (r == infinity)
+ {
+ ++zeroes;
+ continue;
+ }
+
+ if (zeroes > 0)
+ {
+ R = R.timesPow2(zeroes);
+ zeroes = 0;
+ }
+
+ R = R.twicePlus(r);
+ }
+
+ if (zeroes > 0)
+ {
+ R = R.timesPow2(zeroes);
+ }
+
+ return R;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
index 19f0062..4c658f2 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
@@ -1,9 +1,15 @@
package org.bouncycastle.math.ec;
import java.math.BigInteger;
+import java.util.Hashtable;
import java.util.Random;
+import org.bouncycastle.math.ec.endo.ECEndomorphism;
+import org.bouncycastle.math.ec.endo.GLVEndomorphism;
+import org.bouncycastle.math.field.FiniteField;
+import org.bouncycastle.math.field.FiniteFields;
import org.bouncycastle.util.BigIntegers;
+import org.bouncycastle.util.Integers;
/**
* base class for an elliptic curve
@@ -28,11 +34,13 @@ public abstract class ECCurve
public class Config
{
protected int coord;
+ protected ECEndomorphism endomorphism;
protected ECMultiplier multiplier;
- Config(int coord, ECMultiplier multiplier)
+ Config(int coord, ECEndomorphism endomorphism, ECMultiplier multiplier)
{
this.coord = coord;
+ this.endomorphism = endomorphism;
this.multiplier = multiplier;
}
@@ -42,6 +50,12 @@ public abstract class ECCurve
return this;
}
+ public Config setEndomorphism(ECEndomorphism endomorphism)
+ {
+ this.endomorphism = endomorphism;
+ return this;
+ }
+
public Config setMultiplier(ECMultiplier multiplier)
{
this.multiplier = multiplier;
@@ -62,23 +76,57 @@ public abstract class ECCurve
}
c.coord = coord;
+ c.endomorphism = endomorphism;
c.multiplier = multiplier;
return c;
}
}
+ protected FiniteField field;
protected ECFieldElement a, b;
+ protected BigInteger order, cofactor;
+
protected int coord = COORD_AFFINE;
+ protected ECEndomorphism endomorphism = null;
protected ECMultiplier multiplier = null;
+ protected ECCurve(FiniteField field)
+ {
+ this.field = field;
+ }
+
public abstract int getFieldSize();
public abstract ECFieldElement fromBigInteger(BigInteger x);
public Config configure()
{
- return new Config(this.coord, this.multiplier);
+ return new Config(this.coord, this.endomorphism, this.multiplier);
+ }
+
+ public ECPoint validatePoint(BigInteger x, BigInteger y)
+ {
+ ECPoint p = createPoint(x, y);
+ if (!p.isValid())
+ {
+ throw new IllegalArgumentException("Invalid point coordinates");
+ }
+ return p;
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, use {@link #validatePoint(BigInteger, BigInteger)}
+ * and refer {@link ECPoint#getEncoded(boolean)}
+ */
+ public ECPoint validatePoint(BigInteger x, BigInteger y, boolean withCompression)
+ {
+ ECPoint p = createPoint(x, y, withCompression);
+ if (!p.isValid())
+ {
+ throw new IllegalArgumentException("Invalid point coordinates");
+ }
+ return p;
}
public ECPoint createPoint(BigInteger x, BigInteger y)
@@ -99,8 +147,15 @@ public abstract class ECCurve
protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression);
+ protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression);
+
protected ECMultiplier createDefaultMultiplier()
{
+ if (endomorphism instanceof GLVEndomorphism)
+ {
+ return new GLVMultiplier(this, (GLVEndomorphism)endomorphism);
+ }
+
return new WNafL2RMultiplier();
}
@@ -109,26 +164,40 @@ public abstract class ECCurve
return coord == COORD_AFFINE;
}
- public PreCompInfo getPreCompInfo(ECPoint p)
+ public PreCompInfo getPreCompInfo(ECPoint point, String name)
{
- checkPoint(p);
- return p.preCompInfo;
+ checkPoint(point);
+ synchronized (point)
+ {
+ Hashtable table = point.preCompTable;
+ return table == null ? null : (PreCompInfo)table.get(name);
+ }
}
/**
- * Sets the <code>PreCompInfo</code> for a point on this curve. Used by
+ * Adds <code>PreCompInfo</code> for a point on this curve, under a given name. Used by
* <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use
* by subsequent multiplication.
*
* @param point
* The <code>ECPoint</code> to store precomputations for.
+ * @param name
+ * A <code>String</code> used to index precomputations of different types.
* @param preCompInfo
* The values precomputed by the <code>ECMultiplier</code>.
*/
- public void setPreCompInfo(ECPoint point, PreCompInfo preCompInfo)
+ public void setPreCompInfo(ECPoint point, String name, PreCompInfo preCompInfo)
{
checkPoint(point);
- point.preCompInfo = preCompInfo;
+ synchronized (point)
+ {
+ Hashtable table = point.preCompTable;
+ if (null == table)
+ {
+ point.preCompTable = table = new Hashtable(4);
+ }
+ table.put(name, preCompInfo);
+ }
}
public ECPoint importPoint(ECPoint p)
@@ -145,7 +214,7 @@ public abstract class ECCurve
// TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates.
p = p.normalize();
- return createPoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression);
+ return validatePoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression);
}
/**
@@ -188,7 +257,7 @@ public abstract class ECCurve
return;
}
- ECAlgorithms.implMontgomeryTrick(zs, 0, count);
+ ECAlgorithms.montgomeryTrick(zs, 0, count);
for (int j = 0; j < count; ++j)
{
@@ -199,6 +268,11 @@ public abstract class ECCurve
public abstract ECPoint getInfinity();
+ public FiniteField getField()
+ {
+ return field;
+ }
+
public ECFieldElement getA()
{
return a;
@@ -209,6 +283,16 @@ public abstract class ECCurve
return b;
}
+ public BigInteger getOrder()
+ {
+ return order;
+ }
+
+ public BigInteger getCofactor()
+ {
+ return cofactor;
+ }
+
public int getCoordinateSystem()
{
return coord;
@@ -216,10 +300,15 @@ public abstract class ECCurve
protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1);
+ public ECEndomorphism getEndomorphism()
+ {
+ return endomorphism;
+ }
+
/**
* Sets the default <code>ECMultiplier</code>, unless already set.
*/
- public ECMultiplier getMultiplier()
+ public synchronized ECMultiplier getMultiplier()
{
if (this.multiplier == null)
{
@@ -239,7 +328,8 @@ public abstract class ECCurve
ECPoint p = null;
int expectedLength = (getFieldSize() + 7) / 8;
- switch (encoded[0])
+ byte type = encoded[0];
+ switch (type)
{
case 0x00: // infinity
{
@@ -259,29 +349,56 @@ public abstract class ECCurve
throw new IllegalArgumentException("Incorrect length for compressed encoding");
}
- int yTilde = encoded[0] & 1;
+ int yTilde = type & 1;
BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
p = decompressPoint(yTilde, X);
+ if (!p.satisfiesCofactor())
+ {
+ throw new IllegalArgumentException("Invalid point");
+ }
+
break;
}
case 0x04: // uncompressed
+ {
+ if (encoded.length != (2 * expectedLength + 1))
+ {
+ throw new IllegalArgumentException("Incorrect length for uncompressed encoding");
+ }
+
+ BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
+ BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
+
+ p = validatePoint(X, Y);
+ break;
+ }
case 0x06: // hybrid
case 0x07: // hybrid
{
if (encoded.length != (2 * expectedLength + 1))
{
- throw new IllegalArgumentException("Incorrect length for uncompressed/hybrid encoding");
+ throw new IllegalArgumentException("Incorrect length for hybrid encoding");
}
BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
- p = createPoint(X, Y);
+ if (Y.testBit(0) != (type == 0x07))
+ {
+ throw new IllegalArgumentException("Inconsistent Y coordinate in hybrid encoding");
+ }
+
+ p = validatePoint(X, Y);
break;
}
default:
- throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
+ throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(type, 16));
+ }
+
+ if (type != 0x00 && p.isInfinity())
+ {
+ throw new IllegalArgumentException("Invalid infinity encoding");
}
return p;
@@ -312,10 +429,62 @@ public abstract class ECCurve
}
}
+ public boolean equals(ECCurve other)
+ {
+ return this == other
+ || (null != other
+ && getField().equals(other.getField())
+ && getA().toBigInteger().equals(other.getA().toBigInteger())
+ && getB().toBigInteger().equals(other.getB().toBigInteger()));
+ }
+
+ public boolean equals(Object obj)
+ {
+ return this == obj || (obj instanceof ECCurve && equals((ECCurve)obj));
+ }
+
+ public int hashCode()
+ {
+ return getField().hashCode()
+ ^ Integers.rotateLeft(getA().toBigInteger().hashCode(), 8)
+ ^ Integers.rotateLeft(getB().toBigInteger().hashCode(), 16);
+ }
+
+ public static abstract class AbstractFp extends ECCurve
+ {
+ protected AbstractFp(BigInteger q)
+ {
+ super(FiniteFields.getPrimeField(q));
+ }
+
+ protected ECPoint decompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement x = this.fromBigInteger(X1);
+ ECFieldElement rhs = x.square().add(a).multiply(x).add(b);
+ ECFieldElement y = rhs.sqrt();
+
+ /*
+ * If y is not a square, then we haven't got a point on the curve
+ */
+ if (y == null)
+ {
+ throw new IllegalArgumentException("Invalid point compression");
+ }
+
+ if (y.testBitZero() != (yTilde == 1))
+ {
+ // Use the other root
+ y = y.negate();
+ }
+
+ return this.createRawPoint(x, y, true);
+ }
+ }
+
/**
* Elliptic curve over Fp
*/
- public static class Fp extends ECCurve
+ public static class Fp extends AbstractFp
{
private static final int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
@@ -324,29 +493,47 @@ public abstract class ECCurve
public Fp(BigInteger q, BigInteger a, BigInteger b)
{
+ this(q, a, b, null, null);
+ }
+
+ public Fp(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor)
+ {
+ super(q);
+
this.q = q;
this.r = ECFieldElement.Fp.calculateResidue(q);
this.infinity = new ECPoint.Fp(this, null, null);
this.a = fromBigInteger(a);
this.b = fromBigInteger(b);
+ this.order = order;
+ this.cofactor = cofactor;
this.coord = FP_DEFAULT_COORDS;
}
protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)
{
+ this(q, r, a, b, null, null);
+ }
+
+ protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor)
+ {
+ super(q);
+
this.q = q;
this.r = r;
this.infinity = new ECPoint.Fp(this, null, null);
this.a = a;
this.b = b;
+ this.order = order;
+ this.cofactor = cofactor;
this.coord = FP_DEFAULT_COORDS;
}
protected ECCurve cloneCurve()
{
- return new Fp(q, r, a, b);
+ return new Fp(q, r, a, b, order, cofactor);
}
public boolean supportsCoordinateSystem(int coord)
@@ -383,6 +570,11 @@ public abstract class ECCurve
return new ECPoint.Fp(this, x, y, withCompression);
}
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new ECPoint.Fp(this, x, y, zs, withCompression);
+ }
+
public ECPoint importPoint(ECPoint p)
{
if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity())
@@ -405,58 +597,47 @@ public abstract class ECCurve
return super.importPoint(p);
}
- protected ECPoint decompressPoint(int yTilde, BigInteger X1)
+ public ECPoint getInfinity()
{
- ECFieldElement x = fromBigInteger(X1);
- ECFieldElement alpha = x.multiply(x.square().add(a)).add(b);
- ECFieldElement beta = alpha.sqrt();
+ return infinity;
+ }
+ }
- //
- // if we can't find a sqrt we haven't got a point on the
- // curve - run!
- //
- if (beta == null)
+ public static abstract class AbstractF2m extends ECCurve
+ {
+ private static FiniteField buildField(int m, int k1, int k2, int k3)
+ {
+ if (k1 == 0)
{
- throw new RuntimeException("Invalid point compression");
+ throw new IllegalArgumentException("k1 must be > 0");
}
- BigInteger betaValue = beta.toBigInteger();
- if (betaValue.testBit(0) != (yTilde == 1))
+ if (k2 == 0)
{
- // Use the other root
- beta = fromBigInteger(q.subtract(betaValue));
- }
-
- return new ECPoint.Fp(this, x, beta, true);
- }
+ if (k3 != 0)
+ {
+ throw new IllegalArgumentException("k3 must be 0 if k2 == 0");
+ }
- public ECPoint getInfinity()
- {
- return infinity;
- }
+ return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, m });
+ }
- public boolean equals(
- Object anObject)
- {
- if (anObject == this)
+ if (k2 <= k1)
{
- return true;
+ throw new IllegalArgumentException("k2 must be > k1");
}
- if (!(anObject instanceof ECCurve.Fp))
+ if (k3 <= k2)
{
- return false;
+ throw new IllegalArgumentException("k3 must be > k2");
}
- ECCurve.Fp other = (ECCurve.Fp) anObject;
-
- return this.q.equals(other.q)
- && a.equals(other.a) && b.equals(other.b);
+ return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, k2, k3, m });
}
- public int hashCode()
+ protected AbstractF2m(int m, int k1, int k2, int k3)
{
- return a.hashCode() ^ b.hashCode() ^ q.hashCode();
+ super(buildField(m, k1, k2, k3));
}
}
@@ -464,9 +645,9 @@ public abstract class ECCurve
* 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
+ public static class F2m extends AbstractF2m
{
- private static final int F2M_DEFAULT_COORDS = COORD_AFFINE;
+ private static final int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
/**
* The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
@@ -498,16 +679,6 @@ public abstract class ECCurve
* 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.
@@ -563,8 +734,8 @@ public abstract class ECCurve
* @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.
+ * @param order The order of the main subgroup of the elliptic curve.
+ * @param cofactor 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(
@@ -572,10 +743,10 @@ public abstract class ECCurve
int k,
BigInteger a,
BigInteger b,
- BigInteger n,
- BigInteger h)
+ BigInteger order,
+ BigInteger cofactor)
{
- this(m, k, 0, 0, a, b, n, h);
+ this(m, k, 0, 0, a, b, order, cofactor);
}
/**
@@ -628,8 +799,8 @@ public abstract class ECCurve
* @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.
+ * @param order The order of the main subgroup of the elliptic curve.
+ * @param cofactor 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(
@@ -639,40 +810,17 @@ public abstract class ECCurve
int k3,
BigInteger a,
BigInteger b,
- BigInteger n,
- BigInteger h)
+ BigInteger order,
+ BigInteger cofactor)
{
+ super(m, k1, k2, k3);
+
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.order = order;
+ this.cofactor = cofactor;
this.infinity = new ECPoint.F2m(this, null, null);
this.a = fromBigInteger(a);
@@ -680,14 +828,16 @@ public abstract class ECCurve
this.coord = F2M_DEFAULT_COORDS;
}
- protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger n, BigInteger h)
+ protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor)
{
+ super(m, k1, k2, k3);
+
this.m = m;
this.k1 = k1;
this.k2 = k2;
this.k3 = k3;
- this.n = n;
- this.h = h;
+ this.order = order;
+ this.cofactor = cofactor;
this.infinity = new ECPoint.F2m(this, null, null);
this.a = a;
@@ -697,7 +847,7 @@ public abstract class ECCurve
protected ECCurve cloneCurve()
{
- return new F2m(m, k1, k2, k3, a, b, n, h);
+ return new F2m(m, k1, k2, k3, a, b, order, cofactor);
}
public boolean supportsCoordinateSystem(int coord)
@@ -742,7 +892,14 @@ public abstract class ECCurve
case COORD_LAMBDA_AFFINE:
case COORD_LAMBDA_PROJECTIVE:
{
- if (!X.isZero())
+ if (X.isZero())
+ {
+ if (!Y.square().equals(this.getB()))
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+ else
{
// Y becomes Lambda (X + Y/X) here
Y = Y.divide(X).add(X);
@@ -763,6 +920,11 @@ public abstract class ECCurve
return new ECPoint.F2m(this, x, y, withCompression);
}
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new ECPoint.F2m(this, x, y, zs, withCompression);
+ }
+
public ECPoint getInfinity()
{
return infinity;
@@ -774,7 +936,7 @@ public abstract class ECCurve
*/
public boolean isKoblitz()
{
- return n != null && h != null && a.bitLength() <= 1 && b.bitLength() == 1;
+ return order != null && cofactor != null && b.isOne() && (a.isZero() || a.isOne());
}
/**
@@ -817,49 +979,47 @@ public abstract class ECCurve
*/
protected ECPoint decompressPoint(int yTilde, BigInteger X1)
{
- ECFieldElement xp = fromBigInteger(X1);
- ECFieldElement yp = null;
- if (xp.isZero())
+ ECFieldElement x = fromBigInteger(X1), y = null;
+ if (x.isZero())
{
- yp = (ECFieldElement.F2m)b;
- for (int i = 0; i < m - 1; i++)
- {
- yp = yp.square();
- }
+ y = b.sqrt();
}
else
{
- ECFieldElement beta = xp.add(a).add(b.multiply(xp.square().invert()));
+ ECFieldElement beta = x.square().invert().multiply(b).add(a).add(x);
ECFieldElement z = solveQuadraticEquation(beta);
- if (z == null)
- {
- throw new IllegalArgumentException("Invalid point compression");
- }
- if (z.testBitZero() != (yTilde == 1))
+ if (z != null)
{
- z = z.addOne();
+ if (z.testBitZero() != (yTilde == 1))
+ {
+ z = z.addOne();
+ }
+
+ switch (this.getCoordinateSystem())
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ y = z.add(x);
+ break;
+ }
+ default:
+ {
+ y = z.multiply(x);
+ break;
+ }
+ }
}
+ }
- yp = xp.multiply(z);
-
- switch (this.getCoordinateSystem())
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- yp = yp.divide(xp).add(xp);
- break;
- }
- default:
- {
- break;
- }
- }
+ if (y == null)
+ {
+ throw new IllegalArgumentException("Invalid point compression");
}
- return new ECPoint.F2m(this, xp, yp, true);
+ return this.createRawPoint(x, y, true);
}
-
+
/**
* Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
* D.1.6) The other solution is <code>z + 1</code>.
@@ -903,31 +1063,6 @@ public abstract class ECCurve
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()
{
@@ -959,14 +1094,20 @@ public abstract class ECCurve
return k3;
}
+ /**
+ * @deprecated use {@link #getOrder()} instead
+ */
public BigInteger getN()
{
- return n;
+ return order;
}
+ /**
+ * @deprecated use {@link #getCofactor()} instead
+ */
public BigInteger getH()
{
- return h;
+ return cofactor;
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
index 87608eb..5943882 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
@@ -3,6 +3,8 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
import java.util.Random;
+import org.bouncycastle.math.raw.Mod;
+import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
@@ -27,11 +29,36 @@ public abstract class ECFieldElement
return toBigInteger().bitLength();
}
+ public boolean isOne()
+ {
+ return bitLength() == 1;
+ }
+
public boolean isZero()
{
return 0 == toBigInteger().signum();
}
+ public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return multiply(b).subtract(x.multiply(y));
+ }
+
+ public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return multiply(b).add(x.multiply(y));
+ }
+
+ public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return square().subtract(x.multiply(y));
+ }
+
+ public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return square().add(x.multiply(y));
+ }
+
public boolean testBitZero()
{
return toBigInteger().testBit(0);
@@ -51,42 +78,10 @@ public abstract class ECFieldElement
{
BigInteger q, r, x;
-// static int[] calculateNaf(BigInteger p)
-// {
-// int[] naf = WNafUtil.generateCompactNaf(p);
-//
-// int bit = 0;
-// for (int i = 0; i < naf.length; ++i)
-// {
-// int ni = naf[i];
-// int digit = ni >> 16, zeroes = ni & 0xFFFF;
-//
-// bit += zeroes;
-// naf[i] = digit < 0 ? ~bit : bit;
-// ++bit;
-// }
-//
-// int last = naf.length - 1;
-// if (last > 0 && last <= 16)
-// {
-// int top = naf[last], top2 = naf[last - 1];
-// if (top2 < 0)
-// {
-// top2 = ~top2;
-// }
-// if (top - top2 >= 64)
-// {
-// return naf;
-// }
-// }
-//
-// return null;
-// }
-
static BigInteger calculateResidue(BigInteger p)
{
int bitLength = p.bitLength();
- if (bitLength > 128)
+ if (bitLength >= 96)
{
BigInteger firstWord = p.shiftRight(bitLength - 64);
if (firstWord.longValue() == -1L)
@@ -159,13 +154,7 @@ public abstract class ECFieldElement
public ECFieldElement subtract(ECFieldElement b)
{
- BigInteger x2 = b.toBigInteger();
- BigInteger x3 = x.subtract(x2);
- if (x3.signum() < 0)
- {
- x3 = x3.add(q);
- }
- return new Fp(q, r, x3);
+ return new Fp(q, r, modSubtract(x, b.toBigInteger()));
}
public ECFieldElement multiply(ECFieldElement b)
@@ -173,27 +162,30 @@ public abstract class ECFieldElement
return new Fp(q, r, modMult(x, b.toBigInteger()));
}
+ public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger();
+ BigInteger ab = ax.multiply(bx);
+ BigInteger xy = xx.multiply(yx);
+ return new Fp(q, r, modReduce(ab.subtract(xy)));
+ }
+
+ public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger();
+ BigInteger ab = ax.multiply(bx);
+ BigInteger xy = xx.multiply(yx);
+ return new Fp(q, r, modReduce(ab.add(xy)));
+ }
+
public ECFieldElement divide(ECFieldElement b)
{
- return new Fp(q, modMult(x, b.toBigInteger().modInverse(q)));
+ return new Fp(q, r, modMult(x, modInverse(b.toBigInteger())));
}
public ECFieldElement negate()
{
- BigInteger x2;
- if (x.signum() == 0)
- {
- x2 = x;
- }
- else if (ONE.equals(r))
- {
- x2 = q.xor(x);
- }
- else
- {
- x2 = q.subtract(x);
- }
- return new Fp(q, r, x2);
+ return x.signum() == 0 ? this : new Fp(q, r, q.subtract(x));
}
public ECFieldElement square()
@@ -201,10 +193,26 @@ public abstract class ECFieldElement
return new Fp(q, r, modMult(x, x));
}
+ public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger();
+ BigInteger aa = ax.multiply(ax);
+ BigInteger xy = xx.multiply(yx);
+ return new Fp(q, r, modReduce(aa.subtract(xy)));
+ }
+
+ public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger();
+ BigInteger aa = ax.multiply(ax);
+ BigInteger xy = xx.multiply(yx);
+ return new Fp(q, r, modReduce(aa.add(xy)));
+ }
+
public ECFieldElement invert()
{
// TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
- return new Fp(q, r, x.modInverse(q));
+ return new Fp(q, r, modInverse(x));
}
// D.1.4 91
@@ -214,6 +222,11 @@ public abstract class ECFieldElement
*/
public ECFieldElement sqrt()
{
+ if (this.isZero() || this.isOne()) // earlier JDK compatibility
+ {
+ return this;
+ }
+
if (!q.testBit(0))
{
throw new RuntimeException("not done yet");
@@ -221,29 +234,44 @@ public abstract class ECFieldElement
// 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))
+
+ if (q.testBit(1)) // q == 4m + 3
+ {
+ BigInteger e = q.shiftRight(2).add(ECConstants.ONE);
+ return checkSqrt(new Fp(q, r, x.modPow(e, q)));
+ }
+
+ if (q.testBit(2)) // q == 8m + 5
{
- // z = g^(u+1) + p, p = 4u + 3
- ECFieldElement z = new Fp(q, r, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q));
+ BigInteger t1 = x.modPow(q.shiftRight(3), q);
+ BigInteger t2 = modMult(t1, x);
+ BigInteger t3 = modMult(t2, t1);
+
+ if (t3.equals(ECConstants.ONE))
+ {
+ return checkSqrt(new Fp(q, r, t2));
+ }
+
+ // TODO This is constant and could be precomputed
+ BigInteger t4 = ECConstants.TWO.modPow(q.shiftRight(2), q);
- return z.square().equals(this) ? z : null;
+ BigInteger y = modMult(t2, t4);
+
+ return checkSqrt(new Fp(q, r, y));
}
- // p mod 4 == 1
- BigInteger qMinusOne = q.subtract(ECConstants.ONE);
+ // q == 8m + 1
- BigInteger legendreExponent = qMinusOne.shiftRight(1);
+ BigInteger legendreExponent = q.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 X = this.x;
+ BigInteger fourX = modDouble(modDouble(X));
- BigInteger Q = this.x;
- BigInteger fourQ = modDouble(modDouble(Q));
+ BigInteger k = legendreExponent.add(ECConstants.ONE), qMinusOne = q.subtract(ECConstants.ONE);
BigInteger U, V;
Random rand = new Random();
@@ -255,94 +283,39 @@ public abstract class ECFieldElement
P = new BigInteger(q.bitLength(), rand);
}
while (P.compareTo(q) >= 0
- || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne)));
+ || !modReduce(P.multiply(P).subtract(fourX)).modPow(legendreExponent, q).equals(qMinusOne));
- BigInteger[] result = lucasSequence(P, Q, k);
+ BigInteger[] result = lucasSequence(P, X, k);
U = result[0];
V = result[1];
- if (modMult(V, V).equals(fourQ))
+ if (modMult(V, V).equals(fourX))
{
- // 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, r, V);
+ return new ECFieldElement.Fp(q, r, modHalfAbs(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 ECFieldElement checkSqrt(ECFieldElement z)
+ {
+ return z.square().equals(this) ? z : null;
+ }
private BigInteger[] lucasSequence(
BigInteger P,
BigInteger Q,
BigInteger k)
{
+ // TODO Research and apply "common-multiplicand multiplication here"
+
int n = k.bitLength();
int s = k.getLowestSetBit();
+ // assert k.testBit(s);
+
BigInteger Uh = ECConstants.ONE;
BigInteger Vl = ECConstants.TWO;
BigInteger Vh = P;
@@ -405,6 +378,35 @@ public abstract class ECFieldElement
return _2x;
}
+ protected BigInteger modHalf(BigInteger x)
+ {
+ if (x.testBit(0))
+ {
+ x = q.add(x);
+ }
+ return x.shiftRight(1);
+ }
+
+ protected BigInteger modHalfAbs(BigInteger x)
+ {
+ if (x.testBit(0))
+ {
+ x = q.subtract(x);
+ }
+ return x.shiftRight(1);
+ }
+
+ protected BigInteger modInverse(BigInteger x)
+ {
+ int bits = getFieldSize();
+ int len = (bits + 31) >> 5;
+ int[] p = Nat.fromBigInteger(bits, q);
+ int[] n = Nat.fromBigInteger(bits, x);
+ int[] z = Nat.create(len);
+ Mod.invert(p, n, z);
+ return Nat.toBigInteger(len, z);
+ }
+
protected BigInteger modMult(BigInteger x1, BigInteger x2)
{
return modReduce(x1.multiply(x2));
@@ -412,44 +414,20 @@ public abstract class ECFieldElement
protected BigInteger modReduce(BigInteger x)
{
-// if (naf != null)
-// {
-// int last = naf.length - 1;
-// int bits = naf[last];
-// while (x.bitLength() > (bits + 1))
-// {
-// BigInteger u = x.shiftRight(bits);
-// BigInteger v = x.subtract(u.shiftLeft(bits));
-//
-// x = v;
-//
-// for (int i = 0; i < last; ++i)
-// {
-// int ni = naf[i];
-// if (ni < 0)
-// {
-// x = x.add(u.shiftLeft(~ni));
-// }
-// else
-// {
-// x = x.subtract(u.shiftLeft(ni));
-// }
-// }
-// }
-// while (x.compareTo(q) >= 0)
-// {
-// x = x.subtract(q);
-// }
-// }
-// else
if (r != null)
{
+ boolean negative = x.signum() < 0;
+ if (negative)
+ {
+ x = x.abs();
+ }
int qLen = q.bitLength();
+ boolean rIsOne = r.equals(ECConstants.ONE);
while (x.bitLength() > (qLen + 1))
{
BigInteger u = x.shiftRight(qLen);
BigInteger v = x.subtract(u.shiftLeft(qLen));
- if (!r.equals(ONE))
+ if (!rIsOne)
{
u = u.multiply(r);
}
@@ -459,6 +437,10 @@ public abstract class ECFieldElement
{
x = x.subtract(q);
}
+ if (negative && x.signum() != 0)
+ {
+ x = q.subtract(x);
+ }
}
else
{
@@ -467,6 +449,16 @@ public abstract class ECFieldElement
return x;
}
+ protected BigInteger modSubtract(BigInteger x1, BigInteger x2)
+ {
+ BigInteger x3 = x1.subtract(x2);
+ if (x3.signum() < 0)
+ {
+ x3 = x3.add(q);
+ }
+ return x3;
+ }
+
public boolean equals(Object other)
{
if (other == this)
@@ -489,467 +481,6 @@ public abstract class ECFieldElement
}
}
-// /**
-// * 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(16));
-//// }
-// }
-// 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)
@@ -987,32 +518,6 @@ public abstract class ECFieldElement
*/
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;
-
private int[] ks;
/**
@@ -1097,6 +602,11 @@ public abstract class ECFieldElement
return x.degree();
}
+ public boolean isOne()
+ {
+ return x.isOne();
+ }
+
public boolean isZero()
{
return x.isZero();
@@ -1192,6 +702,29 @@ public abstract class ECFieldElement
return new F2m(m, ks, x.modMultiply(((F2m)b).x, m, ks));
}
+ public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ return multiplyPlusProduct(b, x, y);
+ }
+
+ public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+ {
+ LongArray ax = this.x, bx = ((F2m)b).x, xx = ((F2m)x).x, yx = ((F2m)y).x;
+
+ LongArray ab = ax.multiply(bx, m, ks);
+ LongArray xy = xx.multiply(yx, m, ks);
+
+ if (ab == ax || ab == bx)
+ {
+ ab = (LongArray)ab.clone();
+ }
+
+ ab.addShiftedByWords(xy, 0);
+ ab.reduce(m, ks);
+
+ return new F2m(m, ks, ab);
+ }
+
public ECFieldElement divide(final ECFieldElement b)
{
// There may be more efficient implementations
@@ -1210,6 +743,29 @@ public abstract class ECFieldElement
return new F2m(m, ks, x.modSquare(m, ks));
}
+ public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ return squarePlusProduct(x, y);
+ }
+
+ public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y)
+ {
+ LongArray ax = this.x, xx = ((F2m)x).x, yx = ((F2m)y).x;
+
+ LongArray aa = ax.square(m, ks);
+ LongArray xy = xx.multiply(yx, m, ks);
+
+ if (aa == ax)
+ {
+ aa = (LongArray)aa.clone();
+ }
+
+ aa.addShiftedByWords(xy, 0);
+ aa.reduce(m, ks);
+
+ return new F2m(m, ks, aa);
+ }
+
public ECFieldElement invert()
{
return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks));
@@ -1217,7 +773,14 @@ public abstract class ECFieldElement
public ECFieldElement sqrt()
{
- throw new RuntimeException("Not implemented");
+ LongArray x1 = this.x;
+ if (x1.isOne() || x1.isZero())
+ {
+ return this;
+ }
+
+ LongArray x2 = x1.modSquareN(m - 1, m, ks);
+ return new ECFieldElement.F2m(m, ks, x2);
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
index 7f740e4..7cd04e4 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
@@ -1,6 +1,7 @@
package org.bouncycastle.math.ec;
import java.math.BigInteger;
+import java.util.Hashtable;
/**
* base class for points on elliptic curves.
@@ -47,7 +48,8 @@ public abstract class ECPoint
protected boolean withCompression;
- protected PreCompInfo preCompInfo = null;
+ // Hashtable is (String -> PreCompInfo)
+ protected Hashtable preCompTable = null;
protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
{
@@ -62,11 +64,26 @@ public abstract class ECPoint
this.zs = zs;
}
+ protected boolean satisfiesCofactor()
+ {
+ BigInteger h = curve.getCofactor();
+ return h == null || h.equals(ECConstants.ONE) || !ECAlgorithms.referenceMultiply(this, h).isInfinity();
+ }
+
+ protected abstract boolean satisfiesCurveEquation();
+
+ public final ECPoint getDetachedPoint()
+ {
+ return normalize().detach();
+ }
+
public ECCurve getCurve()
{
return curve;
}
+ protected abstract ECPoint detach();
+
protected int getCurveCoordinateSystem()
{
// Cope with null curve, most commonly used by implicitlyCa
@@ -79,7 +96,7 @@ public abstract class ECPoint
* Note: normalization can be expensive, this method is deprecated in favour
* of caller-controlled normalization.
*
- * @deprecated Use getAffineXCoord, or normalize() and getXCoord(), instead
+ * @deprecated Use getAffineXCoord(), or normalize() and getXCoord(), instead
*/
public ECFieldElement getX()
{
@@ -93,7 +110,7 @@ public abstract class ECPoint
* Note: normalization can be expensive, this method is deprecated in favour
* of caller-controlled normalization.
*
- * @deprecated Use getAffineYCoord, or normalize() and getYCoord(), instead
+ * @deprecated Use getAffineYCoord(), or normalize() and getYCoord(), instead
*/
public ECFieldElement getY()
{
@@ -129,7 +146,7 @@ public abstract class ECPoint
*
* Caution: depending on the curve's coordinate system, this may not be the same value as in an
* affine coordinate system; use normalize() to get a point where the coordinates have their
- * affine values, or use getAffineXCoord if you expect the point to already have been
+ * affine values, or use getAffineXCoord() if you expect the point to already have been
* normalized.
*
* @return the x-coordinate of this point
@@ -144,7 +161,7 @@ public abstract class ECPoint
*
* Caution: depending on the curve's coordinate system, this may not be the same value as in an
* affine coordinate system; use normalize() to get a point where the coordinates have their
- * affine values, or use getAffineYCoord if you expect the point to already have been
+ * affine values, or use getAffineYCoord() if you expect the point to already have been
* normalized.
*
* @return the y-coordinate of this point
@@ -171,16 +188,21 @@ public abstract class ECPoint
return copy;
}
- protected ECFieldElement getRawXCoord()
+ protected final ECFieldElement getRawXCoord()
{
return x;
}
- protected ECFieldElement getRawYCoord()
+ protected final ECFieldElement getRawYCoord()
{
return y;
}
+ protected final ECFieldElement[] getRawZCoords()
+ {
+ return zs;
+ }
+
protected void checkNormalized()
{
if (!isNormalized())
@@ -196,7 +218,7 @@ public abstract class ECPoint
return coord == ECCurve.COORD_AFFINE
|| coord == ECCurve.COORD_LAMBDA_AFFINE
|| isInfinity()
- || zs[0].bitLength() == 1;
+ || zs[0].isOne();
}
/**
@@ -222,7 +244,7 @@ public abstract class ECPoint
default:
{
ECFieldElement Z1 = getZCoord(0);
- if (Z1.bitLength() == 1)
+ if (Z1.isOne())
{
return this;
}
@@ -270,6 +292,46 @@ public abstract class ECPoint
return this.withCompression;
}
+ public boolean isValid()
+ {
+ if (isInfinity())
+ {
+ return true;
+ }
+
+ // TODO Sanity-check the field elements
+
+ ECCurve curve = getCurve();
+ if (curve != null)
+ {
+ if (!satisfiesCurveEquation())
+ {
+ return false;
+ }
+
+ if (!satisfiesCofactor())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public ECPoint scaleX(ECFieldElement scale)
+ {
+ return isInfinity()
+ ? this
+ : getCurve().createRawPoint(getRawXCoord().multiply(scale), getRawYCoord(), getRawZCoords(), this.withCompression);
+ }
+
+ public ECPoint scaleY(ECFieldElement scale)
+ {
+ return isInfinity()
+ ? this
+ : getCurve().createRawPoint(getRawXCoord(), getRawYCoord().multiply(scale), getRawZCoords(), this.withCompression);
+ }
+
public boolean equals(ECPoint other)
{
if (null == other)
@@ -454,13 +516,84 @@ public abstract class ECPoint
return this.getCurve().getMultiplier().multiply(this, k);
}
+ public static abstract class AbstractFp extends ECPoint
+ {
+ protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ super(curve, x, y);
+ }
+
+ protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
+ {
+ super(curve, x, y, zs);
+ }
+
+ protected boolean getCompressionYTilde()
+ {
+ return this.getAffineYCoord().testBitZero();
+ }
+
+ protected boolean satisfiesCurveEquation()
+ {
+ ECFieldElement X = this.x, Y = this.y, A = curve.getA(), B = curve.getB();
+ ECFieldElement lhs = Y.square();
+
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_AFFINE:
+ break;
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Z = this.zs[0];
+ if (!Z.isOne())
+ {
+ ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2);
+ lhs = lhs.multiply(Z);
+ A = A.multiply(Z2);
+ B = B.multiply(Z3);
+ }
+ break;
+ }
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ ECFieldElement Z = this.zs[0];
+ if (!Z.isOne())
+ {
+ ECFieldElement Z2 = Z.square(), Z4 = Z2.square(), Z6 = Z2.multiply(Z4);
+ A = A.multiply(Z4);
+ B = B.multiply(Z6);
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+
+ ECFieldElement rhs = X.square().add(A).multiply(X).add(B);
+ return lhs.equals(rhs);
+ }
+
+ public ECPoint subtract(ECPoint b)
+ {
+ if (b.isInfinity())
+ {
+ return this;
+ }
+
+ // Add -b
+ return this.add(b.negate());
+ }
+ }
+
/**
* Elliptic curve points over Fp
*/
- public static class Fp extends ECPoint
+ public static class Fp extends AbstractFp
{
/**
- * Create a point which encodes with point compression.
+ * Create a point which encodes without point compression.
*
* @param curve the curve to use
* @param x affine x co-ordinate
@@ -474,7 +607,7 @@ public abstract class ECPoint
}
/**
- * Create a point that encodes with or without point compresion.
+ * Create a point that encodes with or without point compression.
*
* @param curve the curve to use
* @param x affine x co-ordinate
@@ -487,7 +620,7 @@ public abstract class ECPoint
{
super(curve, x, y);
- if ((x != null && y == null) || (x == null && y != null))
+ if ((x == null) != (y == null))
{
throw new IllegalArgumentException("Exactly one of the field elements is null");
}
@@ -502,9 +635,9 @@ public abstract class ECPoint
this.withCompression = withCompression;
}
- protected boolean getCompressionYTilde()
+ protected ECPoint detach()
{
- return this.getAffineYCoord().testBitZero();
+ return new ECPoint.Fp(null, this.getAffineXCoord(), this.getAffineYCoord());
}
public ECFieldElement getZCoord(int index)
@@ -569,8 +702,8 @@ public abstract class ECPoint
ECFieldElement Z1 = this.zs[0];
ECFieldElement Z2 = b.zs[0];
- boolean Z1IsOne = Z1.bitLength() == 1;
- boolean Z2IsOne = Z2.bitLength() == 1;
+ boolean Z1IsOne = Z1.isOne();
+ boolean Z2IsOne = Z2.isOne();
ECFieldElement u1 = Z1IsOne ? Y2 : Y2.multiply(Z1);
ECFieldElement u2 = Z2IsOne ? Y1 : Y1.multiply(Z2);
@@ -600,7 +733,7 @@ public abstract class ECPoint
ECFieldElement A = u.square().multiply(w).subtract(vCubed).subtract(two(vSquaredV2));
ECFieldElement X3 = v.multiply(A);
- ECFieldElement Y3 = vSquaredV2.subtract(A).multiply(u).subtract(vCubed.multiply(u2));
+ ECFieldElement Y3 = vSquaredV2.subtract(A).multiplyMinusProduct(u, u2, vCubed);
ECFieldElement Z3 = vCubed.multiply(w);
return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
@@ -612,7 +745,7 @@ public abstract class ECPoint
ECFieldElement Z1 = this.zs[0];
ECFieldElement Z2 = b.zs[0];
- boolean Z1IsOne = Z1.bitLength() == 1;
+ boolean Z1IsOne = Z1.isOne();
ECFieldElement X3, Y3, Z3, Z3Squared = null;
@@ -662,7 +795,7 @@ public abstract class ECPoint
S2 = Z1Cubed.multiply(Y2);
}
- boolean Z2IsOne = Z2.bitLength() == 1;
+ boolean Z2IsOne = Z2.isOne();
ECFieldElement Z2Squared, U1, S1;
if (Z2IsOne)
{
@@ -697,8 +830,8 @@ public abstract class ECPoint
ECFieldElement V = HSquared.multiply(U1);
X3 = R.square().add(G).subtract(two(V));
- Y3 = V.subtract(X3).multiply(R).subtract(S1.multiply(G));
-
+ Y3 = V.subtract(X3).multiplyMinusProduct(R, G, S1);
+
Z3 = H;
if (!Z1IsOne)
{
@@ -735,6 +868,7 @@ public abstract class ECPoint
return new ECPoint.Fp(curve, X3, Y3, zs, this.withCompression);
}
+
default:
{
throw new IllegalStateException("unsupported coordinate system");
@@ -778,14 +912,13 @@ public abstract class ECPoint
{
ECFieldElement Z1 = this.zs[0];
- boolean Z1IsOne = Z1.bitLength() == 1;
- ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
+ boolean Z1IsOne = Z1.isOne();
// TODO Optimize for small negative a4 and -3
ECFieldElement w = curve.getA();
- if (!Z1IsOne)
+ if (!w.isZero() && !Z1IsOne)
{
- w = w.multiply(Z1Squared);
+ w = w.multiply(Z1.square());
}
w = w.add(three(X1.square()));
@@ -795,9 +928,11 @@ public abstract class ECPoint
ECFieldElement _4B = four(B);
ECFieldElement h = w.square().subtract(two(_4B));
- ECFieldElement X3 = two(h.multiply(s));
- ECFieldElement Y3 = w.multiply(_4B.subtract(h)).subtract(two(two(t).square()));
- ECFieldElement _4sSquared = Z1IsOne ? four(t) : two(s).square();
+ ECFieldElement _2s = two(s);
+ ECFieldElement X3 = h.multiply(_2s);
+ ECFieldElement _2t = two(t);
+ ECFieldElement Y3 = _4B.subtract(h).multiply(w).subtract(two(_2t.square()));
+ ECFieldElement _4sSquared = Z1IsOne ? two(_2t) : _2s.square();
ECFieldElement Z3 = two(_4sSquared).multiply(s);
return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
@@ -807,8 +942,7 @@ public abstract class ECPoint
{
ECFieldElement Z1 = this.zs[0];
- boolean Z1IsOne = Z1.bitLength() == 1;
- ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
+ boolean Z1IsOne = Z1.isOne();
ECFieldElement Y1Squared = Y1.square();
ECFieldElement T = Y1Squared.square();
@@ -819,6 +953,7 @@ public abstract class ECPoint
ECFieldElement M, S;
if (a4Neg.toBigInteger().equals(BigInteger.valueOf(3)))
{
+ ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
M = three(X1.add(Z1Squared).multiply(X1.subtract(Z1Squared)));
S = four(Y1Squared.multiply(X1));
}
@@ -830,8 +965,9 @@ public abstract class ECPoint
{
M = M.add(a4);
}
- else
+ else if (!a4.isZero())
{
+ ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
ECFieldElement Z1Pow4 = Z1Squared.square();
if (a4Neg.bitLength() < a4.bitLength())
{
@@ -842,7 +978,8 @@ public abstract class ECPoint
M = M.add(Z1Pow4.multiply(a4));
}
}
- S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
+// S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
+ S = four(X1.multiply(Y1Squared));
}
ECFieldElement X3 = M.square().subtract(two(S));
@@ -951,7 +1088,13 @@ public abstract class ECPoint
public ECPoint threeTimes()
{
- if (this.isInfinity() || this.y.isZero())
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
{
return this;
}
@@ -963,7 +1106,7 @@ public abstract class ECPoint
{
case ECCurve.COORD_AFFINE:
{
- ECFieldElement X1 = this.x, Y1 = this.y;
+ ECFieldElement X1 = this.x;
ECFieldElement _2Y1 = two(Y1);
ECFieldElement X = _2Y1.square();
@@ -997,6 +1140,98 @@ public abstract class ECPoint
}
}
+ public ECPoint timesPow2(int e)
+ {
+ if (e < 0)
+ {
+ throw new IllegalArgumentException("'e' cannot be negative");
+ }
+ if (e == 0 || this.isInfinity())
+ {
+ return this;
+ }
+ if (e == 1)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement W1 = curve.getA();
+ ECFieldElement X1 = this.x;
+ ECFieldElement Z1 = this.zs.length < 1 ? curve.fromBigInteger(ECConstants.ONE) : this.zs[0];
+
+ if (!Z1.isOne())
+ {
+ switch (coord)
+ {
+ case ECCurve.COORD_HOMOGENEOUS:
+ ECFieldElement Z1Sq = Z1.square();
+ X1 = X1.multiply(Z1);
+ Y1 = Y1.multiply(Z1Sq);
+ W1 = calculateJacobianModifiedW(Z1, Z1Sq);
+ break;
+ case ECCurve.COORD_JACOBIAN:
+ W1 = calculateJacobianModifiedW(Z1, null);
+ break;
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ W1 = getJacobianModifiedW();
+ break;
+ }
+ }
+
+ for (int i = 0; i < e; ++i)
+ {
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ ECFieldElement X1Squared = X1.square();
+ ECFieldElement M = three(X1Squared);
+ ECFieldElement _2Y1 = two(Y1);
+ ECFieldElement _2Y1Squared = _2Y1.multiply(Y1);
+ ECFieldElement S = two(X1.multiply(_2Y1Squared));
+ ECFieldElement _4T = _2Y1Squared.square();
+ ECFieldElement _8T = two(_4T);
+
+ if (!W1.isZero())
+ {
+ M = M.add(W1);
+ W1 = two(_8T.multiply(W1));
+ }
+
+ X1 = M.square().subtract(two(S));
+ Y1 = M.multiply(S.subtract(X1)).subtract(_8T);
+ Z1 = Z1.isOne() ? _2Y1 : _2Y1.multiply(Z1);
+ }
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ ECFieldElement zInv = Z1.invert(), zInv2 = zInv.square(), zInv3 = zInv2.multiply(zInv);
+ return new Fp(curve, X1.multiply(zInv2), Y1.multiply(zInv3), this.withCompression);
+ case ECCurve.COORD_HOMOGENEOUS:
+ X1 = X1.multiply(Z1);
+ Z1 = Z1.multiply(Z1.square());
+ return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1 }, this.withCompression);
+ case ECCurve.COORD_JACOBIAN:
+ return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1 }, this.withCompression);
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1, W1 }, this.withCompression);
+ default:
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
+
protected ECFieldElement two(ECFieldElement x)
{
return x.add(x);
@@ -1027,18 +1262,6 @@ public abstract class ECPoint
return a.add(b).square().subtract(aSquared).subtract(bSquared);
}
- // 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()
{
if (this.isInfinity())
@@ -1059,13 +1282,18 @@ public abstract class ECPoint
protected ECFieldElement calculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared)
{
+ ECFieldElement a4 = this.getCurve().getA();
+ if (a4.isZero() || Z.isOne())
+ {
+ return a4;
+ }
+
if (ZSquared == null)
{
ZSquared = Z.square();
}
ECFieldElement W = ZSquared.square();
- ECFieldElement a4 = this.getCurve().getA();
ECFieldElement a4Neg = a4.negate();
if (a4Neg.bitLength() < a4.bitLength())
{
@@ -1095,23 +1323,105 @@ public abstract class ECPoint
ECFieldElement X1Squared = X1.square();
ECFieldElement M = three(X1Squared).add(W1);
- ECFieldElement Y1Squared = Y1.square();
- ECFieldElement T = Y1Squared.square();
- ECFieldElement S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
+ ECFieldElement _2Y1 = two(Y1);
+ ECFieldElement _2Y1Squared = _2Y1.multiply(Y1);
+ ECFieldElement S = two(X1.multiply(_2Y1Squared));
ECFieldElement X3 = M.square().subtract(two(S));
- ECFieldElement _8T = eight(T);
+ ECFieldElement _4T = _2Y1Squared.square();
+ ECFieldElement _8T = two(_4T);
ECFieldElement Y3 = M.multiply(S.subtract(X3)).subtract(_8T);
ECFieldElement W3 = calculateW ? two(_8T.multiply(W1)) : null;
- ECFieldElement Z3 = two(Z1.bitLength() == 1 ? Y1 : Y1.multiply(Z1));
+ ECFieldElement Z3 = Z1.isOne() ? _2Y1 : _2Y1.multiply(Z1);
return new ECPoint.Fp(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression);
}
}
+ public static abstract class AbstractF2m extends ECPoint
+ {
+ protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ super(curve, x, y);
+ }
+
+ protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
+ {
+ super(curve, x, y, zs);
+ }
+
+ protected boolean satisfiesCurveEquation()
+ {
+ ECCurve curve = this.getCurve();
+ ECFieldElement X = this.x, A = curve.getA(), B = curve.getB();
+
+ int coord = curve.getCoordinateSystem();
+ if (coord == ECCurve.COORD_LAMBDA_PROJECTIVE)
+ {
+ ECFieldElement Z = this.zs[0];
+ boolean ZIsOne = Z.isOne();
+
+ if (X.isZero())
+ {
+ // NOTE: For x == 0, we expect the affine-y instead of the lambda-y
+ ECFieldElement Y = this.y;
+ ECFieldElement lhs = Y.square(), rhs = B;
+ if (!ZIsOne)
+ {
+ rhs = rhs.multiply(Z.square());
+ }
+ return lhs.equals(rhs);
+ }
+
+ ECFieldElement L = this.y, X2 = X.square();
+ ECFieldElement lhs, rhs;
+ if (ZIsOne)
+ {
+ lhs = L.square().add(L).add(A);
+ rhs = X2.square().add(B);
+ }
+ else
+ {
+ ECFieldElement Z2 = Z.square(), Z4 = Z2.square();
+ lhs = L.add(Z).multiplyPlusProduct(L, A, Z2);
+ // TODO If sqrt(b) is precomputed this can be simplified to a single square
+ rhs = X2.squarePlusProduct(B, Z4);
+ }
+ lhs = lhs.multiply(X2);
+ return lhs.equals(rhs);
+ }
+
+ ECFieldElement Y = this.y;
+ ECFieldElement lhs = Y.add(X).multiply(Y);
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ break;
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Z = this.zs[0];
+ if (!Z.isOne())
+ {
+ ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2);
+ lhs = lhs.multiply(Z);
+ A = A.multiply(Z);
+ B = B.multiply(Z3);
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+
+ ECFieldElement rhs = X.add(A).multiply(X.square()).add(B);
+ return lhs.equals(rhs);
+ }
+ }
+
/**
* Elliptic curve points over F2m
*/
- public static class F2m extends ECPoint
+ public static class F2m extends AbstractF2m
{
/**
* @param curve base curve
@@ -1137,7 +1447,7 @@ public abstract class ECPoint
{
super(curve, x, y);
- if ((x != null && y == null) || (x == null && y != null))
+ if ((x == null) != (y == null))
{
throw new IllegalArgumentException("Exactly one of the field elements is null");
}
@@ -1168,6 +1478,11 @@ public abstract class ECPoint
// checkCurveEquation();
}
+ protected ECPoint detach()
+ {
+ return new ECPoint.F2m(null, this.getAffineXCoord(), this.getAffineYCoord()); // earlier JDK
+ }
+
public ECFieldElement getYCoord()
{
int coord = this.getCurveCoordinateSystem();
@@ -1177,19 +1492,19 @@ public abstract class ECPoint
case ECCurve.COORD_LAMBDA_AFFINE:
case ECCurve.COORD_LAMBDA_PROJECTIVE:
{
- // TODO The X == 0 stuff needs further thought
- if (this.isInfinity() || x.isZero())
+ ECFieldElement X = x, L = y;
+
+ if (this.isInfinity() || X.isZero())
{
- return y;
+ return L;
}
// Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
- ECFieldElement X = x, L = y;
- ECFieldElement Y = L.subtract(X).multiply(X);
+ ECFieldElement Y = L.add(X).multiply(X);
if (ECCurve.COORD_LAMBDA_PROJECTIVE == coord)
{
ECFieldElement Z = zs[0];
- if (Z.bitLength() != 1)
+ if (!Z.isOne())
{
Y = Y.divide(Z);
}
@@ -1203,6 +1518,74 @@ public abstract class ECPoint
}
}
+ public ECPoint scaleX(ECFieldElement scale)
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ int coord = this.getCurveCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ // Y is actually Lambda (X + Y/X) here
+ ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK
+
+ ECFieldElement X2 = X.multiply(scale);
+ ECFieldElement L2 = L.add(X).divide(scale).add(X2);
+
+ return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK
+ }
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ // Y is actually Lambda (X + Y/X) here
+ ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(), Z = this.getRawZCoords()[0]; // earlier JDK
+
+ // We scale the Z coordinate also, to avoid an inversion
+ ECFieldElement X2 = X.multiply(scale.square());
+ ECFieldElement L2 = L.add(X).add(X2);
+ ECFieldElement Z2 = Z.multiply(scale);
+
+ return this.getCurve().createRawPoint(X2, L2, new ECFieldElement[]{ Z2 }, this.withCompression); // earlier JDK
+ }
+ default:
+ {
+ return super.scaleX(scale);
+ }
+ }
+ }
+
+ public ECPoint scaleY(ECFieldElement scale)
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ int coord = this.getCurveCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK
+
+ // Y is actually Lambda (X + Y/X) here
+ ECFieldElement L2 = L.add(X).multiply(scale).add(X);
+
+ return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK
+ }
+ default:
+ {
+ return super.scaleY(scale);
+ }
+ }
+ }
+
protected boolean getCompressionYTilde()
{
ECFieldElement X = this.getRawXCoord();
@@ -1219,7 +1602,7 @@ public abstract class ECPoint
case ECCurve.COORD_LAMBDA_PROJECTIVE:
{
// Y is actually Lambda (X + Y/X) here
- return Y.subtract(X).testBitZero();
+ return Y.testBitZero() != X.testBitZero();
}
default:
{
@@ -1289,9 +1672,10 @@ public abstract class ECPoint
ECFieldElement Y1 = this.y;
ECFieldElement Y2 = b.y;
- if (X1.equals(X2))
+ ECFieldElement dx = X1.add(X2), dy = Y1.add(Y2);
+ if (dx.isZero())
{
- if (Y1.equals(Y2))
+ if (dy.isZero())
{
return (ECPoint.F2m)twice();
}
@@ -1299,10 +1683,9 @@ public abstract class ECPoint
return (ECPoint.F2m)curve.getInfinity();
}
- ECFieldElement sumX = X1.add(X2);
- ECFieldElement L = Y1.add(Y2).divide(sumX);
+ ECFieldElement L = dy.divide(dx);
- ECFieldElement X3 = L.square().add(L).add(sumX).add(curve.getA());
+ ECFieldElement X3 = L.square().add(L).add(dx).add(curve.getA());
ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
@@ -1312,18 +1695,18 @@ public abstract class ECPoint
ECFieldElement Y1 = this.y, Z1 = this.zs[0];
ECFieldElement Y2 = b.y, Z2 = b.zs[0];
- boolean Z2IsOne = Z2.bitLength() == 1;
+ boolean Z2IsOne = Z2.isOne();
- ECFieldElement U1 = Z1.multiply(Y2);
+ ECFieldElement U1 = Z1.multiply(Y2);
ECFieldElement U2 = Z2IsOne ? Y1 : Y1.multiply(Z2);
- ECFieldElement U = U1.subtract(U2);
+ ECFieldElement U = U1.add(U2);
ECFieldElement V1 = Z1.multiply(X2);
ECFieldElement V2 = Z2IsOne ? X1 : X1.multiply(Z2);
- ECFieldElement V = V1.subtract(V2);
+ ECFieldElement V = V1.add(V2);
- if (V1.equals(V2))
+ if (V.isZero())
{
- if (U1.equals(U2))
+ if (U.isZero())
{
return (ECPoint.F2m)twice();
}
@@ -1331,14 +1714,16 @@ public abstract class ECPoint
return (ECPoint.F2m)curve.getInfinity();
}
- ECFieldElement VSq = V.square();
+ ECFieldElement VSq = V.square();
+ ECFieldElement VCu = VSq.multiply(V);
ECFieldElement W = Z2IsOne ? Z1 : Z1.multiply(Z2);
- ECFieldElement A = U.square().add(U.multiply(V).add(VSq.multiply(curve.getA()))).multiply(W).add(V.multiply(VSq));
+ ECFieldElement uv = U.add(V);
+ ECFieldElement A = uv.multiplyPlusProduct(U, VSq, curve.getA()).multiply(W).add(VCu);
ECFieldElement X3 = V.multiply(A);
ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.multiply(Z2);
- ECFieldElement Y3 = VSqZ2.multiply(U.multiply(X1).add(Y1.multiply(V))).add(A.multiply(U.add(V)));
- ECFieldElement Z3 = VSq.multiply(V).multiply(W);
+ ECFieldElement Y3 = U.multiplyPlusProduct(X1, V, Y1).multiplyPlusProduct(VSqZ2, uv, A);
+ ECFieldElement Z3 = VCu.multiply(W);
return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
}
@@ -1346,13 +1731,18 @@ public abstract class ECPoint
{
if (X1.isZero())
{
+ if (X2.isZero())
+ {
+ return (ECPoint.F2m)curve.getInfinity();
+ }
+
return b.addSimple(this);
}
ECFieldElement L1 = this.y, Z1 = this.zs[0];
ECFieldElement L2 = b.y, Z2 = b.zs[0];
- boolean Z1IsOne = Z1.bitLength() == 1;
+ boolean Z1IsOne = Z1.isOne();
ECFieldElement U2 = X2, S2 = L2;
if (!Z1IsOne)
{
@@ -1360,7 +1750,7 @@ public abstract class ECPoint
S2 = S2.multiply(Z1);
}
- boolean Z2IsOne = Z2.bitLength() == 1;
+ boolean Z2IsOne = Z2.isOne();
ECFieldElement U1 = X1, S1 = L1;
if (!Z2IsOne)
{
@@ -1385,13 +1775,21 @@ public abstract class ECPoint
if (X2.isZero())
{
// TODO This can probably be optimized quite a bit
+ ECPoint p = this.normalize();
+ X1 = p.getXCoord();
+ ECFieldElement Y1 = p.getYCoord();
- ECFieldElement Y1 = getYCoord(), Y2 = L2;
+ ECFieldElement Y2 = L2;
ECFieldElement L = Y1.add(Y2).divide(X1);
X3 = L.square().add(L).add(X1).add(curve.getA());
+ if (X3.isZero())
+ {
+ return new ECPoint.F2m(curve, X3, curve.getB().sqrt(), this.withCompression);
+ }
+
ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
- L3 = X3.isZero() ? Y3 : Y3.divide(X3).add(X3);
+ L3 = Y3.divide(X3).add(X3);
Z3 = curve.fromBigInteger(ECConstants.ONE);
}
else
@@ -1400,14 +1798,20 @@ public abstract class ECPoint
ECFieldElement AU1 = A.multiply(U1);
ECFieldElement AU2 = A.multiply(U2);
+
+ X3 = AU1.multiply(AU2);
+ if (X3.isZero())
+ {
+ return new ECPoint.F2m(curve, X3, curve.getB().sqrt(), this.withCompression);
+ }
+
ECFieldElement ABZ2 = A.multiply(B);
if (!Z2IsOne)
{
ABZ2 = ABZ2.multiply(Z2);
}
- X3 = AU1.multiply(AU2);
- L3 = AU2.add(B).square().add(ABZ2.multiply(L1.add(Z1)));
+ L3 = AU2.add(B).squarePlusProduct(ABZ2, L1.add(Z1));
Z3 = ABZ2;
if (!Z1IsOne)
@@ -1514,7 +1918,7 @@ public abstract class ECPoint
ECFieldElement L1 = Y1.divide(X1).add(X1);
ECFieldElement X3 = L1.square().add(L1).add(curve.getA());
- ECFieldElement Y3 = X1.square().add(X3.multiply(L1.addOne()));
+ ECFieldElement Y3 = X1.squarePlusProduct(X3, L1.addOne());
return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
}
@@ -1522,7 +1926,7 @@ public abstract class ECPoint
{
ECFieldElement Y1 = this.y, Z1 = this.zs[0];
- boolean Z1IsOne = Z1.bitLength() == 1;
+ boolean Z1IsOne = Z1.isOne();
ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1);
ECFieldElement Y1Z1 = Z1IsOne ? Y1 : Y1.multiply(Z1);
@@ -1530,10 +1934,11 @@ public abstract class ECPoint
ECFieldElement S = X1Sq.add(Y1Z1);
ECFieldElement V = X1Z1;
ECFieldElement vSquared = V.square();
- ECFieldElement h = S.square().add(S.multiply(V)).add(curve.getA().multiply(vSquared));
+ ECFieldElement sv = S.add(V);
+ ECFieldElement h = sv.multiplyPlusProduct(S, vSquared, curve.getA());
ECFieldElement X3 = V.multiply(h);
- ECFieldElement Y3 = h.multiply(S.add(V)).add(X1Sq.square().multiply(V));
+ ECFieldElement Y3 = X1Sq.square().multiplyPlusProduct(V, h, sv);
ECFieldElement Z3 = V.multiply(vSquared);
return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
@@ -1542,12 +1947,16 @@ public abstract class ECPoint
{
ECFieldElement L1 = this.y, Z1 = this.zs[0];
- boolean Z1IsOne = Z1.bitLength() == 1;
+ boolean Z1IsOne = Z1.isOne();
ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.multiply(Z1);
ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.square();
ECFieldElement a = curve.getA();
ECFieldElement aZ1Sq = Z1IsOne ? a : a.multiply(Z1Sq);
ECFieldElement T = L1.square().add(L1Z1).add(aZ1Sq);
+ if (T.isZero())
+ {
+ return new ECPoint.F2m(curve, T, curve.getB().sqrt(), withCompression);
+ }
ECFieldElement X3 = T.square();
ECFieldElement Z3 = Z1IsOne ? T : T.multiply(Z1Sq);
@@ -1557,14 +1966,30 @@ public abstract class ECPoint
if (b.bitLength() < (curve.getFieldSize() >> 1))
{
ECFieldElement t1 = L1.add(X1).square();
- ECFieldElement t2 = aZ1Sq.square();
- ECFieldElement t3 = curve.getB().multiply(Z1Sq.square());
- L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2.add(t3)).add(X3).add(a.addOne().multiply(Z3));
+ ECFieldElement t2;
+ if (b.isOne())
+ {
+ t2 = aZ1Sq.add(Z1Sq).square();
+ }
+ else
+ {
+ // TODO Can be calculated with one square if we pre-compute sqrt(b)
+ t2 = aZ1Sq.squarePlusProduct(b, Z1Sq.square());
+ }
+ L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2).add(X3);
+ if (a.isZero())
+ {
+ L3 = L3.add(Z3);
+ }
+ else if (!a.isOne())
+ {
+ L3 = L3.add(a.addOne().multiply(Z3));
+ }
}
else
{
ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1);
- L3 = X1Z1.square().add(X3).add(T.multiply(L1Z1)).add(Z3);
+ L3 = X1Z1.squarePlusProduct(T, L1Z1).add(X3).add(Z3);
}
return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
@@ -1604,7 +2029,7 @@ public abstract class ECPoint
{
// NOTE: twicePlus() only optimized for lambda-affine argument
ECFieldElement X2 = b.x, Z2 = b.zs[0];
- if (X2.isZero() || Z2.bitLength() != 1)
+ if (X2.isZero() || !Z2.isOne())
{
return twice().add(b);
}
@@ -1619,13 +2044,28 @@ public abstract class ECPoint
ECFieldElement T = curve.getA().multiply(Z1Sq).add(L1Sq).add(L1Z1);
ECFieldElement L2plus1 = L2.addOne();
- ECFieldElement A = curve.getA().add(L2plus1).multiply(Z1Sq).add(L1Sq).multiply(T).add(X1Sq.multiply(Z1Sq));
+ ECFieldElement A = curve.getA().add(L2plus1).multiply(Z1Sq).add(L1Sq).multiplyPlusProduct(T, X1Sq, Z1Sq);
ECFieldElement X2Z1Sq = X2.multiply(Z1Sq);
ECFieldElement B = X2Z1Sq.add(T).square();
+ if (B.isZero())
+ {
+ if (A.isZero())
+ {
+ return b.twice();
+ }
+
+ return curve.getInfinity();
+ }
+
+ if (A.isZero())
+ {
+ return new ECPoint.F2m(curve, A, curve.getB().sqrt(), withCompression);
+ }
+
ECFieldElement X3 = A.square().multiply(X2Z1Sq);
ECFieldElement Z3 = A.multiply(B).multiply(Z1Sq);
- ECFieldElement L3 = A.add(B).square().multiply(T).add(L2plus1.multiply(Z3));
+ ECFieldElement L3 = A.add(B).square().multiplyPlusProduct(T, L2plus1, Z3);
return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
}
@@ -1636,57 +2076,6 @@ public abstract class ECPoint
}
}
- protected void checkCurveEquation()
- {
- if (this.isInfinity())
- {
- return;
- }
-
- ECFieldElement Z;
- switch (this.getCurveCoordinateSystem())
- {
- case ECCurve.COORD_LAMBDA_AFFINE:
- Z = curve.fromBigInteger(ECConstants.ONE);
- break;
- case ECCurve.COORD_LAMBDA_PROJECTIVE:
- Z = this.zs[0];
- break;
- default:
- return;
- }
-
- if (Z.isZero())
- {
- throw new IllegalStateException();
- }
-
- ECFieldElement X = this.x;
- if (X.isZero())
- {
- // NOTE: For x == 0, we expect the affine-y instead of the lambda-y
- ECFieldElement Y = this.y;
- if (!Y.square().equals(curve.getB().multiply(Z)))
- {
- throw new IllegalStateException();
- }
-
- return;
- }
-
- ECFieldElement L = this.y;
- ECFieldElement XSq = X.square();
- ECFieldElement ZSq = Z.square();
-
- ECFieldElement lhs = L.square().add(L.multiply(Z)).add(this.getCurve().getA().multiply(ZSq)).multiply(XSq);
- ECFieldElement rhs = ZSq.square().multiply(this.getCurve().getB()).add(XSq.square());
-
- if (!lhs.equals(rhs))
- {
- throw new IllegalStateException("F2m Lambda-Projective invariant broken");
- }
- }
-
public ECPoint negate()
{
if (this.isInfinity())
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPointMap.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPointMap.java
new file mode 100644
index 0000000..439e8da
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPointMap.java
@@ -0,0 +1,6 @@
+package org.bouncycastle.math.ec;
+
+public interface ECPointMap
+{
+ ECPoint map(ECPoint p);
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java
new file mode 100644
index 0000000..9fe00b9
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java
@@ -0,0 +1,57 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public class FixedPointCombMultiplier extends AbstractECMultiplier
+{
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ ECCurve c = p.getCurve();
+ int size = FixedPointUtil.getCombSize(c);
+
+ if (k.bitLength() > size)
+ {
+ /*
+ * TODO The comb works best when the scalars are less than the (possibly unknown) order.
+ * Still, if we want to handle larger scalars, we could allow customization of the comb
+ * size, or alternatively we could deal with the 'extra' bits either by running the comb
+ * multiple times as necessary, or by using an alternative multiplier as prelude.
+ */
+ throw new IllegalStateException("fixed-point comb doesn't support scalars larger than the curve order");
+ }
+
+ int minWidth = getWidthForCombSize(size);
+
+ FixedPointPreCompInfo info = FixedPointUtil.precompute(p, minWidth);
+ ECPoint[] lookupTable = info.getPreComp();
+ int width = info.getWidth();
+
+ int d = (size + width - 1) / width;
+
+ ECPoint R = c.getInfinity();
+
+ int top = d * width - 1;
+ for (int i = 0; i < d; ++i)
+ {
+ int index = 0;
+
+ for (int j = top - i; j >= 0; j -= d)
+ {
+ index <<= 1;
+ if (k.testBit(j))
+ {
+ index |= 1;
+ }
+ }
+
+ R = R.twicePlus(lookupTable[index]);
+ }
+
+ return R;
+ }
+
+ protected int getWidthForCombSize(int combSize)
+ {
+ return combSize > 257 ? 6 : 5;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java
new file mode 100644
index 0000000..b7569aa
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java
@@ -0,0 +1,40 @@
+package org.bouncycastle.math.ec;
+
+/**
+ * Class holding precomputation data for fixed-point multiplications.
+ */
+public class FixedPointPreCompInfo implements PreCompInfo
+{
+ /**
+ * Array holding the precomputed <code>ECPoint</code>s used for a fixed
+ * point multiplication.
+ */
+ protected ECPoint[] preComp = null;
+
+ /**
+ * The width used for the precomputation. If a larger width precomputation
+ * is already available this may be larger than was requested, so calling
+ * code should refer to the actual width.
+ */
+ protected int width = -1;
+
+ public ECPoint[] getPreComp()
+ {
+ return preComp;
+ }
+
+ public void setPreComp(ECPoint[] preComp)
+ {
+ this.preComp = preComp;
+ }
+
+ public int getWidth()
+ {
+ return width;
+ }
+
+ public void setWidth(int width)
+ {
+ this.width = width;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java
new file mode 100644
index 0000000..e4fbb8d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java
@@ -0,0 +1,71 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public class FixedPointUtil
+{
+ public static final String PRECOMP_NAME = "bc_fixed_point";
+
+ public static int getCombSize(ECCurve c)
+ {
+ BigInteger order = c.getOrder();
+ return order == null ? c.getFieldSize() + 1 : order.bitLength();
+ }
+
+ public static FixedPointPreCompInfo getFixedPointPreCompInfo(PreCompInfo preCompInfo)
+ {
+ if ((preCompInfo != null) && (preCompInfo instanceof FixedPointPreCompInfo))
+ {
+ return (FixedPointPreCompInfo)preCompInfo;
+ }
+
+ return new FixedPointPreCompInfo();
+ }
+
+ public static FixedPointPreCompInfo precompute(ECPoint p, int minWidth)
+ {
+ ECCurve c = p.getCurve();
+
+ int n = 1 << minWidth;
+ FixedPointPreCompInfo info = getFixedPointPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME));
+ ECPoint[] lookupTable = info.getPreComp();
+
+ if (lookupTable == null || lookupTable.length < n)
+ {
+ int bits = getCombSize(c);
+ int d = (bits + minWidth - 1) / minWidth;
+
+ ECPoint[] pow2Table = new ECPoint[minWidth];
+ pow2Table[0] = p;
+ for (int i = 1; i < minWidth; ++i)
+ {
+ pow2Table[i] = pow2Table[i - 1].timesPow2(d);
+ }
+
+ c.normalizeAll(pow2Table);
+
+ lookupTable = new ECPoint[n];
+ lookupTable[0] = c.getInfinity();
+
+ for (int bit = minWidth - 1; bit >= 0; --bit)
+ {
+ ECPoint pow2 = pow2Table[bit];
+
+ int step = 1 << bit;
+ for (int i = step; i < n; i += (step << 1))
+ {
+ lookupTable[i] = lookupTable[i - step].add(pow2);
+ }
+ }
+
+ c.normalizeAll(lookupTable);
+
+ info.setPreComp(lookupTable);
+ info.setWidth(minWidth);
+
+ c.setPreCompInfo(p, PRECOMP_NAME, info);
+ }
+
+ return info;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/GLVMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/GLVMultiplier.java
new file mode 100644
index 0000000..09b8366
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/GLVMultiplier.java
@@ -0,0 +1,42 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.endo.GLVEndomorphism;
+
+public class GLVMultiplier extends AbstractECMultiplier
+{
+ protected final ECCurve curve;
+ protected final GLVEndomorphism glvEndomorphism;
+
+ public GLVMultiplier(ECCurve curve, GLVEndomorphism glvEndomorphism)
+ {
+ if (curve == null || curve.getOrder() == null)
+ {
+ throw new IllegalArgumentException("Need curve with known group order");
+ }
+
+ this.curve = curve;
+ this.glvEndomorphism = glvEndomorphism;
+ }
+
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ if (!curve.equals(p.getCurve()))
+ {
+ throw new IllegalStateException();
+ }
+
+ BigInteger n = p.getCurve().getOrder();
+ BigInteger[] ab = glvEndomorphism.decomposeScalar(k.mod(n));
+ BigInteger a = ab[0], b = ab[1];
+
+ ECPointMap pointMap = glvEndomorphism.getPointMap();
+ if (glvEndomorphism.hasEfficientPointMap())
+ {
+ return ECAlgorithms.implShamirsTrickWNaf(p, a, pointMap, b);
+ }
+
+ return ECAlgorithms.implShamirsTrickWNaf(p, a, pointMap.map(p), b);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java b/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java
deleted file mode 100644
index 34395a5..0000000
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java
+++ /dev/null
@@ -1,860 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import org.bouncycastle.util.Arrays;
-
-import java.math.BigInteger;
-
-class IntArray
-{
-// private static int DEINTERLEAVE_MASK = 0x55555555;
-
- /*
- * This expands 8 bit indices into 16 bit contents, by inserting 0s between bits.
- * In a binary field, this operation is the same as squaring an 8 bit number.
- */
- private static final int[] INTERLEAVE_TABLE = new int[] { 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014,
- 0x0015, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, 0x0100, 0x0101, 0x0104, 0x0105, 0x0110,
- 0x0111, 0x0114, 0x0115, 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, 0x0400, 0x0401, 0x0404,
- 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, 0x0500,
- 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554,
- 0x0555, 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, 0x1040, 0x1041, 0x1044, 0x1045, 0x1050,
- 0x1051, 0x1054, 0x1055, 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, 0x1140, 0x1141, 0x1144,
- 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, 0x1440,
- 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514,
- 0x1515, 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, 0x4000, 0x4001, 0x4004, 0x4005, 0x4010,
- 0x4011, 0x4014, 0x4015, 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, 0x4100, 0x4101, 0x4104,
- 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, 0x4400,
- 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454,
- 0x4455, 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, 0x4540, 0x4541, 0x4544, 0x4545, 0x4550,
- 0x4551, 0x4554, 0x4555, 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, 0x5040, 0x5041, 0x5044,
- 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, 0x5140,
- 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414,
- 0x5415, 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, 0x5500, 0x5501, 0x5504, 0x5505, 0x5510,
- 0x5511, 0x5514, 0x5515, 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 };
-
- // For toString(); must have length 32
- private static final String ZEROES = "00000000000000000000000000000000";
-
- private final static byte[] bitLengths =
- {
- 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
- };
-
- public static int getWordLength(int bits)
- {
- return (bits + 31) >>> 5;
- }
-
- // 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)
- {
- if (bigInt == null || bigInt.signum() < 0)
- {
- throw new IllegalArgumentException("invalid F2m field value");
- }
-
- if (bigInt.signum() == 0)
- {
- 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;
- 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] & 0xFF;
- 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++] & 0xFF;
- temp |= barrBarrI;
- }
- m_ints[iarrJ] = temp;
- }
- }
-
- public boolean isZero()
- {
- int[] a = m_ints;
- for (int i = 0; i < a.length; ++i)
- {
- if (a[i] != 0)
- {
- return false;
- }
- }
- return true;
- }
-
- public int getUsedLength()
- {
- return getUsedLengthFrom(m_ints.length);
- }
-
- public int getUsedLengthFrom(int from)
- {
- int[] a = m_ints;
- from = Math.min(from, a.length);
-
- if (from < 1)
- {
- return 0;
- }
-
- // Check if first element will act as sentinel
- if (a[0] != 0)
- {
- while (a[--from] == 0)
- {
- }
- return from + 1;
- }
-
- do
- {
- if (a[--from] != 0)
- {
- return from + 1;
- }
- }
- while (from > 0);
-
- return 0;
- }
-
- public int degree()
- {
- int i = m_ints.length, w;
- do
- {
- if (i == 0)
- {
- return 0;
- }
- w = m_ints[--i];
- }
- while (w == 0);
-
- return (i << 5) + bitLength(w);
- }
-
- private static int bitLength(int w)
- {
- int t = w >>> 16;
- if (t == 0)
- {
- t = w >>> 8;
- return (t == 0) ? bitLengths[w] : 8 + bitLengths[t];
- }
-
- int u = t >>> 8;
- return (u == 0) ? 16 + bitLengths[t] : 24 + bitLengths[u];
- }
-
- private int[] resizedInts(int newLen)
- {
- int[] newInts = new int[newLen];
- System.arraycopy(m_ints, 0, newInts, 0, Math.min(m_ints.length, newLen));
- 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);
- }
-
- private static int shiftLeft(int[] x, int count)
- {
- int prev = 0;
- for (int i = 0; i < count; ++i)
- {
- int next = x[i];
- x[i] = (next << 1) | prev;
- prev = next >>> 31;
- }
- return prev;
- }
-
- public void addOneShifted(int shift)
- {
- if (shift >= m_ints.length)
- {
- m_ints = resizedInts(shift + 1);
- }
-
- m_ints[shift] ^= 1;
- }
-
- private void addShiftedByBits(IntArray other, int bits)
- {
- int words = bits >>> 5;
- int shift = bits & 0x1F;
-
- if (shift == 0)
- {
- addShiftedByWords(other, words);
- return;
- }
-
- int otherUsedLen = other.getUsedLength();
- if (otherUsedLen == 0)
- {
- return;
- }
-
- int minLen = otherUsedLen + words + 1;
- if (minLen > m_ints.length)
- {
- m_ints = resizedInts(minLen);
- }
-
- int shiftInv = 32 - shift, prev = 0;
- for (int i = 0; i < otherUsedLen; ++i)
- {
- int next = other.m_ints[i];
- m_ints[i + words] ^= (next << shift) | prev;
- prev = next >>> shiftInv;
- }
- m_ints[otherUsedLen + words] ^= prev;
- }
-
- private static int addShiftedByBits(int[] x, int[] y, int count, int shift)
- {
- int shiftInv = 32 - shift, prev = 0;
- for (int i = 0; i < count; ++i)
- {
- int next = y[i];
- x[i] ^= (next << shift) | prev;
- prev = next >>> shiftInv;
- }
- return prev;
- }
-
- private static int addShiftedByBits(int[] x, int xOff, int[] y, int yOff, int count, int shift)
- {
- int shiftInv = 32 - shift, prev = 0;
- for (int i = 0; i < count; ++i)
- {
- int next = y[yOff + i];
- x[xOff + i] ^= (next << shift) | prev;
- prev = next >>> shiftInv;
- }
- return prev;
- }
-
- public void addShiftedByWords(IntArray other, int words)
- {
- int otherUsedLen = other.getUsedLength();
- if (otherUsedLen == 0)
- {
- return;
- }
-
- int minLen = otherUsedLen + words;
- if (minLen > m_ints.length)
- {
- m_ints = resizedInts(minLen);
- }
-
- for (int i = 0; i < otherUsedLen; i++)
- {
- m_ints[words + i] ^= other.m_ints[i];
- }
- }
-
- private static void addShiftedByWords(int[] x, int xOff, int[] y, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- x[xOff + i] ^= y[i];
- }
- }
-
- private static void add(int[] x, int[] y, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- x[i] ^= y[i];
- }
- }
-
- private static void distribute(int[] x, int dst1, int dst2, int src, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- int v = x[src + i];
- x[dst1 + i] ^= v;
- x[dst2 + i] ^= v;
- }
- }
-
- public int getLength()
- {
- return m_ints.length;
- }
-
- public void flipWord(int bit, int word)
- {
- int len = m_ints.length;
- int n = bit >>> 5;
- if (n < len)
- {
- int shift = bit & 0x1F;
- if (shift == 0)
- {
- m_ints[n] ^= word;
- }
- else
- {
- m_ints[n] ^= word << shift;
- if (++n < len)
- {
- m_ints[n] ^= word >>> (32 - shift);
- }
- }
- }
- }
-
- public int getWord(int bit)
- {
- int len = m_ints.length;
- int n = bit >>> 5;
- if (n >= len)
- {
- return 0;
- }
- int shift = bit & 0x1F;
- if (shift == 0)
- {
- return m_ints[n];
- }
- int result = m_ints[n] >>> shift;
- if (++n < len)
- {
- result |= m_ints[n] << (32 - shift);
- }
- return result;
- }
-
- public boolean testBitZero()
- {
- return m_ints.length > 0 && (m_ints[0] & 1) != 0;
- }
-
- 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 void clearBit(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)
- {
- int aLen = getUsedLength();
- if (aLen == 0)
- {
- return new IntArray(1);
- }
-
- int bLen = other.getUsedLength();
- if (bLen == 0)
- {
- return new IntArray(1);
- }
-
- IntArray A = this, B = other;
- if (aLen > bLen)
- {
- A = other; B = this;
- int tmp = aLen; aLen = bLen; bLen = tmp;
- }
-
- if (aLen == 1)
- {
- int a = A.m_ints[0];
- int[] b = B.m_ints;
- int[] c = new int[aLen + bLen];
- if ((a & 1) != 0)
- {
- add(c, b, bLen);
- }
- int k = 1;
- while ((a >>>= 1) != 0)
- {
- if ((a & 1) != 0)
- {
- addShiftedByBits(c, b, bLen, k);
- }
- ++k;
- }
- return new IntArray(c);
- }
-
- // TODO It'd be better to be able to tune the width directly (need support for interleaving arbitrary widths)
- int complexity = aLen <= 8 ? 1 : 2;
-
- int width = 1 << complexity;
- int shifts = (32 >>> complexity);
-
- int bExt = bLen;
- if ((B.m_ints[bLen - 1] >>> (33 - shifts)) != 0)
- {
- ++bExt;
- }
-
- int cLen = bExt + aLen;
-
- int[] c = new int[cLen << width];
- System.arraycopy(B.m_ints, 0, c, 0, bLen);
- interleave(A.m_ints, 0, c, bExt, aLen, complexity);
-
- int[] ci = new int[1 << width];
- for (int i = 1; i < ci.length; ++i)
- {
- ci[i] = ci[i - 1] + cLen;
- }
-
- int MASK = (1 << width) - 1;
-
- int k = 0;
- for (;;)
- {
- for (int aPos = 0; aPos < aLen; ++aPos)
- {
- int index = (c[bExt + aPos] >>> k) & MASK;
- if (index != 0)
- {
- addShiftedByWords(c, aPos + ci[index], c, bExt);
- }
- }
-
- if ((k += width) >= 32)
- {
- break;
- }
-
- shiftLeft(c, bExt);
- }
-
- int ciPos = ci.length, pow2 = ciPos >>> 1, offset = 32;
- while (--ciPos > 1)
- {
- if (ciPos == pow2)
- {
- offset -= shifts;
- addShiftedByBits(c, ci[1], c, ci[pow2], cLen, offset);
- pow2 >>>= 1;
- }
- else
- {
- distribute(c, ci[pow2], ci[ciPos - pow2], ci[ciPos], cLen);
- }
- }
-
- // TODO reduce in place to avoid extra copying
- IntArray p = new IntArray(cLen);
- System.arraycopy(c, ci[1], p.m_ints, 0, cLen);
- return p;
- }
-
-// private static void deInterleave(int[] x, int xOff, int[] z, int zOff, int count, int rounds)
-// {
-// for (int i = 0; i < count; ++i)
-// {
-// z[zOff + i] = deInterleave(x[zOff + i], rounds);
-// }
-// }
-//
-// private static int deInterleave(int x, int rounds)
-// {
-// while (--rounds >= 0)
-// {
-// x = deInterleave16(x & DEINTERLEAVE_MASK) | (deInterleave16((x >>> 1) & DEINTERLEAVE_MASK) << 16);
-// }
-// return x;
-// }
-//
-// private static int deInterleave16(int x)
-// {
-// x = (x | (x >>> 1)) & 0x33333333;
-// x = (x | (x >>> 2)) & 0x0F0F0F0F;
-// x = (x | (x >>> 4)) & 0x00FF00FF;
-// x = (x | (x >>> 8)) & 0x0000FFFF;
-// return x;
-// }
-
- public void reduce(int m, int[] ks)
- {
- int len = getUsedLength();
- int mLen = (m + 31) >>> 5;
- if (len < mLen)
- {
- return;
- }
-
- int _2m = m << 1;
- int pos = Math.min(_2m - 2, (len << 5) - 1);
-
- int kMax = ks[ks.length - 1];
- if (kMax < m - 31)
- {
- reduceWordWise(pos, m, ks);
- }
- else
- {
- reduceBitWise(pos, m, ks);
- }
-
- // Instead of flipping the high bits in the loop, explicitly clear any partial word above m bits
- int partial = m & 0x1F;
- if (partial != 0)
- {
- m_ints[mLen - 1] &= (1 << partial) - 1;
- }
-
- if (len > mLen)
- {
- m_ints = resizedInts(mLen);
- }
- }
-
- private void reduceBitWise(int from, int m, int[] ks)
- {
- for (int i = from; i >= m; --i)
- {
- if (testBit(i))
- {
-// clearBit(i);
- int bit = i - m;
- flipBit(bit);
- int j = ks.length;
- while (--j >= 0)
- {
- flipBit(ks[j] + bit);
- }
- }
- }
- }
-
- private void reduceWordWise(int from, int m, int[] ks)
- {
- int pos = m + ((from - m) & ~0x1F);
- for (int i = pos; i >= m; i -= 32)
- {
- int word = getWord(i);
- if (word != 0)
- {
-// flipWord(i);
- int bit = i - m;
- flipWord(bit, word);
- int j = ks.length;
- while (--j >= 0)
- {
- flipWord(ks[j] + bit, word);
- }
- }
- }
- }
-
- public IntArray square(int m)
- {
- int len = getUsedLength();
- if (len == 0)
- {
- return this;
- }
-
- int _2len = len << 1;
- int[] r = new int[_2len];
-
- int pos = 0;
- while (pos < _2len)
- {
- int mi = m_ints[pos >>> 1];
- r[pos++] = interleave16(mi & 0xFFFF);
- r[pos++] = interleave16(mi >>> 16);
- }
-
- return new IntArray(r);
- }
-
- private static void interleave(int[] x, int xOff, int[] z, int zOff, int count, int rounds)
- {
- for (int i = 0; i < count; ++i)
- {
- z[zOff + i] = interleave(x[xOff + i], rounds);
- }
- }
-
- private static int interleave(int x, int rounds)
- {
- while (--rounds >= 0)
- {
- x = interleave16(x & 0xFFFF) | (interleave16(x >>> 16) << 1);
- }
- return x;
- }
-
- private static int interleave16(int n)
- {
- return INTERLEAVE_TABLE[n & 0xFF] | INTERLEAVE_TABLE[n >>> 8] << 16;
- }
-
- public IntArray modInverse(int m, int[] ks)
- {
- // 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)
-
- int uzDegree = degree();
- if (uzDegree == 1)
- {
- return this;
- }
-
- // u(z) := a(z)
- IntArray uz = (IntArray)clone();
-
- int t = getWordLength(m);
-
- // v(z) := f(z)
- IntArray vz = new IntArray(t);
- vz.setBit(m);
- vz.setBit(0);
- vz.setBit(ks[0]);
- if (ks.length > 1)
- {
- vz.setBit(ks[1]);
- vz.setBit(ks[2]);
- }
-
- // g1(z) := 1, g2(z) := 0
- IntArray g1z = new IntArray(t);
- g1z.setBit(0);
- IntArray g2z = new IntArray(t);
-
- while (uzDegree != 0)
- {
- // j := deg(u(z)) - deg(v(z))
- int j = uzDegree - vz.degree();
-
- // 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));
- uz.addShiftedByBits(vz, j);
- uzDegree = uz.degree();
-
- // g1(z) := g1(z) + z^j * g2(z)
-// g1z = g1z.xor(g2z.shiftLeft(j));
- if (uzDegree != 0)
- {
- g1z.addShiftedByBits(g2z, j);
- }
- }
- return g2z;
- }
-
- 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 *= 31;
- hash ^= m_ints[i];
- }
- return hash;
- }
-
- public Object clone()
- {
- return new IntArray(Arrays.clone(m_ints));
- }
-
- public String toString()
- {
- int i = getUsedLength();
- if (i == 0)
- {
- return "0";
- }
-
- StringBuffer sb = new StringBuffer(Integer.toBinaryString(m_ints[--i]));
- while (--i >= 0)
- {
- String s = Integer.toBinaryString(m_ints[i]);
-
- // Add leading zeroes, except for highest significant word
- int len = s.length();
- if (len < 32)
- {
- sb.append(ZEROES.substring(len));
- }
-
- sb.append(s);
- }
- return sb.toString();
- }
-} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java b/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java
index 7e8b172..e3069dc 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java
@@ -371,6 +371,23 @@ class LongArray
}
}
+ public boolean isOne()
+ {
+ long[] a = m_ints;
+ if (a[0] != 1L)
+ {
+ return false;
+ }
+ for (int i = 1; i < a.length; ++i)
+ {
+ if (a[i] != 0L)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
public boolean isZero()
{
long[] a = m_ints;
@@ -822,12 +839,12 @@ class LongArray
add(c, cOff, b, 0, bLen);
}
int k = 1;
- while ((a >>>= 1) != 0)
+ while ((a >>>= 1) != 0L)
{
if ((a & 1L) != 0L)
{
long carry = addShiftedUp(c, cOff, b, 0, bLen, k);
- if (carry != 0)
+ if (carry != 0L)
{
c[cOff + bLen] ^= carry;
}
@@ -871,8 +888,8 @@ class LongArray
if (aLen == 1)
{
- long a = A.m_ints[0];
- if (a == 1L)
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
{
return B;
}
@@ -880,13 +897,13 @@ class LongArray
/*
* Fast path for small A, with performance dependent only on the number of set bits
*/
- long[] c = new long[cLen];
- multiplyWord(a, B.m_ints, bLen, c, 0);
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
/*
* Reduce the raw answer against the reduction coefficients
*/
- return reduceResult(c, 0, cLen, m, ks);
+ return reduceResult(c0, 0, cLen, m, ks);
}
/*
@@ -1003,8 +1020,8 @@ class LongArray
if (aLen == 1)
{
- long a = A.m_ints[0];
- if (a == 1L)
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
{
return B;
}
@@ -1012,13 +1029,13 @@ class LongArray
/*
* Fast path for small A, with performance dependent only on the number of set bits
*/
- long[] c = new long[cLen];
- multiplyWord(a, B.m_ints, bLen, c, 0);
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
/*
* Reduce the raw answer against the reduction coefficients
*/
- return reduceResult(c, 0, cLen, m, ks);
+ return reduceResult(c0, 0, cLen, m, ks);
}
/*
@@ -1077,7 +1094,8 @@ class LongArray
aVal >>>= 4;
int v = (int)aVal & MASK;
addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
- if ((aVal >>>= 4) == 0L)
+ aVal >>>= 4;
+ if (aVal == 0L)
{
break;
}
@@ -1085,10 +1103,12 @@ class LongArray
}
}
- int cOff = c.length;
- while ((cOff -= cLen) != 0)
{
- addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
}
/*
@@ -1132,8 +1152,8 @@ class LongArray
if (aLen == 1)
{
- long a = A.m_ints[0];
- if (a == 1L)
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
{
return B;
}
@@ -1141,13 +1161,13 @@ class LongArray
/*
* Fast path for small A, with performance dependent only on the number of set bits
*/
- long[] c = new long[cLen];
- multiplyWord(a, B.m_ints, bLen, c, 0);
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
/*
* Reduce the raw answer against the reduction coefficients
*/
- return reduceResult(c, 0, cLen, m, ks);
+ return reduceResult(c0, 0, cLen, m, ks);
}
// NOTE: This works, but is slower than width 4 processing
@@ -1314,6 +1334,158 @@ class LongArray
return reduceResult(c, ci[1], cLen, m, ks);
}
+ public LongArray modReduce(int m, int[] ks)
+ {
+ long[] buf = Arrays.clone(m_ints);
+ int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
+ return new LongArray(buf, 0, rLen);
+ }
+
+ public LongArray multiply(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+// return reduceResult(c0, 0, cLen, m, ks);
+ return new LongArray(c0, 0, cLen);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen << 3];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab (Modified) algorithm
+ */
+
+ for (int aPos = 0; aPos < aLen; ++aPos)
+ {
+ long aVal = a[aPos];
+ int cOff = aPos;
+ for (;;)
+ {
+ int u = (int)aVal & MASK;
+ aVal >>>= 4;
+ int v = (int)aVal & MASK;
+ addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+ aVal >>>= 4;
+ if (aVal == 0L)
+ {
+ break;
+ }
+ cOff += cLen;
+ }
+ }
+
+ {
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+// return reduceResult(c, 0, cLen, m, ks);
+ return new LongArray(c, 0, cLen);
+ }
+
+ public void reduce(int m, int[] ks)
+ {
+ long[] buf = m_ints;
+ int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
+ if (rLen < buf.length)
+ {
+ m_ints = new long[rLen];
+ System.arraycopy(buf, 0, m_ints, 0, rLen);
+ }
+ }
+
private static LongArray reduceResult(long[] buf, int off, int len, int m, int[] ks)
{
int rLen = reduceInPlace(buf, off, len, m, ks);
@@ -1405,13 +1577,13 @@ class LongArray
private static void reduceBit(long[] buf, int off, int bit, int m, int[] ks)
{
flipBit(buf, off, bit);
- int base = bit - m;
+ int n = bit - m;
int j = ks.length;
while (--j >= 0)
{
- flipBit(buf, off, ks[j] + base);
+ flipBit(buf, off, ks[j] + n);
}
- flipBit(buf, off, base);
+ flipBit(buf, off, n);
}
private static void reduceWordWise(long[] buf, int off, int len, int toBit, int m, int[] ks)
@@ -1428,12 +1600,14 @@ class LongArray
}
}
- int partial = toBit & 0x3F;
- long word = buf[off + toPos] >>> partial;
- if (word != 0)
{
- buf[off + toPos] ^= word << partial;
- reduceWord(buf, off, toBit, word, m, ks);
+ int partial = toBit & 0x3F;
+ long word = buf[off + toPos] >>> partial;
+ if (word != 0)
+ {
+ buf[off + toPos] ^= word << partial;
+ reduceWord(buf, off, toBit, word, m, ks);
+ }
}
}
@@ -1502,37 +1676,59 @@ class LongArray
return new LongArray(r, 0, reduceInPlace(r, 0, r.length, m, ks));
}
-// private LongArray modSquareN(int n, int m, int[] ks)
-// {
-// int len = getUsedLength();
-// if (len == 0)
-// {
-// return this;
-// }
-//
-// int mLen = (m + 63) >>> 6;
-// long[] r = new long[mLen << 1];
-// System.arraycopy(m_ints, 0, r, 0, len);
-//
-// while (--n >= 0)
-// {
-// squareInPlace(r, len, m, ks);
-// len = reduceInPlace(r, 0, r.length, m, ks);
-// }
-//
-// return new LongArray(r, 0, len);
-// }
-//
-// private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
-// {
-// int pos = xLen << 1;
-// while (--xLen >= 0)
-// {
-// long xVal = x[xLen];
-// x[--pos] = interleave2_32to64((int)(xVal >>> 32));
-// x[--pos] = interleave2_32to64((int)xVal);
-// }
-// }
+ public LongArray modSquareN(int n, int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int mLen = (m + 63) >>> 6;
+ long[] r = new long[mLen << 1];
+ System.arraycopy(m_ints, 0, r, 0, len);
+
+ while (--n >= 0)
+ {
+ squareInPlace(r, len, m, ks);
+ len = reduceInPlace(r, 0, r.length, m, ks);
+ }
+
+ return new LongArray(r, 0, len);
+ }
+
+ public LongArray square(int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int _2len = len << 1;
+ long[] r = new long[_2len];
+
+ int pos = 0;
+ while (pos < _2len)
+ {
+ long mi = m_ints[pos >>> 1];
+ r[pos++] = interleave2_32to64((int)mi);
+ r[pos++] = interleave2_32to64((int)(mi >>> 32));
+ }
+
+ return new LongArray(r, 0, r.length);
+ }
+
+ private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
+ {
+ int pos = xLen << 1;
+ while (--xLen >= 0)
+ {
+ long xVal = x[xLen];
+ x[--pos] = interleave2_32to64((int)(xVal >>> 32));
+ x[--pos] = interleave2_32to64((int)xVal);
+ }
+ }
private static void interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
{
@@ -1856,6 +2052,10 @@ class LongArray
* Output: a(z)^(-1) mod f(z)
*/
int uzDegree = degree();
+ if (uzDegree == 0)
+ {
+ throw new IllegalStateException();
+ }
if (uzDegree == 1)
{
return this;
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ScaleXPointMap.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ScaleXPointMap.java
new file mode 100644
index 0000000..099f5fb
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ScaleXPointMap.java
@@ -0,0 +1,16 @@
+package org.bouncycastle.math.ec;
+
+public class ScaleXPointMap implements ECPointMap
+{
+ protected final ECFieldElement scale;
+
+ public ScaleXPointMap(ECFieldElement scale)
+ {
+ this.scale = scale;
+ }
+
+ public ECPoint map(ECPoint p)
+ {
+ return p.scaleX(scale);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java b/bcprov/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java
index 96e666d..229fae4 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/SimpleBigDecimal.java
@@ -54,12 +54,6 @@ class SimpleBigDecimal
this.scale = scale;
}
- private SimpleBigDecimal(SimpleBigDecimal limBigDec)
- {
- bigInt = limBigDec.bigInt;
- scale = limBigDec.scale;
- }
-
private void checkScale(SimpleBigDecimal b)
{
if (scale != b.scale)
@@ -78,7 +72,7 @@ class SimpleBigDecimal
if (newScale == scale)
{
- return new SimpleBigDecimal(this);
+ return this;
}
return new SimpleBigDecimal(bigInt.shiftLeft(newScale - scale),
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java b/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java
index 42d6738..236bbc8 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java
@@ -535,45 +535,36 @@ class Tnaf
int m = curve.getM();
int a = curve.getA().toBigInteger().intValue();
byte mu = curve.getMu();
- int h = curve.getH().intValue();
+ int shifts = getShiftsForCofactor(curve.getCofactor());
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");
+ ui[0] = ui[0].negate();
+ ui[1] = ui[1].negate();
}
- BigInteger[] si = new BigInteger[2];
+ BigInteger dividend0 = ECConstants.ONE.add(ui[1]).shiftRight(shifts);
+ BigInteger dividend1 = ECConstants.ONE.add(ui[0]).shiftRight(shifts).negate();
- 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
+ return new BigInteger[] { dividend0, dividend1 };
+ }
+
+ protected static int getShiftsForCofactor(BigInteger h)
+ {
+ if (h != null)
{
- throw new IllegalArgumentException("h (Cofactor) must be 2 or 4");
+ if (h.equals(ECConstants.TWO))
+ {
+ return 1;
+ }
+ if (h.equals(ECConstants.FOUR))
+ {
+ return 2;
+ }
}
- return si;
+ throw new IllegalArgumentException("h (Cofactor) must be 2 or 4");
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java
index 59a9313..90b0847 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java
@@ -31,7 +31,7 @@ public class WNafL2RMultiplier extends AbstractECMultiplier
int i = wnaf.length;
/*
- * NOTE This code optimizes the first window using the precomputed points to substitute an
+ * NOTE: We try to optimize the first window using the precomputed points to substitute an
* addition for 2 or more doublings.
*/
if (i > 1)
@@ -42,19 +42,14 @@ public class WNafL2RMultiplier extends AbstractECMultiplier
int n = Math.abs(digit);
ECPoint[] table = digit < 0 ? preCompNeg : preComp;
- /*
- * NOTE: We use this optimization conservatively, since some coordinate systems have
- * significantly cheaper doubling relative to addition.
- *
- * (n << 2) selects precomputed values in the lower half of the table
- * (n << 3) selects precomputed values in the lower quarter of the table
- */
- //if ((n << 2) < (1 << width))
- if ((n << 3) < (1 << width))
+ // Optimization can only be used for values in the lower half of the table
+ if ((n << 2) < (1 << width))
{
int highest = LongArray.bitLengths[n];
- int lowBits = n ^ (1 << (highest - 1));
+
+ // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting?
int scale = width - highest;
+ int lowBits = n ^ (1 << (highest - 1));
int i1 = ((1 << (width - 1)) - 1);
int i2 = (lowBits << scale) + 1;
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
index d142ab7..e8f16e6 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
@@ -10,47 +10,47 @@ public class WNafPreCompInfo implements PreCompInfo
* Array holding the precomputed <code>ECPoint</code>s used for a Window
* NAF multiplication.
*/
- private ECPoint[] preComp = null;
+ protected ECPoint[] preComp = null;
/**
* Array holding the negations of the precomputed <code>ECPoint</code>s used
* for a Window NAF multiplication.
*/
- private ECPoint[] preCompNeg = null;
+ protected ECPoint[] preCompNeg = null;
/**
* Holds an <code>ECPoint</code> representing twice(this). Used for the
* Window NAF multiplication to create or extend the precomputed values.
*/
- private ECPoint twiceP = null;
+ protected ECPoint twice = null;
- protected ECPoint[] getPreComp()
+ public ECPoint[] getPreComp()
{
return preComp;
}
- protected ECPoint[] getPreCompNeg()
+ public void setPreComp(ECPoint[] preComp)
{
- return preCompNeg;
+ this.preComp = preComp;
}
- protected void setPreComp(ECPoint[] preComp)
+ public ECPoint[] getPreCompNeg()
{
- this.preComp = preComp;
+ return preCompNeg;
}
- protected void setPreCompNeg(ECPoint[] preCompNeg)
+ public void setPreCompNeg(ECPoint[] preCompNeg)
{
this.preCompNeg = preCompNeg;
}
- protected ECPoint getTwiceP()
+ public ECPoint getTwice()
{
- return twiceP;
+ return twice;
}
- protected void setTwiceP(ECPoint twiceP)
+ public void setTwice(ECPoint twice)
{
- this.twiceP = twiceP;
+ this.twice = twice;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
index 6465d66..7ac3160 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
@@ -4,7 +4,12 @@ import java.math.BigInteger;
public abstract class WNafUtil
{
- private static int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
+ public static final String PRECOMP_NAME = "bc_wnaf";
+
+ private static final int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
+
+ private static final byte[] EMPTY_BYTES = new byte[0];
+ private static final int[] EMPTY_INTS = new int[0];
public static int[] generateCompactNaf(BigInteger k)
{
@@ -12,30 +17,35 @@ public abstract class WNafUtil
{
throw new IllegalArgumentException("'k' must have bitlength < 2^16");
}
+ if (k.signum() == 0)
+ {
+ return EMPTY_INTS;
+ }
BigInteger _3k = k.shiftLeft(1).add(k);
- int digits = _3k.bitLength() - 1;
- int[] naf = new int[(digits + 1) >> 1];
+ int bits = _3k.bitLength();
+ int[] naf = new int[bits >> 1];
- int length = 0, zeroes = 0;
- for (int i = 1; i <= digits; ++i)
- {
- boolean _3kBit = _3k.testBit(i);
- boolean kBit = k.testBit(i);
+ BigInteger diff = _3k.xor(k);
- if (_3kBit == kBit)
+ int highBit = bits - 1, length = 0, zeroes = 0;
+ for (int i = 1; i < highBit; ++i)
+ {
+ if (!diff.testBit(i))
{
++zeroes;
+ continue;
}
- else
- {
- int digit = kBit ? -1 : 1;
- naf[length++] = (digit << 16) | zeroes;
- zeroes = 0;
- }
+
+ int digit = k.testBit(i) ? -1 : 1;
+ naf[length++] = (digit << 16) | zeroes;
+ zeroes = 1;
+ ++i;
}
+ naf[length++] = (1 << 16) | zeroes;
+
if (naf.length > length)
{
naf = trim(naf, length);
@@ -59,6 +69,10 @@ public abstract class WNafUtil
{
throw new IllegalArgumentException("'k' must have bitlength < 2^16");
}
+ if (k.signum() == 0)
+ {
+ return EMPTY_INTS;
+ }
int[] wnaf = new int[k.bitLength() / width + 1];
@@ -114,9 +128,10 @@ public abstract class WNafUtil
BigInteger k0 = g, k1 = h;
int j = 0, d0 = 0, d1 = 0;
- while (k0.signum() > 0 || k1.signum() > 0 || d0 > 0 || d1 > 0)
+ int offset = 0;
+ while ((d0 | d1) != 0 || k0.bitLength() > offset || k1.bitLength() > offset)
{
- int n0 = (k0.intValue() + d0) & 7, n1 = (k1.intValue() + d1) & 7;
+ int n0 = ((k0.intValue() >>> offset) + d0) & 7, n1 = ((k1.intValue() >>> offset) + d1) & 7;
int u0 = n0 & 1;
if (u0 != 0)
@@ -140,15 +155,19 @@ public abstract class WNafUtil
if ((d0 << 1) == 1 + u0)
{
- d0 = 1 - d0;
+ d0 ^= 1;
}
if ((d1 << 1) == 1 + u1)
{
- d1 = 1 - d1;
+ d1 ^= 1;
}
- k0 = k0.shiftRight(1);
- k1 = k1.shiftRight(1);
+ if (++offset == 30)
+ {
+ offset = 0;
+ k0 = k0.shiftRight(30);
+ k1 = k1.shiftRight(30);
+ }
jsf[j++] = (byte)((u0 << 4) | (u1 & 0xF));
}
@@ -164,19 +183,29 @@ public abstract class WNafUtil
public static byte[] generateNaf(BigInteger k)
{
+ if (k.signum() == 0)
+ {
+ return EMPTY_BYTES;
+ }
+
BigInteger _3k = k.shiftLeft(1).add(k);
int digits = _3k.bitLength() - 1;
byte[] naf = new byte[digits];
- for (int i = 1; i <= digits; ++i)
- {
- boolean _3kBit = _3k.testBit(i);
- boolean kBit = k.testBit(i);
+ BigInteger diff = _3k.xor(k);
- naf[i - 1] = (byte)(_3kBit == kBit ? 0 : kBit ? -1 : 1);
+ for (int i = 1; i < digits; ++i)
+ {
+ if (diff.testBit(i))
+ {
+ naf[i - 1] = (byte)(k.testBit(i) ? -1 : 1);
+ ++i;
+ }
}
+ naf[digits - 1] = 1;
+
return naf;
}
@@ -203,6 +232,10 @@ public abstract class WNafUtil
{
throw new IllegalArgumentException("'width' must be in the range [2, 8]");
}
+ if (k.signum() == 0)
+ {
+ return EMPTY_BYTES;
+ }
byte[] wnaf = new byte[k.bitLength() + 1];
@@ -250,6 +283,24 @@ public abstract class WNafUtil
return wnaf;
}
+ public static int getNafWeight(BigInteger k)
+ {
+ if (k.signum() == 0)
+ {
+ return 0;
+ }
+
+ BigInteger _3k = k.shiftLeft(1).add(k);
+ BigInteger diff = _3k.xor(k);
+
+ return diff.bitCount();
+ }
+
+ public static WNafPreCompInfo getWNafPreCompInfo(ECPoint p)
+ {
+ return getWNafPreCompInfo(p.getCurve().getPreCompInfo(p, PRECOMP_NAME));
+ }
+
public static WNafPreCompInfo getWNafPreCompInfo(PreCompInfo preCompInfo)
{
if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
@@ -291,10 +342,49 @@ public abstract class WNafUtil
return w + 2;
}
+ public static ECPoint mapPointWithPrecomp(ECPoint p, int width, boolean includeNegated,
+ ECPointMap pointMap)
+ {
+ ECCurve c = p.getCurve();
+ WNafPreCompInfo wnafPreCompP = precompute(p, width, includeNegated);
+
+ ECPoint q = pointMap.map(p);
+ WNafPreCompInfo wnafPreCompQ = getWNafPreCompInfo(c.getPreCompInfo(q, PRECOMP_NAME));
+
+ ECPoint twiceP = wnafPreCompP.getTwice();
+ if (twiceP != null)
+ {
+ ECPoint twiceQ = pointMap.map(twiceP);
+ wnafPreCompQ.setTwice(twiceQ);
+ }
+
+ ECPoint[] preCompP = wnafPreCompP.getPreComp();
+ ECPoint[] preCompQ = new ECPoint[preCompP.length];
+ for (int i = 0; i < preCompP.length; ++i)
+ {
+ preCompQ[i] = pointMap.map(preCompP[i]);
+ }
+ wnafPreCompQ.setPreComp(preCompQ);
+
+ if (includeNegated)
+ {
+ ECPoint[] preCompNegQ = new ECPoint[preCompQ.length];
+ for (int i = 0; i < preCompNegQ.length; ++i)
+ {
+ preCompNegQ[i] = preCompQ[i].negate();
+ }
+ wnafPreCompQ.setPreCompNeg(preCompNegQ);
+ }
+
+ c.setPreCompInfo(q, PRECOMP_NAME, wnafPreCompQ);
+
+ return q;
+ }
+
public static WNafPreCompInfo precompute(ECPoint p, int width, boolean includeNegated)
{
ECCurve c = p.getCurve();
- WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p));
+ WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME));
ECPoint[] preComp = wnafPreCompInfo.getPreComp();
if (preComp == null)
@@ -307,26 +397,28 @@ public abstract class WNafUtil
if (preCompLen < reqPreCompLen)
{
- ECPoint twiceP = wnafPreCompInfo.getTwiceP();
- if (twiceP == null)
+ preComp = resizeTable(preComp, reqPreCompLen);
+ if (reqPreCompLen == 2)
{
- twiceP = preComp[0].twice().normalize();
- wnafPreCompInfo.setTwiceP(twiceP);
+ preComp[1] = preComp[0].threeTimes();
}
-
- preComp = resizeTable(preComp, reqPreCompLen);
-
- /*
- * TODO Okeya/Sakurai paper has precomputation trick and "Montgomery's Trick" to speed this up.
- * Also, co-Z arithmetic could avoid the subsequent normalization too.
- */
- for (int i = preCompLen; i < reqPreCompLen; i++)
+ else
{
- /*
- * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ...,
- * 2^(width-1)-1 times p are computed
- */
- preComp[i] = twiceP.add(preComp[i - 1]);
+ ECPoint twiceP = wnafPreCompInfo.getTwice();
+ if (twiceP == null)
+ {
+ twiceP = preComp[0].twice();
+ wnafPreCompInfo.setTwice(twiceP);
+ }
+
+ for (int i = preCompLen; i < reqPreCompLen; i++)
+ {
+ /*
+ * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ...,
+ * 2^(width-1)-1 times p are computed
+ */
+ preComp[i] = twiceP.add(preComp[i - 1]);
+ }
}
/*
@@ -365,7 +457,7 @@ public abstract class WNafUtil
wnafPreCompInfo.setPreCompNeg(preCompNeg);
}
- c.setPreCompInfo(p, wnafPreCompInfo);
+ c.setPreCompInfo(p, PRECOMP_NAME, wnafPreCompInfo);
return wnafPreCompInfo;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
index 7bd30ec..93d03b4 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
@@ -8,6 +8,9 @@ import java.math.BigInteger;
*/
public class WTauNafMultiplier extends AbstractECMultiplier
{
+ // TODO Create WTauNafUtil class and move various functionality into it
+ static final String PRECOMP_NAME = "bc_wtnaf";
+
/**
* Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
* by <code>k</code> using the reduced <code>&tau;</code>-adic NAF (RTNAF)
@@ -33,7 +36,7 @@ public class WTauNafMultiplier extends AbstractECMultiplier
ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10);
- return multiplyWTnaf(p, rho, curve.getPreCompInfo(p), a, mu);
+ return multiplyWTnaf(p, rho, curve.getPreCompInfo(p, PRECOMP_NAME), a, mu);
}
/**
@@ -49,21 +52,12 @@ public class WTauNafMultiplier extends AbstractECMultiplier
private ECPoint.F2m multiplyWTnaf(ECPoint.F2m p, ZTauElement lambda,
PreCompInfo preCompInfo, byte a, byte mu)
{
- ZTauElement[] alpha;
- if (a == 0)
- {
- alpha = Tnaf.alpha0;
- }
- else
- {
- // a == 1
- alpha = Tnaf.alpha1;
- }
+ ZTauElement[] alpha = (a == 0) ? Tnaf.alpha0 : Tnaf.alpha1;
BigInteger tw = Tnaf.getTw(mu, Tnaf.WIDTH);
byte[]u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH,
- BigInteger.valueOf(Tnaf.POW_2_WIDTH), tw, alpha);
+ BigInteger.valueOf(Tnaf.POW_2_WIDTH), tw, alpha);
return multiplyFromWTnaf(p, u, preCompInfo);
}
@@ -77,8 +71,7 @@ public class WTauNafMultiplier extends AbstractECMultiplier
* @param u The the WTNAF of <code>&lambda;</code>..
* @return <code>&lambda; * p</code>
*/
- private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u,
- PreCompInfo preCompInfo)
+ private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u, PreCompInfo preCompInfo)
{
ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
byte a = curve.getA().toBigInteger().byteValue();
@@ -87,7 +80,10 @@ public class WTauNafMultiplier extends AbstractECMultiplier
if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo))
{
pu = Tnaf.getPreComp(p, a);
- curve.setPreCompInfo(p, new WTauNafPreCompInfo(pu));
+
+ WTauNafPreCompInfo pre = new WTauNafPreCompInfo();
+ pre.setPreComp(pu);
+ curve.setPreCompInfo(p, PRECOMP_NAME, pre);
}
else
{
@@ -99,16 +95,16 @@ public class WTauNafMultiplier extends AbstractECMultiplier
for (int i = u.length - 1; i >= 0; i--)
{
q = Tnaf.tau(q);
- if (u[i] != 0)
+ byte ui = u[i];
+ if (ui != 0)
{
- if (u[i] > 0)
+ if (ui > 0)
{
- q = q.addSimple(pu[u[i]]);
+ q = q.addSimple(pu[ui]);
}
else
{
- // u[i] < 0
- q = q.subtractSimple(pu[-u[i]]);
+ q = q.subtractSimple(pu[-ui]);
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java
index d7c583f..190eecb 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafPreCompInfo.java
@@ -4,7 +4,7 @@ package org.bouncycastle.math.ec;
* Class holding precomputation data for the WTNAF (Window
* <code>&tau;</code>-adic Non-Adjacent Form) algorithm.
*/
-class WTauNafPreCompInfo implements PreCompInfo
+public class WTauNafPreCompInfo implements PreCompInfo
{
/**
* Array holding the precomputed <code>ECPoint.F2m</code>s used for the
@@ -12,28 +12,15 @@ class WTauNafPreCompInfo implements PreCompInfo
* {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
* WTauNafMultiplier.multiply()}</code>.
*/
- private ECPoint.F2m[] preComp = null;
+ protected ECPoint.F2m[] preComp = null;
- /**
- * Constructor for <code>WTauNafPreCompInfo</code>
- * @param preComp Array holding the precomputed <code>ECPoint.F2m</code>s
- * used for the WTNAF multiplication in <code>
- * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
- * WTauNafMultiplier.multiply()}</code>.
- */
- WTauNafPreCompInfo(ECPoint.F2m[] preComp)
+ public ECPoint.F2m[] getPreComp()
{
- this.preComp = preComp;
+ return preComp;
}
- /**
- * @return the array holding the precomputed <code>ECPoint.F2m</code>s
- * used for the WTNAF multiplication in <code>
- * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
- * WTauNafMultiplier.multiply()}</code>.
- */
- protected ECPoint.F2m[] getPreComp()
+ public void setPreComp(ECPoint.F2m[] preComp)
{
- return preComp;
+ this.preComp = preComp;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java
new file mode 100644
index 0000000..b46cba6
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java
@@ -0,0 +1,79 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECConstants;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.encoders.Hex;
+
+public class SecP192K1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"));
+
+ private static final int SecP192K1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP192K1Point infinity;
+
+ public SecP192K1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP192K1Point(this, null, null);
+
+ this.a = fromBigInteger(ECConstants.ZERO);
+ this.b = fromBigInteger(BigInteger.valueOf(3));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP192K1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP192K1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP192K1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP192K1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP192K1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Field.java
new file mode 100644
index 0000000..1a0bde8
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Field.java
@@ -0,0 +1,177 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat192;
+
+public class SecP192K1Field
+{
+ // 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
+ static final int[] P = new int[]{ 0xFFFFEE37, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x013C4FD1, 0x00002392, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0xFFFFDC6E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFEC3B02F, 0xFFFFDC6D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0x00002391, 0x00000002 };
+ private static final int P5 = 0xFFFFFFFF;
+ private static final int PExt11 = 0xFFFFFFFF;
+ private static final int PInv33 = 0x11C9;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat192.add(x, y, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(12, xx, yy, zz);
+ if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(6, x, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat192.fromBigInteger(x);
+ if (z[5] == P5 && Nat192.gte(z, P))
+ {
+ Nat192.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(6, x, 0, z);
+ }
+ else
+ {
+ int c = Nat192.add(x, P, z);
+ Nat.shiftDownBit(6, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat192.createExt();
+ Nat192.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat192.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat192.isZero(x))
+ {
+ Nat192.zero(z);
+ }
+ else
+ {
+ Nat192.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long cc = Nat192.mul33Add(PInv33, xx, 6, xx, 0, z, 0);
+ int c = Nat192.mul33DWordAdd(PInv33, cc, z, 0);
+
+ // assert c == 0L || c == 1L;
+
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ if ((x != 0 && Nat192.mul33WordAdd(PInv33, x, z, 0) != 0)
+ || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat192.createExt();
+ Nat192.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat192.createExt();
+ Nat192.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat192.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat192.sub(x, y, z);
+ if (c != 0)
+ {
+ Nat.sub33From(6, PInv33, z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(12, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(6, x, 0, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ Nat.add33To(6, PInv33, z);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java
new file mode 100644
index 0000000..0032f35
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java
@@ -0,0 +1,213 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.raw.Mod;
+import org.bouncycastle.math.raw.Nat192;
+import org.bouncycastle.util.Arrays;
+
+public class SecP192K1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP192K1Curve.q;
+
+ protected int[] x;
+
+ public SecP192K1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP192K1FieldElement");
+ }
+
+ this.x = SecP192K1Field.fromBigInteger(x);
+ }
+
+ public SecP192K1FieldElement()
+ {
+ this.x = Nat192.create();
+ }
+
+ protected SecP192K1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat192.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat192.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat192.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat192.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP192K1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.add(x, ((SecP192K1FieldElement)b).x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.addOne(x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.subtract(x, ((SecP192K1FieldElement)b).x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.multiply(x, ((SecP192K1FieldElement)b).x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat192.create();
+ Mod.invert(SecP192K1Field.P, ((SecP192K1FieldElement)b).x, z);
+ SecP192K1Field.multiply(z, x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.negate(x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat192.create();
+ SecP192K1Field.square(x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP192K1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat192.create();
+ Mod.invert(SecP192K1Field.P, x, z);
+ return new SecP192K1FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ /*
+ * Raise this element to the exponent 2^190 - 2^30 - 2^10 - 2^6 - 2^5 - 2^4 - 2^1
+ *
+ * Breaking up the exponent's binary representation into "repunits", we get:
+ * { 159 1s } { 1 0s } { 19 1s } { 1 0s } { 3 1s } { 3 0s} { 3 1s } { 1 0s }
+ *
+ * Therefore we need an addition chain containing 3, 19, 159 (the lengths of the repunits)
+ * We use: 1, 2, [3], 6, 8, 16, [19], 35, 70, 140, [159]
+ */
+
+ int[] x1 = this.x;
+ if (Nat192.isZero(x1) || Nat192.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] x2 = Nat192.create();
+ SecP192K1Field.square(x1, x2);
+ SecP192K1Field.multiply(x2, x1, x2);
+ int[] x3 = Nat192.create();
+ SecP192K1Field.square(x2, x3);
+ SecP192K1Field.multiply(x3, x1, x3);
+ int[] x6 = Nat192.create();
+ SecP192K1Field.squareN(x3, 3, x6);
+ SecP192K1Field.multiply(x6, x3, x6);
+ int[] x8 = x6;
+ SecP192K1Field.squareN(x6, 2, x8);
+ SecP192K1Field.multiply(x8, x2, x8);
+ int[] x16 = x2;
+ SecP192K1Field.squareN(x8, 8, x16);
+ SecP192K1Field.multiply(x16, x8, x16);
+ int[] x19 = x8;
+ SecP192K1Field.squareN(x16, 3, x19);
+ SecP192K1Field.multiply(x19, x3, x19);
+ int[] x35 = Nat192.create();
+ SecP192K1Field.squareN(x19, 16, x35);
+ SecP192K1Field.multiply(x35, x16, x35);
+ int[] x70 = x16;
+ SecP192K1Field.squareN(x35, 35, x70);
+ SecP192K1Field.multiply(x70, x35, x70);
+ int[] x140 = x35;
+ SecP192K1Field.squareN(x70, 70, x140);
+ SecP192K1Field.multiply(x140, x70, x140);
+ int[] x159 = x70;
+ SecP192K1Field.squareN(x140, 19, x159);
+ SecP192K1Field.multiply(x159, x19, x159);
+
+ int[] t1 = x159;
+ SecP192K1Field.squareN(t1, 20, t1);
+ SecP192K1Field.multiply(t1, x19, t1);
+ SecP192K1Field.squareN(t1, 4, t1);
+ SecP192K1Field.multiply(t1, x3, t1);
+ SecP192K1Field.squareN(t1, 6, t1);
+ SecP192K1Field.multiply(t1, x3, t1);
+ SecP192K1Field.square(t1, t1);
+
+ int[] t2 = x3;
+ SecP192K1Field.square(t1, t2);
+
+ return Nat192.eq(x1, t2) ? new SecP192K1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP192K1FieldElement))
+ {
+ return false;
+ }
+
+ SecP192K1FieldElement o = (SecP192K1FieldElement)other;
+ return Nat192.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 6);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java
new file mode 100644
index 0000000..eaa9727
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Point.java
@@ -0,0 +1,298 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat192;
+
+public class SecP192K1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ 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
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
+ boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP192K1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.x, Y1 = (SecP192K1FieldElement)this.y;
+ SecP192K1FieldElement X2 = (SecP192K1FieldElement)b.getXCoord(), Y2 = (SecP192K1FieldElement)b.getYCoord();
+
+ SecP192K1FieldElement Z1 = (SecP192K1FieldElement)this.zs[0];
+ SecP192K1FieldElement Z2 = (SecP192K1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat192.createExt();
+ int[] t2 = Nat192.create();
+ int[] t3 = Nat192.create();
+ int[] t4 = Nat192.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP192K1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP192K1Field.multiply(S2, X2.x, U2);
+
+ SecP192K1Field.multiply(S2, Z1.x, S2);
+ SecP192K1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP192K1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP192K1Field.multiply(S1, X1.x, U1);
+
+ SecP192K1Field.multiply(S1, Z2.x, S1);
+ SecP192K1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat192.create();
+ SecP192K1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP192K1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat192.isZero(H))
+ {
+ if (Nat192.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP192K1Field.square(H, HSquared);
+
+ int[] G = Nat192.create();
+ SecP192K1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP192K1Field.multiply(HSquared, U1, V);
+
+ SecP192K1Field.negate(G, G);
+ Nat192.mul(S1, G, tt1);
+
+ c = Nat192.addBothTo(V, V, G);
+ SecP192K1Field.reduce32(c, G);
+
+ SecP192K1FieldElement X3 = new SecP192K1FieldElement(t4);
+ SecP192K1Field.square(R, X3.x);
+ SecP192K1Field.subtract(X3.x, G, X3.x);
+
+ SecP192K1FieldElement Y3 = new SecP192K1FieldElement(G);
+ SecP192K1Field.subtract(V, X3.x, Y3.x);
+ SecP192K1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP192K1Field.reduce(tt1, Y3.x);
+
+ SecP192K1FieldElement Z3 = new SecP192K1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP192K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP192K1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+ return new SecP192K1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP192K1FieldElement Y1 = (SecP192K1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.x, Z1 = (SecP192K1FieldElement)this.zs[0];
+
+ int c;
+
+ int[] Y1Squared = Nat192.create();
+ SecP192K1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat192.create();
+ SecP192K1Field.square(Y1Squared, T);
+
+ int[] M = Nat192.create();
+ SecP192K1Field.square(X1.x, M);
+ c = Nat192.addBothTo(M, M, M);
+ SecP192K1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP192K1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(6, S, 2, 0);
+ SecP192K1Field.reduce32(c, S);
+
+ int[] t1 = Nat192.create();
+ c = Nat.shiftUpBits(6, T, 3, 0, t1);
+ SecP192K1Field.reduce32(c, t1);
+
+ SecP192K1FieldElement X3 = new SecP192K1FieldElement(T);
+ SecP192K1Field.square(M, X3.x);
+ SecP192K1Field.subtract(X3.x, S, X3.x);
+ SecP192K1Field.subtract(X3.x, S, X3.x);
+
+ SecP192K1FieldElement Y3 = new SecP192K1FieldElement(S);
+ SecP192K1Field.subtract(S, X3.x, Y3.x);
+ SecP192K1Field.multiply(Y3.x, M, Y3.x);
+ SecP192K1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP192K1FieldElement Z3 = new SecP192K1FieldElement(M);
+ SecP192K1Field.twice(Y1.x, Z3.x);
+ if (!Z1.isOne())
+ {
+ SecP192K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP192K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP192K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java
new file mode 100644
index 0000000..be67100
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.encoders.Hex;
+
+public class SecP192R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"));
+
+ private static final int SecP192R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP192R1Point infinity;
+
+ public SecP192R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP192R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP192R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP192R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP192R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP192R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP192R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java
new file mode 100644
index 0000000..c8f5eed
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Field.java
@@ -0,0 +1,286 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat192;
+
+public class SecP192R1Field
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ // 2^192 - 2^64 - 1
+ static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
+ 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFE,
+ 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000002 };
+ private static final int P5 = 0xFFFFFFFF;
+ private static final int PExt11 = 0xFFFFFFFF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat192.add(x, y, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(12, xx, yy, zz);
+ if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(6, x, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat192.fromBigInteger(x);
+ if (z[5] == P5 && Nat192.gte(z, P))
+ {
+ Nat192.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(6, x, 0, z);
+ }
+ else
+ {
+ int c = Nat192.add(x, P, z);
+ Nat.shiftDownBit(6, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat192.createExt();
+ Nat192.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat192.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat192.isZero(x))
+ {
+ Nat192.zero(z);
+ }
+ else
+ {
+ Nat192.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long xx06 = xx[6] & M, xx07 = xx[7] & M, xx08 = xx[8] & M;
+ long xx09 = xx[9] & M, xx10 = xx[10] & M, xx11 = xx[11] & M;
+
+ long t0 = xx06 + xx10;
+ long t1 = xx07 + xx11;
+
+ long cc = 0;
+ cc += (xx[0] & M) + t0;
+ int z0 = (int)cc;
+ cc >>= 32;
+ cc += (xx[1] & M) + t1;
+ z[1] = (int)cc;
+ cc >>= 32;
+
+ t0 += xx08;
+ t1 += xx09;
+
+ cc += (xx[2] & M) + t0;
+ long z2 = cc & M;
+ cc >>= 32;
+ cc += (xx[3] & M) + t1;
+ z[3] = (int)cc;
+ cc >>= 32;
+
+ t0 -= xx06;
+ t1 -= xx07;
+
+ cc += (xx[4] & M) + t0;
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (xx[5] & M) + t1;
+ z[5] = (int)cc;
+ cc >>= 32;
+
+ z2 += cc;
+
+ cc += (z0 & M);
+ z[0] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ z2 += cc >> 32;
+ }
+ z[2] = (int)z2;
+ cc = z2 >> 32;
+
+// assert cc == 0 || cc == 1;
+
+ if ((cc != 0 && Nat.incAt(6, z, 3) != 0)
+ || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ long cc = 0;
+
+ if (x != 0)
+ {
+ long xx06 = x & M;
+
+ cc += (z[0] & M) + xx06;
+ z[0] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[2] & M) + xx06;
+ z[2] = (int)cc;
+ cc >>= 32;
+
+// assert cc == 0 || cc == 1;
+ }
+
+ if ((cc != 0 && Nat.incAt(6, z, 3) != 0)
+ || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat192.createExt();
+ Nat192.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat192.createExt();
+ Nat192.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat192.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat192.sub(x, y, z);
+ if (c != 0)
+ {
+ subPInvFrom(z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(12, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(12, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(6, x, 0, z);
+ if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ private static void addPInvTo(int[] z)
+ {
+ long c = (z[0] & M) + 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ }
+ c += (z[2] & M) + 1;
+ z[2] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.incAt(6, z, 3);
+ }
+ }
+
+ private static void subPInvFrom(int[] z)
+ {
+ long c = (z[0] & M) - 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ }
+ c += (z[2] & M) - 1;
+ z[2] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.decAt(6, z, 3);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1FieldElement.java
new file mode 100644
index 0000000..68c8080
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1FieldElement.java
@@ -0,0 +1,190 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.raw.Mod;
+import org.bouncycastle.math.raw.Nat192;
+import org.bouncycastle.util.Arrays;
+
+public class SecP192R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP192R1Curve.q;
+
+ protected int[] x;
+
+ public SecP192R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP192R1FieldElement");
+ }
+
+ this.x = SecP192R1Field.fromBigInteger(x);
+ }
+
+ public SecP192R1FieldElement()
+ {
+ this.x = Nat192.create();
+ }
+
+ protected SecP192R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat192.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat192.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat192.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat192.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP192R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.add(x, ((SecP192R1FieldElement)b).x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.addOne(x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.subtract(x, ((SecP192R1FieldElement)b).x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.multiply(x, ((SecP192R1FieldElement)b).x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat192.create();
+ Mod.invert(SecP192R1Field.P, ((SecP192R1FieldElement)b).x, z);
+ SecP192R1Field.multiply(z, x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.negate(x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat192.create();
+ SecP192R1Field.square(x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP192R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat192.create();
+ Mod.invert(SecP192R1Field.P, x, z);
+ return new SecP192R1FieldElement(z);
+ }
+
+ // 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()
+ {
+ // Raise this element to the exponent 2^190 - 2^62
+
+ int[] x1 = this.x;
+ if (Nat192.isZero(x1) || Nat192.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] t1 = Nat192.create();
+ int[] t2 = Nat192.create();
+
+ SecP192R1Field.square(x1, t1);
+ SecP192R1Field.multiply(t1, x1, t1);
+
+ SecP192R1Field.squareN(t1, 2, t2);
+ SecP192R1Field.multiply(t2, t1, t2);
+
+ SecP192R1Field.squareN(t2, 4, t1);
+ SecP192R1Field.multiply(t1, t2, t1);
+
+ SecP192R1Field.squareN(t1, 8, t2);
+ SecP192R1Field.multiply(t2, t1, t2);
+
+ SecP192R1Field.squareN(t2, 16, t1);
+ SecP192R1Field.multiply(t1, t2, t1);
+
+ SecP192R1Field.squareN(t1, 32, t2);
+ SecP192R1Field.multiply(t2, t1, t2);
+
+ SecP192R1Field.squareN(t2, 64, t1);
+ SecP192R1Field.multiply(t1, t2, t1);
+
+ SecP192R1Field.squareN(t1, 62, t1);
+ SecP192R1Field.square(t1, t2);
+
+ return Nat192.eq(x1, t2) ? new SecP192R1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP192R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP192R1FieldElement o = (SecP192R1FieldElement)other;
+ return Nat192.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 6);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java
new file mode 100644
index 0000000..3ed72f8
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Point.java
@@ -0,0 +1,310 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat192;
+
+public class SecP192R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ 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
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP192R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Y1 = (SecP192R1FieldElement)this.y;
+ SecP192R1FieldElement X2 = (SecP192R1FieldElement)b.getXCoord(), Y2 = (SecP192R1FieldElement)b.getYCoord();
+
+ SecP192R1FieldElement Z1 = (SecP192R1FieldElement)this.zs[0];
+ SecP192R1FieldElement Z2 = (SecP192R1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat192.createExt();
+ int[] t2 = Nat192.create();
+ int[] t3 = Nat192.create();
+ int[] t4 = Nat192.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP192R1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP192R1Field.multiply(S2, X2.x, U2);
+
+ SecP192R1Field.multiply(S2, Z1.x, S2);
+ SecP192R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP192R1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP192R1Field.multiply(S1, X1.x, U1);
+
+ SecP192R1Field.multiply(S1, Z2.x, S1);
+ SecP192R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat192.create();
+ SecP192R1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP192R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat192.isZero(H))
+ {
+ if (Nat192.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP192R1Field.square(H, HSquared);
+
+ int[] G = Nat192.create();
+ SecP192R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP192R1Field.multiply(HSquared, U1, V);
+
+ SecP192R1Field.negate(G, G);
+ Nat192.mul(S1, G, tt1);
+
+ c = Nat192.addBothTo(V, V, G);
+ SecP192R1Field.reduce32(c, G);
+
+ SecP192R1FieldElement X3 = new SecP192R1FieldElement(t4);
+ SecP192R1Field.square(R, X3.x);
+ SecP192R1Field.subtract(X3.x, G, X3.x);
+
+ SecP192R1FieldElement Y3 = new SecP192R1FieldElement(G);
+ SecP192R1Field.subtract(V, X3.x, Y3.x);
+ SecP192R1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP192R1Field.reduce(tt1, Y3.x);
+
+ SecP192R1FieldElement Z3 = new SecP192R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP192R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP192R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP192R1FieldElement Y1 = (SecP192R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Z1 = (SecP192R1FieldElement)this.zs[0];
+
+ int c;
+ int[] t1 = Nat192.create();
+ int[] t2 = Nat192.create();
+
+ int[] Y1Squared = Nat192.create();
+ SecP192R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat192.create();
+ SecP192R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP192R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP192R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP192R1Field.add(X1.x, Z1Squared, M);
+ SecP192R1Field.multiply(M, t1, M);
+ c = Nat192.addBothTo(M, M, M);
+ SecP192R1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP192R1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(6, S, 2, 0);
+ SecP192R1Field.reduce32(c, S);
+
+ c = Nat.shiftUpBits(6, T, 3, 0, t1);
+ SecP192R1Field.reduce32(c, t1);
+
+ SecP192R1FieldElement X3 = new SecP192R1FieldElement(T);
+ SecP192R1Field.square(M, X3.x);
+ SecP192R1Field.subtract(X3.x, S, X3.x);
+ SecP192R1Field.subtract(X3.x, S, X3.x);
+
+ SecP192R1FieldElement Y3 = new SecP192R1FieldElement(S);
+ SecP192R1Field.subtract(S, X3.x, Y3.x);
+ SecP192R1Field.multiply(Y3.x, M, Y3.x);
+ SecP192R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP192R1FieldElement Z3 = new SecP192R1FieldElement(M);
+ SecP192R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP192R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP192R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java
new file mode 100644
index 0000000..ad733da
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java
@@ -0,0 +1,78 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECConstants;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.encoders.Hex;
+
+public class SecP224K1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D"));
+
+ private static final int SECP224K1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP224K1Point infinity;
+
+ public SecP224K1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP224K1Point(this, null, null);
+
+ this.a = fromBigInteger(ECConstants.ZERO);
+ this.b = fromBigInteger(BigInteger.valueOf(5));
+ this.order = new BigInteger(1, Hex.decode("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"));
+ this.cofactor = BigInteger.valueOf(1);
+ this.coord = SECP224K1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP224K1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP224K1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP224K1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP224K1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Field.java
new file mode 100644
index 0000000..0146fec
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Field.java
@@ -0,0 +1,178 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat224;
+
+public class SecP224K1Field
+{
+ // 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1
+ static final int[] P = new int[]{ 0xFFFFE56D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x02C23069, 0x00003526, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xFFFFCADA, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFD3DCF97, 0xFFFFCAD9, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00003525, 0x00000002 };
+ private static final int P6 = 0xFFFFFFFF;
+ private static final int PExt13 = 0xFFFFFFFF;
+ private static final int PInv33 = 0x1A93;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat224.add(x, y, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(14, xx, yy, zz);
+ if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(7, x, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat224.fromBigInteger(x);
+ if (z[6] == P6 && Nat224.gte(z, P))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(7, x, 0, z);
+ }
+ else
+ {
+ int c = Nat224.add(x, P, z);
+ Nat.shiftDownBit(7, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat224.createExt();
+ Nat224.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat224.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat224.isZero(x))
+ {
+ Nat224.zero(z);
+ }
+ else
+ {
+ Nat224.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long cc = Nat224.mul33Add(PInv33, xx, 7, xx, 0, z, 0);
+ int c = Nat224.mul33DWordAdd(PInv33, cc, z, 0);
+
+ // assert c == 0L || c == 1L;
+
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ if ((x != 0 && Nat224.mul33WordAdd(PInv33, x, z, 0) != 0)
+ || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat224.createExt();
+ Nat224.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat224.createExt();
+ Nat224.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat224.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat224.sub(x, y, z);
+ if (c != 0)
+ {
+ Nat.sub33From(7, PInv33, z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(14, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(7, x, 0, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ Nat.add33To(7, PInv33, z);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java
new file mode 100644
index 0000000..73f1999
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java
@@ -0,0 +1,243 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.raw.Mod;
+import org.bouncycastle.math.raw.Nat224;
+import org.bouncycastle.util.Arrays;
+
+public class SecP224K1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP224K1Curve.q;
+
+ // Calculated as ECConstants.TWO.modPow(Q.shiftRight(2), Q)
+ private static final int[] PRECOMP_POW2 = new int[]{ 0x33bfd202, 0xdcfad133, 0x2287624a, 0xc3811ba8,
+ 0xa85558fc, 0x1eaef5d7, 0x8edf154c };
+
+ protected int[] x;
+
+ public SecP224K1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP224K1FieldElement");
+ }
+
+ this.x = SecP224K1Field.fromBigInteger(x);
+ }
+
+ public SecP224K1FieldElement()
+ {
+ this.x = Nat224.create();
+ }
+
+ protected SecP224K1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat224.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat224.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat224.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat224.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP224K1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.add(x, ((SecP224K1FieldElement)b).x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.addOne(x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.subtract(x, ((SecP224K1FieldElement)b).x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.multiply(x, ((SecP224K1FieldElement)b).x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat224.create();
+ Mod.invert(SecP224K1Field.P, ((SecP224K1FieldElement)b).x, z);
+ SecP224K1Field.multiply(z, x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.negate(x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat224.create();
+ SecP224K1Field.square(x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP224K1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat224.create();
+ Mod.invert(SecP224K1Field.P, x, z);
+ return new SecP224K1FieldElement(z);
+ }
+
+ // 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()
+ {
+ /*
+ * Q == 8m + 5, so we use Pocklington's method for this case.
+ *
+ * First, raise this element to the exponent 2^221 - 2^29 - 2^9 - 2^8 - 2^6 - 2^4 - 2^1 (i.e. m + 1)
+ *
+ * Breaking up the exponent's binary representation into "repunits", we get:
+ * { 191 1s } { 1 0s } { 19 1s } { 2 0s } { 1 1s } { 1 0s} { 1 1s } { 1 0s} { 3 1s } { 1 0s}
+ *
+ * Therefore we need an addition chain containing 1, 3, 19, 191 (the lengths of the repunits)
+ * We use: [1], 2, [3], 4, 8, 11, [19], 23, 42, 84, 107, [191]
+ */
+
+ int[] x1 = this.x;
+ if (Nat224.isZero(x1) || Nat224.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] x2 = Nat224.create();
+ SecP224K1Field.square(x1, x2);
+ SecP224K1Field.multiply(x2, x1, x2);
+ int[] x3 = x2;
+ SecP224K1Field.square(x2, x3);
+ SecP224K1Field.multiply(x3, x1, x3);
+ int[] x4 = Nat224.create();
+ SecP224K1Field.square(x3, x4);
+ SecP224K1Field.multiply(x4, x1, x4);
+ int[] x8 = Nat224.create();
+ SecP224K1Field.squareN(x4, 4, x8);
+ SecP224K1Field.multiply(x8, x4, x8);
+ int[] x11 = Nat224.create();
+ SecP224K1Field.squareN(x8, 3, x11);
+ SecP224K1Field.multiply(x11, x3, x11);
+ int[] x19 = x11;
+ SecP224K1Field.squareN(x11, 8, x19);
+ SecP224K1Field.multiply(x19, x8, x19);
+ int[] x23 = x8;
+ SecP224K1Field.squareN(x19, 4, x23);
+ SecP224K1Field.multiply(x23, x4, x23);
+ int[] x42 = x4;
+ SecP224K1Field.squareN(x23, 19, x42);
+ SecP224K1Field.multiply(x42, x19, x42);
+ int[] x84 = Nat224.create();
+ SecP224K1Field.squareN(x42, 42, x84);
+ SecP224K1Field.multiply(x84, x42, x84);
+ int[] x107 = x42;
+ SecP224K1Field.squareN(x84, 23, x107);
+ SecP224K1Field.multiply(x107, x23, x107);
+ int[] x191 = x23;
+ SecP224K1Field.squareN(x107, 84, x191);
+ SecP224K1Field.multiply(x191, x84, x191);
+
+ int[] t1 = x191;
+ SecP224K1Field.squareN(t1, 20, t1);
+ SecP224K1Field.multiply(t1, x19, t1);
+ SecP224K1Field.squareN(t1, 3, t1);
+ SecP224K1Field.multiply(t1, x1, t1);
+ SecP224K1Field.squareN(t1, 2, t1);
+ SecP224K1Field.multiply(t1, x1, t1);
+ SecP224K1Field.squareN(t1, 4, t1);
+ SecP224K1Field.multiply(t1, x3, t1);
+ SecP224K1Field.square(t1, t1);
+
+ int[] t2 = x84;
+ SecP224K1Field.square(t1, t2);
+
+ if (Nat224.eq(x1, t2))
+ {
+ return new SecP224K1FieldElement(t1);
+ }
+
+ /*
+ * If the first guess is incorrect, we multiply by a precomputed power of 2 to get the second guess,
+ * which is ((4x)^(m + 1))/2 mod Q
+ */
+ SecP224K1Field.multiply(t1, PRECOMP_POW2, t1);
+
+ SecP224K1Field.square(t1, t2);
+
+ if (Nat224.eq(x1, t2))
+ {
+ return new SecP224K1FieldElement(t1);
+ }
+
+ return null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP224K1FieldElement))
+ {
+ return false;
+ }
+
+ SecP224K1FieldElement o = (SecP224K1FieldElement)other;
+ return Nat224.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 7);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java
new file mode 100644
index 0000000..114623d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Point.java
@@ -0,0 +1,298 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat224;
+
+public class SecP224K1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ 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
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
+ boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP224K1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.x, Y1 = (SecP224K1FieldElement)this.y;
+ SecP224K1FieldElement X2 = (SecP224K1FieldElement)b.getXCoord(), Y2 = (SecP224K1FieldElement)b.getYCoord();
+
+ SecP224K1FieldElement Z1 = (SecP224K1FieldElement)this.zs[0];
+ SecP224K1FieldElement Z2 = (SecP224K1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat224.createExt();
+ int[] t2 = Nat224.create();
+ int[] t3 = Nat224.create();
+ int[] t4 = Nat224.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP224K1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP224K1Field.multiply(S2, X2.x, U2);
+
+ SecP224K1Field.multiply(S2, Z1.x, S2);
+ SecP224K1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP224K1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP224K1Field.multiply(S1, X1.x, U1);
+
+ SecP224K1Field.multiply(S1, Z2.x, S1);
+ SecP224K1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat224.create();
+ SecP224K1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP224K1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat224.isZero(H))
+ {
+ if (Nat224.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP224K1Field.square(H, HSquared);
+
+ int[] G = Nat224.create();
+ SecP224K1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP224K1Field.multiply(HSquared, U1, V);
+
+ SecP224K1Field.negate(G, G);
+ Nat224.mul(S1, G, tt1);
+
+ c = Nat224.addBothTo(V, V, G);
+ SecP224K1Field.reduce32(c, G);
+
+ SecP224K1FieldElement X3 = new SecP224K1FieldElement(t4);
+ SecP224K1Field.square(R, X3.x);
+ SecP224K1Field.subtract(X3.x, G, X3.x);
+
+ SecP224K1FieldElement Y3 = new SecP224K1FieldElement(G);
+ SecP224K1Field.subtract(V, X3.x, Y3.x);
+ SecP224K1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP224K1Field.reduce(tt1, Y3.x);
+
+ SecP224K1FieldElement Z3 = new SecP224K1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP224K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP224K1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+ return new SecP224K1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP224K1FieldElement Y1 = (SecP224K1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.x, Z1 = (SecP224K1FieldElement)this.zs[0];
+
+ int c;
+
+ int[] Y1Squared = Nat224.create();
+ SecP224K1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat224.create();
+ SecP224K1Field.square(Y1Squared, T);
+
+ int[] M = Nat224.create();
+ SecP224K1Field.square(X1.x, M);
+ c = Nat224.addBothTo(M, M, M);
+ SecP224K1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP224K1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(7, S, 2, 0);
+ SecP224K1Field.reduce32(c, S);
+
+ int[] t1 = Nat224.create();
+ c = Nat.shiftUpBits(7, T, 3, 0, t1);
+ SecP224K1Field.reduce32(c, t1);
+
+ SecP224K1FieldElement X3 = new SecP224K1FieldElement(T);
+ SecP224K1Field.square(M, X3.x);
+ SecP224K1Field.subtract(X3.x, S, X3.x);
+ SecP224K1Field.subtract(X3.x, S, X3.x);
+
+ SecP224K1FieldElement Y3 = new SecP224K1FieldElement(S);
+ SecP224K1Field.subtract(S, X3.x, Y3.x);
+ SecP224K1Field.multiply(Y3.x, M, Y3.x);
+ SecP224K1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP224K1FieldElement Z3 = new SecP224K1FieldElement(M);
+ SecP224K1Field.twice(Y1.x, Z3.x);
+ if (!Z1.isOne())
+ {
+ SecP224K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP224K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP224K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java
new file mode 100644
index 0000000..c844329
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.encoders.Hex;
+
+public class SecP224R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"));
+
+ private static final int SecP224R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP224R1Point infinity;
+
+ public SecP224R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP224R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP224R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP224R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP224R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP224R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP224R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java
new file mode 100644
index 0000000..02a86f0
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Field.java
@@ -0,0 +1,298 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat224;
+
+public class SecP224R1Field
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ // 2^224 - 2^96 + 1
+ static final int[] P = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0x00000000,
+ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001 };
+ private static final int P6 = 0xFFFFFFFF;
+ private static final int PExt13 = 0xFFFFFFFF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat224.add(x, y, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(14, xx, yy, zz);
+ if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(7, x, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat224.fromBigInteger(x);
+ if (z[6] == P6 && Nat224.gte(z, P))
+ {
+ Nat224.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(7, x, 0, z);
+ }
+ else
+ {
+ int c = Nat224.add(x, P, z);
+ Nat.shiftDownBit(7, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat224.createExt();
+ Nat224.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat224.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat224.isZero(x))
+ {
+ Nat224.zero(z);
+ }
+ else
+ {
+ Nat224.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long xx10 = xx[10] & M, xx11 = xx[11] & M, xx12 = xx[12] & M, xx13 = xx[13] & M;
+
+ final long n = 1;
+
+ long t0 = (xx[7] & M) + xx11 - n;
+ long t1 = (xx[8] & M) + xx12;
+ long t2 = (xx[9] & M) + xx13;
+
+ long cc = 0;
+ cc += (xx[0] & M) - t0;
+ long z0 = cc & M;
+ cc >>= 32;
+ cc += (xx[1] & M) - t1;
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (xx[2] & M) - t2;
+ z[2] = (int)cc;
+ cc >>= 32;
+ cc += (xx[3] & M) + t0 - xx10;
+ long z3 = cc & M;
+ cc >>= 32;
+ cc += (xx[4] & M) + t1 - xx11;
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (xx[5] & M) + t2 - xx12;
+ z[5] = (int)cc;
+ cc >>= 32;
+ cc += (xx[6] & M) + xx10 - xx13;
+ z[6] = (int)cc;
+ cc >>= 32;
+ cc += n;
+
+// assert cc >= 0;
+
+ z3 += cc;
+
+ z0 -= cc;
+ z[0] = (int)z0;
+ cc = z0 >> 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (z[2] & M);
+ z[2] = (int)cc;
+ z3 += cc >> 32;
+ }
+ z[3] = (int)z3;
+ cc = z3 >> 32;
+
+// assert cc == 0 || cc == 1;
+
+ if ((cc != 0 && Nat.incAt(7, z, 4) != 0)
+ || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ long cc = 0;
+
+ if (x != 0)
+ {
+ long xx07 = x & M;
+
+ cc += (z[0] & M) - xx07;
+ z[0] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (z[2] & M);
+ z[2] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[3] & M) + xx07;
+ z[3] = (int)cc;
+ cc >>= 32;
+
+// assert cc == 0 || cc == 1;
+ }
+
+ if ((cc != 0 && Nat.incAt(7, z, 4) != 0)
+ || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat224.createExt();
+ Nat224.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat224.createExt();
+ Nat224.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat224.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat224.sub(x, y, z);
+ if (c != 0)
+ {
+ subPInvFrom(z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(14, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(14, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(7, x, 0, z);
+ if (c != 0 || (z[6] == P6 && Nat224.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ private static void addPInvTo(int[] z)
+ {
+ long c = (z[0] & M) - 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) + 1;
+ z[3] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.incAt(7, z, 4);
+ }
+ }
+
+ private static void subPInvFrom(int[] z)
+ {
+ long c = (z[0] & M) + 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) - 1;
+ z[3] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.decAt(7, z, 4);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1FieldElement.java
new file mode 100644
index 0000000..4a28f3d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1FieldElement.java
@@ -0,0 +1,273 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.raw.Mod;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat224;
+import org.bouncycastle.util.Arrays;
+
+public class SecP224R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP224R1Curve.q;
+
+ protected int[] x;
+
+ public SecP224R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP224R1FieldElement");
+ }
+
+ this.x = SecP224R1Field.fromBigInteger(x);
+ }
+
+ public SecP224R1FieldElement()
+ {
+ this.x = Nat224.create();
+ }
+
+ protected SecP224R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat224.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat224.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat224.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat224.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP224R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.add(x, ((SecP224R1FieldElement)b).x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.addOne(x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.subtract(x, ((SecP224R1FieldElement)b).x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.multiply(x, ((SecP224R1FieldElement)b).x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat224.create();
+ Mod.invert(SecP224R1Field.P, ((SecP224R1FieldElement)b).x, z);
+ SecP224R1Field.multiply(z, x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.negate(x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat224.create();
+ SecP224R1Field.square(x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP224R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat224.create();
+ Mod.invert(SecP224R1Field.P, x, z);
+ return new SecP224R1FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ int[] c = this.x;
+ if (Nat224.isZero(c) || Nat224.isOne(c))
+ {
+ return this;
+ }
+
+ int[] nc = Nat224.create();
+ SecP224R1Field.negate(c, nc);
+
+ int[] r = Mod.random(SecP224R1Field.P);
+ int[] t = Nat224.create();
+
+ if (!isSquare(c))
+ {
+ return null;
+ }
+
+ while (!trySqrt(nc, r, t))
+ {
+ SecP224R1Field.addOne(r, r);
+ }
+
+ SecP224R1Field.square(t, r);
+
+ return Nat224.eq(c, r) ? new SecP224R1FieldElement(t) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP224R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP224R1FieldElement o = (SecP224R1FieldElement)other;
+ return Nat224.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 7);
+ }
+
+ private static boolean isSquare(int[] x)
+ {
+ int[] t1 = Nat224.create();
+ int[] t2 = Nat224.create();
+ Nat224.copy(x, t1);
+
+ for (int i = 0; i < 7; ++i)
+ {
+ Nat224.copy(t1, t2);
+ SecP224R1Field.squareN(t1, 1 << i, t1);
+ SecP224R1Field.multiply(t1, t2, t1);
+ }
+
+ SecP224R1Field.squareN(t1, 95, t1);
+ return Nat224.isOne(t1);
+ }
+
+ private static void RM(int[] nc, int[] d0, int[] e0, int[] d1, int[] e1, int[] f1, int[] t)
+ {
+ SecP224R1Field.multiply(e1, e0, t);
+ SecP224R1Field.multiply(t, nc, t);
+ SecP224R1Field.multiply(d1, d0, f1);
+ SecP224R1Field.add(f1, t, f1);
+ SecP224R1Field.multiply(d1, e0, t);
+ Nat224.copy(f1, d1);
+ SecP224R1Field.multiply(e1, d0, e1);
+ SecP224R1Field.add(e1, t, e1);
+ SecP224R1Field.square(e1, f1);
+ SecP224R1Field.multiply(f1, nc, f1);
+ }
+
+ private static void RP(int[] nc, int[] d1, int[] e1, int[] f1, int[] t)
+ {
+ Nat224.copy(nc, f1);
+
+ int[] d0 = Nat224.create();
+ int[] e0 = Nat224.create();
+
+ for (int i = 0; i < 7; ++i)
+ {
+ Nat224.copy(d1, d0);
+ Nat224.copy(e1, e0);
+
+ int j = 1 << i;
+ while (--j >= 0)
+ {
+ RS(d1, e1, f1, t);
+ }
+
+ RM(nc, d0, e0, d1, e1, f1, t);
+ }
+ }
+
+ private static void RS(int[] d, int[] e, int[] f, int[] t)
+ {
+ SecP224R1Field.multiply(e, d, e);
+ SecP224R1Field.twice(e, e);
+ SecP224R1Field.square(d, t);
+ SecP224R1Field.add(f, t, d);
+ SecP224R1Field.multiply(f, t, f);
+ int c = Nat.shiftUpBits(7, f, 2, 0);
+ SecP224R1Field.reduce32(c, f);
+ }
+
+ private static boolean trySqrt(int[] nc, int[] r, int[] t)
+ {
+ int[] d1 = Nat224.create();
+ Nat224.copy(r, d1);
+ int[] e1 = Nat224.create();
+ e1[0] = 1;
+ int[] f1 = Nat224.create();
+ RP(nc, d1, e1, f1, t);
+
+ int[] d0 = Nat224.create();
+ int[] e0 = Nat224.create();
+
+ for (int k = 1; k < 96; ++k)
+ {
+ Nat224.copy(d1, d0);
+ Nat224.copy(e1, e0);
+
+ RS(d1, e1, f1, t);
+
+ if (Nat224.isZero(d1))
+ {
+ Mod.invert(SecP224R1Field.P, e0, t);
+ SecP224R1Field.multiply(t, d0, t);
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java
new file mode 100644
index 0000000..df10b9b
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Point.java
@@ -0,0 +1,308 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat224;
+
+public class SecP224R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ 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
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP224R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.x, Y1 = (SecP224R1FieldElement)this.y;
+ SecP224R1FieldElement X2 = (SecP224R1FieldElement)b.getXCoord(), Y2 = (SecP224R1FieldElement)b.getYCoord();
+
+ SecP224R1FieldElement Z1 = (SecP224R1FieldElement)this.zs[0];
+ SecP224R1FieldElement Z2 = (SecP224R1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat224.createExt();
+ int[] t2 = Nat224.create();
+ int[] t3 = Nat224.create();
+ int[] t4 = Nat224.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP224R1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP224R1Field.multiply(S2, X2.x, U2);
+
+ SecP224R1Field.multiply(S2, Z1.x, S2);
+ SecP224R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP224R1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP224R1Field.multiply(S1, X1.x, U1);
+
+ SecP224R1Field.multiply(S1, Z2.x, S1);
+ SecP224R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat224.create();
+ SecP224R1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP224R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat224.isZero(H))
+ {
+ if (Nat224.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP224R1Field.square(H, HSquared);
+
+ int[] G = Nat224.create();
+ SecP224R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP224R1Field.multiply(HSquared, U1, V);
+
+ SecP224R1Field.negate(G, G);
+ Nat224.mul(S1, G, tt1);
+
+ c = Nat224.addBothTo(V, V, G);
+ SecP224R1Field.reduce32(c, G);
+
+ SecP224R1FieldElement X3 = new SecP224R1FieldElement(t4);
+ SecP224R1Field.square(R, X3.x);
+ SecP224R1Field.subtract(X3.x, G, X3.x);
+
+ SecP224R1FieldElement Y3 = new SecP224R1FieldElement(G);
+ SecP224R1Field.subtract(V, X3.x, Y3.x);
+ SecP224R1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP224R1Field.reduce(tt1, Y3.x);
+
+ SecP224R1FieldElement Z3 = new SecP224R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP224R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP224R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP224R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP224R1FieldElement Y1 = (SecP224R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.x, Z1 = (SecP224R1FieldElement)this.zs[0];
+
+ int c;
+ int[] t1 = Nat224.create();
+ int[] t2 = Nat224.create();
+
+ int[] Y1Squared = Nat224.create();
+ SecP224R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat224.create();
+ SecP224R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP224R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP224R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP224R1Field.add(X1.x, Z1Squared, M);
+ SecP224R1Field.multiply(M, t1, M);
+ c = Nat224.addBothTo(M, M, M);
+ SecP224R1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP224R1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(7, S, 2, 0);
+ SecP224R1Field.reduce32(c, S);
+
+ c = Nat.shiftUpBits(7, T, 3, 0, t1);
+ SecP224R1Field.reduce32(c, t1);
+
+ SecP224R1FieldElement X3 = new SecP224R1FieldElement(T);
+ SecP224R1Field.square(M, X3.x);
+ SecP224R1Field.subtract(X3.x, S, X3.x);
+ SecP224R1Field.subtract(X3.x, S, X3.x);
+
+ SecP224R1FieldElement Y3 = new SecP224R1FieldElement(S);
+ SecP224R1Field.subtract(S, X3.x, Y3.x);
+ SecP224R1Field.multiply(Y3.x, M, Y3.x);
+ SecP224R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP224R1FieldElement Z3 = new SecP224R1FieldElement(M);
+ SecP224R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP224R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP224R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP224R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java
new file mode 100644
index 0000000..9b88576
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java
@@ -0,0 +1,78 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECConstants;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.encoders.Hex;
+
+public class SecP256K1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"));
+
+ private static final int SECP256K1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP256K1Point infinity;
+
+ public SecP256K1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP256K1Point(this, null, null);
+
+ this.a = fromBigInteger(ECConstants.ZERO);
+ this.b = fromBigInteger(BigInteger.valueOf(7));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"));
+ this.cofactor = BigInteger.valueOf(1);
+ this.coord = SECP256K1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP256K1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP256K1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP256K1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP256K1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java
new file mode 100644
index 0000000..c7b4def
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Field.java
@@ -0,0 +1,179 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat256;
+
+public class SecP256K1Field
+{
+ // 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+ static final int[] P = new int[]{ 0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x000E90A1, 0x000007A2, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xFFFFF85E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFFF16F5F, 0xFFFFF85D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000007A1, 0x00000002 };
+ private static final int P7 = 0xFFFFFFFF;
+ private static final int PExt15 = 0xFFFFFFFF;
+ private static final int PInv33 = 0x3D1;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat256.add(x, y, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(16, xx, yy, zz);
+ if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(16, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(8, x, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat256.fromBigInteger(x);
+ if (z[7] == P7 && Nat256.gte(z, P))
+ {
+ Nat256.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(8, x, 0, z);
+ }
+ else
+ {
+ int c = Nat256.add(x, P, z);
+ Nat.shiftDownBit(8, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat256.mulAddTo(x, y, zz);
+ if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(16, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat256.isZero(x))
+ {
+ Nat256.zero(z);
+ }
+ else
+ {
+ Nat256.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long cc = Nat256.mul33Add(PInv33, xx, 8, xx, 0, z, 0);
+ int c = Nat256.mul33DWordAdd(PInv33, cc, z, 0);
+
+ // assert c == 0L || c == 1L;
+
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ if ((x != 0 && Nat256.mul33WordAdd(PInv33, x, z, 0) != 0)
+ || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat256.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat256.sub(x, y, z);
+ if (c != 0)
+ {
+ Nat.sub33From(8, PInv33, z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(16, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(16, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(8, x, 0, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ Nat.add33To(8, PInv33, z);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java
new file mode 100644
index 0000000..0f7e295
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java
@@ -0,0 +1,215 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.raw.Mod;
+import org.bouncycastle.math.raw.Nat256;
+import org.bouncycastle.util.Arrays;
+
+public class SecP256K1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP256K1Curve.q;
+
+ protected int[] x;
+
+ public SecP256K1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP256K1FieldElement");
+ }
+
+ this.x = SecP256K1Field.fromBigInteger(x);
+ }
+
+ public SecP256K1FieldElement()
+ {
+ this.x = Nat256.create();
+ }
+
+ protected SecP256K1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat256.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat256.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat256.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat256.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP256K1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.add(x, ((SecP256K1FieldElement)b).x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.addOne(x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.subtract(x, ((SecP256K1FieldElement)b).x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.multiply(x, ((SecP256K1FieldElement)b).x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat256.create();
+ Mod.invert(SecP256K1Field.P, ((SecP256K1FieldElement)b).x, z);
+ SecP256K1Field.multiply(z, x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.negate(x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat256.create();
+ SecP256K1Field.square(x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP256K1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat256.create();
+ Mod.invert(SecP256K1Field.P, x, z);
+ return new SecP256K1FieldElement(z);
+ }
+
+ // 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()
+ {
+ /*
+ * Raise this element to the exponent 2^254 - 2^30 - 2^7 - 2^6 - 2^5 - 2^4 - 2^2
+ *
+ * Breaking up the exponent's binary representation into "repunits", we get:
+ * { 223 1s } { 1 0s } { 22 1s } { 4 0s } { 2 1s } { 2 0s}
+ *
+ * Therefore we need an addition chain containing 2, 22, 223 (the lengths of the repunits)
+ * We use: 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
+ */
+
+ int[] x1 = this.x;
+ if (Nat256.isZero(x1) || Nat256.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] x2 = Nat256.create();
+ SecP256K1Field.square(x1, x2);
+ SecP256K1Field.multiply(x2, x1, x2);
+ int[] x3 = Nat256.create();
+ SecP256K1Field.square(x2, x3);
+ SecP256K1Field.multiply(x3, x1, x3);
+ int[] x6 = Nat256.create();
+ SecP256K1Field.squareN(x3, 3, x6);
+ SecP256K1Field.multiply(x6, x3, x6);
+ int[] x9 = x6;
+ SecP256K1Field.squareN(x6, 3, x9);
+ SecP256K1Field.multiply(x9, x3, x9);
+ int[] x11 = x9;
+ SecP256K1Field.squareN(x9, 2, x11);
+ SecP256K1Field.multiply(x11, x2, x11);
+ int[] x22 = Nat256.create();
+ SecP256K1Field.squareN(x11, 11, x22);
+ SecP256K1Field.multiply(x22, x11, x22);
+ int[] x44 = x11;
+ SecP256K1Field.squareN(x22, 22, x44);
+ SecP256K1Field.multiply(x44, x22, x44);
+ int[] x88 = Nat256.create();
+ SecP256K1Field.squareN(x44, 44, x88);
+ SecP256K1Field.multiply(x88, x44, x88);
+ int[] x176 = Nat256.create();
+ SecP256K1Field.squareN(x88, 88, x176);
+ SecP256K1Field.multiply(x176, x88, x176);
+ int[] x220 = x88;
+ SecP256K1Field.squareN(x176, 44, x220);
+ SecP256K1Field.multiply(x220, x44, x220);
+ int[] x223 = x44;
+ SecP256K1Field.squareN(x220, 3, x223);
+ SecP256K1Field.multiply(x223, x3, x223);
+
+ int[] t1 = x223;
+ SecP256K1Field.squareN(t1, 23, t1);
+ SecP256K1Field.multiply(t1, x22, t1);
+ SecP256K1Field.squareN(t1, 6, t1);
+ SecP256K1Field.multiply(t1, x2, t1);
+ SecP256K1Field.squareN(t1, 2, t1);
+
+ int[] t2 = x2;
+ SecP256K1Field.square(t1, t2);
+
+ return Nat256.eq(x1, t2) ? new SecP256K1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP256K1FieldElement))
+ {
+ return false;
+ }
+
+ SecP256K1FieldElement o = (SecP256K1FieldElement)other;
+ return Nat256.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 8);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java
new file mode 100644
index 0000000..f57b200
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Point.java
@@ -0,0 +1,298 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat256;
+
+public class SecP256K1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ 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
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
+ boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP256K1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.x, Y1 = (SecP256K1FieldElement)this.y;
+ SecP256K1FieldElement X2 = (SecP256K1FieldElement)b.getXCoord(), Y2 = (SecP256K1FieldElement)b.getYCoord();
+
+ SecP256K1FieldElement Z1 = (SecP256K1FieldElement)this.zs[0];
+ SecP256K1FieldElement Z2 = (SecP256K1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat256.createExt();
+ int[] t2 = Nat256.create();
+ int[] t3 = Nat256.create();
+ int[] t4 = Nat256.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP256K1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP256K1Field.multiply(S2, X2.x, U2);
+
+ SecP256K1Field.multiply(S2, Z1.x, S2);
+ SecP256K1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP256K1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP256K1Field.multiply(S1, X1.x, U1);
+
+ SecP256K1Field.multiply(S1, Z2.x, S1);
+ SecP256K1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat256.create();
+ SecP256K1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP256K1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat256.isZero(H))
+ {
+ if (Nat256.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP256K1Field.square(H, HSquared);
+
+ int[] G = Nat256.create();
+ SecP256K1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP256K1Field.multiply(HSquared, U1, V);
+
+ SecP256K1Field.negate(G, G);
+ Nat256.mul(S1, G, tt1);
+
+ c = Nat256.addBothTo(V, V, G);
+ SecP256K1Field.reduce32(c, G);
+
+ SecP256K1FieldElement X3 = new SecP256K1FieldElement(t4);
+ SecP256K1Field.square(R, X3.x);
+ SecP256K1Field.subtract(X3.x, G, X3.x);
+
+ SecP256K1FieldElement Y3 = new SecP256K1FieldElement(G);
+ SecP256K1Field.subtract(V, X3.x, Y3.x);
+ SecP256K1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP256K1Field.reduce(tt1, Y3.x);
+
+ SecP256K1FieldElement Z3 = new SecP256K1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP256K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP256K1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+ return new SecP256K1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP256K1FieldElement Y1 = (SecP256K1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.x, Z1 = (SecP256K1FieldElement)this.zs[0];
+
+ int c;
+
+ int[] Y1Squared = Nat256.create();
+ SecP256K1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat256.create();
+ SecP256K1Field.square(Y1Squared, T);
+
+ int[] M = Nat256.create();
+ SecP256K1Field.square(X1.x, M);
+ c = Nat256.addBothTo(M, M, M);
+ SecP256K1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP256K1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(8, S, 2, 0);
+ SecP256K1Field.reduce32(c, S);
+
+ int[] t1 = Nat256.create();
+ c = Nat.shiftUpBits(8, T, 3, 0, t1);
+ SecP256K1Field.reduce32(c, t1);
+
+ SecP256K1FieldElement X3 = new SecP256K1FieldElement(T);
+ SecP256K1Field.square(M, X3.x);
+ SecP256K1Field.subtract(X3.x, S, X3.x);
+ SecP256K1Field.subtract(X3.x, S, X3.x);
+
+ SecP256K1FieldElement Y3 = new SecP256K1FieldElement(S);
+ SecP256K1Field.subtract(S, X3.x, Y3.x);
+ SecP256K1Field.multiply(Y3.x, M, Y3.x);
+ SecP256K1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP256K1FieldElement Z3 = new SecP256K1FieldElement(M);
+ SecP256K1Field.twice(Y1.x, Z3.x);
+ if (!Z1.isOne())
+ {
+ SecP256K1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP256K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP256K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java
new file mode 100644
index 0000000..5ff6a38
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.encoders.Hex;
+
+public class SecP256R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"));
+
+ private static final int SecP256R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP256R1Point infinity;
+
+ public SecP256R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP256R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP256R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP256R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP256R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP256R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP256R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java
new file mode 100644
index 0000000..985cb0e
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java
@@ -0,0 +1,312 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat256;
+
+public class SecP256R1Field
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ // 2^256 - 2^224 + 2^192 + 2^96 - 1
+ static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000001, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0x00000001, 0xFFFFFFFE,
+ 0x00000002, 0xFFFFFFFE };
+ private static final int P7 = 0xFFFFFFFF;
+ private static final int PExt15 = 0xFFFFFFFF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat256.add(x, y, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(16, xx, yy, zz);
+ if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt)))
+ {
+ Nat.subFrom(16, PExt, zz);
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(8, x, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat256.fromBigInteger(x);
+ if (z[7] == P7 && Nat256.gte(z, P))
+ {
+ Nat256.subFrom(P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(8, x, 0, z);
+ }
+ else
+ {
+ int c = Nat256.add(x, P, z);
+ Nat.shiftDownBit(8, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
+ {
+ int c = Nat256.mulAddTo(x, y, zz);
+ if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt)))
+ {
+ Nat.subFrom(16, PExt, zz);
+ }
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat256.isZero(x))
+ {
+ Nat256.zero(z);
+ }
+ else
+ {
+ Nat256.sub(P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long xx08 = xx[8] & M, xx09 = xx[9] & M, xx10 = xx[10] & M, xx11 = xx[11] & M;
+ long xx12 = xx[12] & M, xx13 = xx[13] & M, xx14 = xx[14] & M, xx15 = xx[15] & M;
+
+ final long n = 6;
+
+ xx08 -= n;
+
+ long t0 = xx08 + xx09;
+ long t1 = xx09 + xx10;
+ long t2 = xx10 + xx11 - xx15;
+ long t3 = xx11 + xx12;
+ long t4 = xx12 + xx13;
+ long t5 = xx13 + xx14;
+ long t6 = xx14 + xx15;
+
+ long cc = 0;
+ cc += (xx[0] & M) + t0 - t3 - t5;
+ z[0] = (int)cc;
+ cc >>= 32;
+ cc += (xx[1] & M) + t1 - t4 - t6;
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (xx[2] & M) + t2 - t5;
+ z[2] = (int)cc;
+ cc >>= 32;
+ cc += (xx[3] & M) + (t3 << 1) + xx13 - xx15 - t0;
+ z[3] = (int)cc;
+ cc >>= 32;
+ cc += (xx[4] & M) + (t4 << 1) + xx14 - t1;
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (xx[5] & M) + (t5 << 1) - t2;
+ z[5] = (int)cc;
+ cc >>= 32;
+ cc += (xx[6] & M) + (t6 << 1) + t5 - t0;
+ z[6] = (int)cc;
+ cc >>= 32;
+ cc += (xx[7] & M) + (xx15 << 1) + xx08 - t2 - t4;
+ z[7] = (int)cc;
+ cc >>= 32;
+ cc += n;
+
+// assert cc >= 0;
+
+ reduce32((int)cc, z);
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ long cc = 0;
+
+ if (x != 0)
+ {
+ long xx08 = x & M;
+
+ cc += (z[0] & M) + xx08;
+ z[0] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[1] & M);
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (z[2] & M);
+ z[2] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[3] & M) - xx08;
+ z[3] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[4] & M);
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (z[5] & M);
+ z[5] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[6] & M) - xx08;
+ z[6] = (int)cc;
+ cc >>= 32;
+ cc += (z[7] & M) + xx08;
+ z[7] = (int)cc;
+ cc >>= 32;
+
+// assert cc == 0 || cc == 1;
+ }
+
+ if (cc != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat256.createExt();
+ Nat256.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat256.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat256.sub(x, y, z);
+ if (c != 0)
+ {
+ subPInvFrom(z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(16, xx, yy, zz);
+ if (c != 0)
+ {
+ Nat.addTo(16, PExt, zz);
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(8, x, 0, z);
+ if (c != 0 || (z[7] == P7 && Nat256.gte(z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ private static void addPInvTo(int[] z)
+ {
+ long c = (z[0] & M) + 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) - 1;
+ z[3] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ }
+ c += (z[6] & M) - 1;
+ z[6] = (int)c;
+ c >>= 32;
+ c += (z[7] & M) + 1;
+ z[7] = (int)c;
+// c >>= 32;
+ }
+
+ private static void subPInvFrom(int[] z)
+ {
+ long c = (z[0] & M) - 1;
+ z[0] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) + 1;
+ z[3] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ }
+ c += (z[6] & M) + 1;
+ z[6] = (int)c;
+ c >>= 32;
+ c += (z[7] & M) - 1;
+ z[7] = (int)c;
+// c >>= 32;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1FieldElement.java
new file mode 100644
index 0000000..be250d1
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1FieldElement.java
@@ -0,0 +1,189 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.raw.Mod;
+import org.bouncycastle.math.raw.Nat256;
+import org.bouncycastle.util.Arrays;
+
+public class SecP256R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP256R1Curve.q;
+
+ protected int[] x;
+
+ public SecP256R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP256R1FieldElement");
+ }
+
+ this.x = SecP256R1Field.fromBigInteger(x);
+ }
+
+ public SecP256R1FieldElement()
+ {
+ this.x = Nat256.create();
+ }
+
+ protected SecP256R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat256.isZero(x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat256.isOne(x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat256.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat256.toBigInteger(x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP256R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.add(x, ((SecP256R1FieldElement)b).x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.addOne(x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.subtract(x, ((SecP256R1FieldElement)b).x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.multiply(x, ((SecP256R1FieldElement)b).x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat256.create();
+ Mod.invert(SecP256R1Field.P, ((SecP256R1FieldElement)b).x, z);
+ SecP256R1Field.multiply(z, x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.negate(x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat256.create();
+ SecP256R1Field.square(x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP256R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat256.create();
+ Mod.invert(SecP256R1Field.P, x, z);
+ return new SecP256R1FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ // Raise this element to the exponent 2^254 - 2^222 + 2^190 + 2^94
+
+ int[] x1 = this.x;
+ if (Nat256.isZero(x1) || Nat256.isOne(x1))
+ {
+ return this;
+ }
+
+ int[] t1 = Nat256.create();
+ int[] t2 = Nat256.create();
+
+ SecP256R1Field.square(x1, t1);
+ SecP256R1Field.multiply(t1, x1, t1);
+
+ SecP256R1Field.squareN(t1, 2, t2);
+ SecP256R1Field.multiply(t2, t1, t2);
+
+ SecP256R1Field.squareN(t2, 4, t1);
+ SecP256R1Field.multiply(t1, t2, t1);
+
+ SecP256R1Field.squareN(t1, 8, t2);
+ SecP256R1Field.multiply(t2, t1, t2);
+
+ SecP256R1Field.squareN(t2, 16, t1);
+ SecP256R1Field.multiply(t1, t2, t1);
+
+ SecP256R1Field.squareN(t1, 32, t1);
+ SecP256R1Field.multiply(t1, x1, t1);
+
+ SecP256R1Field.squareN(t1, 96, t1);
+ SecP256R1Field.multiply(t1, x1, t1);
+
+ SecP256R1Field.squareN(t1, 94, t1);
+ SecP256R1Field.square(t1, t2);
+
+ return Nat256.eq(x1, t2) ? new SecP256R1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP256R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP256R1FieldElement o = (SecP256R1FieldElement)other;
+ return Nat256.eq(x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 8);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java
new file mode 100644
index 0000000..930fdc5
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Point.java
@@ -0,0 +1,308 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat256;
+
+public class SecP256R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ 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
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP256R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.x, Y1 = (SecP256R1FieldElement)this.y;
+ SecP256R1FieldElement X2 = (SecP256R1FieldElement)b.getXCoord(), Y2 = (SecP256R1FieldElement)b.getYCoord();
+
+ SecP256R1FieldElement Z1 = (SecP256R1FieldElement)this.zs[0];
+ SecP256R1FieldElement Z2 = (SecP256R1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat256.createExt();
+ int[] t2 = Nat256.create();
+ int[] t3 = Nat256.create();
+ int[] t4 = Nat256.create();
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP256R1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP256R1Field.multiply(S2, X2.x, U2);
+
+ SecP256R1Field.multiply(S2, Z1.x, S2);
+ SecP256R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP256R1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP256R1Field.multiply(S1, X1.x, U1);
+
+ SecP256R1Field.multiply(S1, Z2.x, S1);
+ SecP256R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat256.create();
+ SecP256R1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP256R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat256.isZero(H))
+ {
+ if (Nat256.isZero(R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP256R1Field.square(H, HSquared);
+
+ int[] G = Nat256.create();
+ SecP256R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP256R1Field.multiply(HSquared, U1, V);
+
+ SecP256R1Field.negate(G, G);
+ Nat256.mul(S1, G, tt1);
+
+ c = Nat256.addBothTo(V, V, G);
+ SecP256R1Field.reduce32(c, G);
+
+ SecP256R1FieldElement X3 = new SecP256R1FieldElement(t4);
+ SecP256R1Field.square(R, X3.x);
+ SecP256R1Field.subtract(X3.x, G, X3.x);
+
+ SecP256R1FieldElement Y3 = new SecP256R1FieldElement(G);
+ SecP256R1Field.subtract(V, X3.x, Y3.x);
+ SecP256R1Field.multiplyAddToExt(Y3.x, R, tt1);
+ SecP256R1Field.reduce(tt1, Y3.x);
+
+ SecP256R1FieldElement Z3 = new SecP256R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP256R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP256R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP256R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP256R1FieldElement Y1 = (SecP256R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.x, Z1 = (SecP256R1FieldElement)this.zs[0];
+
+ int c;
+ int[] t1 = Nat256.create();
+ int[] t2 = Nat256.create();
+
+ int[] Y1Squared = Nat256.create();
+ SecP256R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat256.create();
+ SecP256R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP256R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP256R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP256R1Field.add(X1.x, Z1Squared, M);
+ SecP256R1Field.multiply(M, t1, M);
+ c = Nat256.addBothTo(M, M, M);
+ SecP256R1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP256R1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(8, S, 2, 0);
+ SecP256R1Field.reduce32(c, S);
+
+ c = Nat.shiftUpBits(8, T, 3, 0, t1);
+ SecP256R1Field.reduce32(c, t1);
+
+ SecP256R1FieldElement X3 = new SecP256R1FieldElement(T);
+ SecP256R1Field.square(M, X3.x);
+ SecP256R1Field.subtract(X3.x, S, X3.x);
+ SecP256R1Field.subtract(X3.x, S, X3.x);
+
+ SecP256R1FieldElement Y3 = new SecP256R1FieldElement(S);
+ SecP256R1Field.subtract(S, X3.x, Y3.x);
+ SecP256R1Field.multiply(Y3.x, M, Y3.x);
+ SecP256R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP256R1FieldElement Z3 = new SecP256R1FieldElement(M);
+ SecP256R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP256R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP256R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP256R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java
new file mode 100644
index 0000000..27cbcdb
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.encoders.Hex;
+
+public class SecP384R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"));
+
+ private static final int SecP384R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP384R1Point infinity;
+
+ public SecP384R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP384R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")));
+ this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP384R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP384R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP384R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP384R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP384R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java
new file mode 100644
index 0000000..f321a10
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java
@@ -0,0 +1,295 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat384;
+
+public class SecP384R1Field
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ // 2^384 - 2^128 - 2^96 + 2^32 - 1
+ static final int[] P = new int[]{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ static final int[] PExt = new int[]{ 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE,
+ 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x00000001, 0x00000000,
+ 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0x00000001,
+ 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF,
+ 0x00000001, 0x00000002 };
+ private static final int P11 = 0xFFFFFFFF;
+ private static final int PExt23 = 0xFFFFFFFF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat.add(12, x, y, z);
+ if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void addExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.add(24, xx, yy, zz);
+ if (c != 0 || (zz[23] == PExt23 && Nat.gte(24, zz, PExt)))
+ {
+ if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.incAt(24, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(12, x, z);
+ if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat.fromBigInteger(384, x);
+ if (z[11] == P11 && Nat.gte(12, z, P))
+ {
+ Nat.subFrom(12, P, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ if ((x[0] & 1) == 0)
+ {
+ Nat.shiftDownBit(12, x, 0, z);
+ }
+ else
+ {
+ int c = Nat.add(12, x, P, z);
+ Nat.shiftDownBit(12, z, c);
+ }
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat.create(24);
+ Nat384.mul(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat.isZero(12, x))
+ {
+ Nat.zero(12, z);
+ }
+ else
+ {
+ Nat.sub(12, P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+ long xx16 = xx[16] & M, xx17 = xx[17] & M, xx18 = xx[18] & M, xx19 = xx[19] & M;
+ long xx20 = xx[20] & M, xx21 = xx[21] & M, xx22 = xx[22] & M, xx23 = xx[23] & M;
+
+ final long n = 1;
+
+ long t0 = (xx[12] & M) + xx20 - n;
+ long t1 = (xx[13] & M) + xx22;
+ long t2 = (xx[14] & M) + xx22 + xx23;
+ long t3 = (xx[15] & M) + xx23;
+ long t4 = xx17 + xx21;
+ long t5 = xx21 - xx23;
+ long t6 = xx22 - xx23;
+
+ long cc = 0;
+ cc += (xx[0] & M) + t0 + t5;
+ z[0] = (int)cc;
+ cc >>= 32;
+ cc += (xx[1] & M) + xx23 - t0 + t1;
+ z[1] = (int)cc;
+ cc >>= 32;
+ cc += (xx[2] & M) - xx21 - t1 + t2;
+ z[2] = (int)cc;
+ cc >>= 32;
+ cc += (xx[3] & M) + t0 - t2 + t3 + t5;
+ z[3] = (int)cc;
+ cc >>= 32;
+ cc += (xx[4] & M) + xx16 + xx21 + t0 + t1 - t3 + t5;
+ z[4] = (int)cc;
+ cc >>= 32;
+ cc += (xx[5] & M) - xx16 + t1 + t2 + t4;
+ z[5] = (int)cc;
+ cc >>= 32;
+ cc += (xx[6] & M) + xx18 - xx17 + t2 + t3;
+ z[6] = (int)cc;
+ cc >>= 32;
+ cc += (xx[7] & M) + xx16 + xx19 - xx18 + t3;
+ z[7] = (int)cc;
+ cc >>= 32;
+ cc += (xx[8] & M) + xx16 + xx17 + xx20 - xx19;
+ z[8] = (int)cc;
+ cc >>= 32;
+ cc += (xx[9] & M) + xx18 - xx20 + t4;
+ z[9] = (int)cc;
+ cc >>= 32;
+ cc += (xx[10] & M) + xx18 + xx19 - t5 + t6;
+ z[10] = (int)cc;
+ cc >>= 32;
+ cc += (xx[11] & M) + xx19 + xx20 - t6;
+ z[11] = (int)cc;
+ cc >>= 32;
+ cc += n;
+
+// assert cc >= 0;
+
+ reduce32((int)cc, z);
+ }
+
+ public static void reduce32(int x, int[] z)
+ {
+ long cc = 0;
+
+ if (x != 0)
+ {
+ long xx12 = x & M;
+
+ cc += (z[0] & M) + xx12;
+ z[0] = (int)cc;
+ cc >>= 32;
+ cc += (z[1] & M) - xx12;
+ z[1] = (int)cc;
+ cc >>= 32;
+ if (cc != 0)
+ {
+ cc += (z[2] & M);
+ z[2] = (int)cc;
+ cc >>= 32;
+ }
+ cc += (z[3] & M) + xx12;
+ z[3] = (int)cc;
+ cc >>= 32;
+ cc += (z[4] & M) + xx12;
+ z[4] = (int)cc;
+ cc >>= 32;
+
+// assert cc == 0 || cc == 1;
+ }
+
+ if ((cc != 0 && Nat.incAt(12, z, 5) != 0)
+ || (z[11] == P11 && Nat.gte(12, z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat.create(24);
+ Nat384.square(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat.create(24);
+ Nat384.square(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ Nat384.square(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat.sub(12, x, y, z);
+ if (c != 0)
+ {
+ subPInvFrom(z);
+ }
+ }
+
+ public static void subtractExt(int[] xx, int[] yy, int[] zz)
+ {
+ int c = Nat.sub(24, xx, yy, zz);
+ if (c != 0)
+ {
+ if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
+ {
+ Nat.decAt(24, zz, PExtInv.length);
+ }
+ }
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int c = Nat.shiftUpBit(12, x, 0, z);
+ if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P)))
+ {
+ addPInvTo(z);
+ }
+ }
+
+ private static void addPInvTo(int[] z)
+ {
+ long c = (z[0] & M) + 1;
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - 1;
+ z[1] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) + 1;
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) + 1;
+ z[4] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.incAt(12, z, 5);
+ }
+ }
+
+ private static void subPInvFrom(int[] z)
+ {
+ long c = (z[0] & M) - 1;
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) + 1;
+ z[1] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ c += (z[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ }
+ c += (z[3] & M) - 1;
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - 1;
+ z[4] = (int)c;
+ c >>= 32;
+ if (c != 0)
+ {
+ Nat.decAt(12, z, 5);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1FieldElement.java
new file mode 100644
index 0000000..24e585d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1FieldElement.java
@@ -0,0 +1,211 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.raw.Mod;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.util.Arrays;
+
+public class SecP384R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP384R1Curve.q;
+
+ protected int[] x;
+
+ public SecP384R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP384R1FieldElement");
+ }
+
+ this.x = SecP384R1Field.fromBigInteger(x);
+ }
+
+ public SecP384R1FieldElement()
+ {
+ this.x = Nat.create(12);
+ }
+
+ protected SecP384R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat.isZero(12, x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat.isOne(12, x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat.toBigInteger(12, x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP384R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.add(x, ((SecP384R1FieldElement)b).x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.addOne(x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.subtract(x, ((SecP384R1FieldElement)b).x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.multiply(x, ((SecP384R1FieldElement)b).x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat.create(12);
+ Mod.invert(SecP384R1Field.P, ((SecP384R1FieldElement)b).x, z);
+ SecP384R1Field.multiply(z, x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.negate(x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat.create(12);
+ SecP384R1Field.square(x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP384R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat.create(12);
+ Mod.invert(SecP384R1Field.P, x, z);
+ return new SecP384R1FieldElement(z);
+ }
+
+ /**
+ * return a sqrt root - the routine verifies that the calculation returns the right value - if
+ * none exists it returns null.
+ */
+ public ECFieldElement sqrt()
+ {
+ // Raise this element to the exponent 2^382 - 2^126 - 2^94 + 2^30
+
+ int[] x1 = this.x;
+ if (Nat.isZero(12, x1) || Nat.isOne(12, x1))
+ {
+ return this;
+ }
+
+ int[] t1 = Nat.create(12);
+ int[] t2 = Nat.create(12);
+ int[] t3 = Nat.create(12);
+ int[] t4 = Nat.create(12);
+
+ SecP384R1Field.square(x1, t1);
+ SecP384R1Field.multiply(t1, x1, t1);
+
+ SecP384R1Field.squareN(t1, 2, t2);
+ SecP384R1Field.multiply(t2, t1, t2);
+
+ SecP384R1Field.square(t2, t2);
+ SecP384R1Field.multiply(t2, x1, t2);
+
+ SecP384R1Field.squareN(t2, 5, t3);
+ SecP384R1Field.multiply(t3, t2, t3);
+
+ SecP384R1Field.squareN(t3, 5, t4);
+ SecP384R1Field.multiply(t4, t2, t4);
+
+ SecP384R1Field.squareN(t4, 15, t2);
+ SecP384R1Field.multiply(t2, t4, t2);
+
+ SecP384R1Field.squareN(t2, 2, t3);
+ SecP384R1Field.multiply(t1, t3, t1);
+
+ SecP384R1Field.squareN(t3, 28, t3);
+ SecP384R1Field.multiply(t2, t3, t2);
+
+ SecP384R1Field.squareN(t2, 60, t3);
+ SecP384R1Field.multiply(t3, t2, t3);
+
+ int[] r = t2;
+
+ SecP384R1Field.squareN(t3, 120, r);
+ SecP384R1Field.multiply(r, t3, r);
+
+ SecP384R1Field.squareN(r, 15, r);
+ SecP384R1Field.multiply(r, t4, r);
+
+ SecP384R1Field.squareN(r, 33, r);
+ SecP384R1Field.multiply(r, t1, r);
+
+ SecP384R1Field.squareN(r, 64, r);
+ SecP384R1Field.multiply(r, x1, r);
+
+ SecP384R1Field.squareN(r, 30, t1);
+ SecP384R1Field.square(t1, t2);
+
+ return Nat.eq(12, x1, t2) ? new SecP384R1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP384R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP384R1FieldElement o = (SecP384R1FieldElement)other;
+ return Nat.eq(12, x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 12);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java
new file mode 100644
index 0000000..89f6bf4
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Point.java
@@ -0,0 +1,309 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat384;
+
+public class SecP384R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ 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
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP384R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Y1 = (SecP384R1FieldElement)this.y;
+ SecP384R1FieldElement X2 = (SecP384R1FieldElement)b.getXCoord(), Y2 = (SecP384R1FieldElement)b.getYCoord();
+
+ SecP384R1FieldElement Z1 = (SecP384R1FieldElement)this.zs[0];
+ SecP384R1FieldElement Z2 = (SecP384R1FieldElement)b.getZCoord(0);
+
+ int c;
+ int[] tt1 = Nat.create(24);
+ int[] tt2 = Nat.create(24);
+ int[] t3 = Nat.create(12);
+ int[] t4 = Nat.create(12);
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP384R1Field.square(Z1.x, S2);
+
+ U2 = tt2;
+ SecP384R1Field.multiply(S2, X2.x, U2);
+
+ SecP384R1Field.multiply(S2, Z1.x, S2);
+ SecP384R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP384R1Field.square(Z2.x, S1);
+
+ U1 = tt1;
+ SecP384R1Field.multiply(S1, X1.x, U1);
+
+ SecP384R1Field.multiply(S1, Z2.x, S1);
+ SecP384R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat.create(12);
+ SecP384R1Field.subtract(U1, U2, H);
+
+ int[] R = Nat.create(12);
+ SecP384R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat.isZero(12, H))
+ {
+ if (Nat.isZero(12, R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP384R1Field.square(H, HSquared);
+
+ int[] G = Nat.create(12);
+ SecP384R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP384R1Field.multiply(HSquared, U1, V);
+
+ SecP384R1Field.negate(G, G);
+ Nat384.mul(S1, G, tt1);
+
+ c = Nat.addBothTo(12, V, V, G);
+ SecP384R1Field.reduce32(c, G);
+
+ SecP384R1FieldElement X3 = new SecP384R1FieldElement(t4);
+ SecP384R1Field.square(R, X3.x);
+ SecP384R1Field.subtract(X3.x, G, X3.x);
+
+ SecP384R1FieldElement Y3 = new SecP384R1FieldElement(G);
+ SecP384R1Field.subtract(V, X3.x, Y3.x);
+ Nat384.mul(Y3.x, R, tt2);
+ SecP384R1Field.addExt(tt1, tt2, tt1);
+ SecP384R1Field.reduce(tt1, Y3.x);
+
+ SecP384R1FieldElement Z3 = new SecP384R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP384R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP384R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP384R1FieldElement Y1 = (SecP384R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Z1 = (SecP384R1FieldElement)this.zs[0];
+
+ int c;
+ int[] t1 = Nat.create(12);
+ int[] t2 = Nat.create(12);
+
+ int[] Y1Squared = Nat.create(12);
+ SecP384R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat.create(12);
+ SecP384R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP384R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP384R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP384R1Field.add(X1.x, Z1Squared, M);
+ SecP384R1Field.multiply(M, t1, M);
+ c = Nat.addBothTo(12, M, M, M);
+ SecP384R1Field.reduce32(c, M);
+
+ int[] S = Y1Squared;
+ SecP384R1Field.multiply(Y1Squared, X1.x, S);
+ c = Nat.shiftUpBits(12, S, 2, 0);
+ SecP384R1Field.reduce32(c, S);
+
+ c = Nat.shiftUpBits(12, T, 3, 0, t1);
+ SecP384R1Field.reduce32(c, t1);
+
+ SecP384R1FieldElement X3 = new SecP384R1FieldElement(T);
+ SecP384R1Field.square(M, X3.x);
+ SecP384R1Field.subtract(X3.x, S, X3.x);
+ SecP384R1Field.subtract(X3.x, S, X3.x);
+
+ SecP384R1FieldElement Y3 = new SecP384R1FieldElement(S);
+ SecP384R1Field.subtract(S, X3.x, Y3.x);
+ SecP384R1Field.multiply(Y3.x, M, Y3.x);
+ SecP384R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP384R1FieldElement Z3 = new SecP384R1FieldElement(M);
+ SecP384R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP384R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP384R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java
new file mode 100644
index 0000000..16691b1
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.encoders.Hex;
+
+public class SecP521R1Curve extends ECCurve.AbstractFp
+{
+ public static final BigInteger q = new BigInteger(1,
+ Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+
+ private static final int SecP521R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+ protected SecP521R1Point infinity;
+
+ public SecP521R1Curve()
+ {
+ super(q);
+
+ this.infinity = new SecP521R1Point(this, null, null);
+
+ this.a = fromBigInteger(new BigInteger(1,
+ Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC")));
+ this.b = fromBigInteger(new BigInteger(1,
+ Hex.decode("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00")));
+ this.order = new BigInteger(1, Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"));
+ this.cofactor = BigInteger.valueOf(1);
+
+ this.coord = SecP521R1_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new SecP521R1Curve();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_JACOBIAN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public int getFieldSize()
+ {
+ return q.bitLength();
+ }
+
+ public ECFieldElement fromBigInteger(BigInteger x)
+ {
+ return new SecP521R1FieldElement(x);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new SecP521R1Point(this, x, y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ return new SecP521R1Point(this, x, y, zs, withCompression);
+ }
+
+ public ECPoint getInfinity()
+ {
+ return infinity;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Field.java
new file mode 100644
index 0000000..00f1066
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Field.java
@@ -0,0 +1,156 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.math.raw.Nat512;
+
+public class SecP521R1Field
+{
+ // 2^521 - 1
+ static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x1FF };
+ private static final int P16 = 0x1FF;
+
+ public static void add(int[] x, int[] y, int[] z)
+ {
+ int c = Nat.add(16, x, y, z) + x[16] + y[16];
+ if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
+ {
+ c += Nat.inc(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static void addOne(int[] x, int[] z)
+ {
+ int c = Nat.inc(16, x, z) + x[16];
+ if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
+ {
+ c += Nat.inc(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ int[] z = Nat.fromBigInteger(521, x);
+ if (Nat.eq(17, z, P))
+ {
+ Nat.zero(17, z);
+ }
+ return z;
+ }
+
+ public static void half(int[] x, int[] z)
+ {
+ int x16 = x[16];
+ int c = Nat.shiftDownBit(16, x, x16, z);
+ z[16] = (x16 >>> 1) | (c >>> 23);
+ }
+
+ public static void multiply(int[] x, int[] y, int[] z)
+ {
+ int[] tt = Nat.create(33);
+ implMultiply(x, y, tt);
+ reduce(tt, z);
+ }
+
+ public static void negate(int[] x, int[] z)
+ {
+ if (Nat.isZero(17, x))
+ {
+ Nat.zero(17, z);
+ }
+ else
+ {
+ Nat.sub(17, P, x, z);
+ }
+ }
+
+ public static void reduce(int[] xx, int[] z)
+ {
+// assert xx[32] >>> 18 == 0;
+
+ int xx32 = xx[32];
+ int c = Nat.shiftDownBits(16, xx, 16, 9, xx32, z, 0) >>> 23;
+ c += xx32 >>> 9;
+ c += Nat.addTo(16, xx, z);
+ if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
+ {
+ c += Nat.inc(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static void reduce23(int[] z)
+ {
+ int z16 = z[16];
+ int c = Nat.addWordTo(16, z16 >>> 9, z) + (z16 & P16);
+ if (c > P16 || (c == P16 && Nat.eq(16, z, P)))
+ {
+ c += Nat.inc(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static void square(int[] x, int[] z)
+ {
+ int[] tt = Nat.create(33);
+ implSquare(x, tt);
+ reduce(tt, z);
+ }
+
+ public static void squareN(int[] x, int n, int[] z)
+ {
+// assert n > 0;
+
+ int[] tt = Nat.create(33);
+ implSquare(x, tt);
+ reduce(tt, z);
+
+ while (--n > 0)
+ {
+ implSquare(z, tt);
+ reduce(tt, z);
+ }
+ }
+
+ public static void subtract(int[] x, int[] y, int[] z)
+ {
+ int c = Nat.sub(16, x, y, z) + x[16] - y[16];
+ if (c < 0)
+ {
+ c += Nat.dec(16, z);
+ c &= P16;
+ }
+ z[16] = c;
+ }
+
+ public static void twice(int[] x, int[] z)
+ {
+ int x16 = x[16];
+ int c = Nat.shiftUpBit(16, x, x16 << 23, z) | (x16 << 1);
+ z[16] = c & P16;
+ }
+
+ protected static void implMultiply(int[] x, int[] y, int[] zz)
+ {
+ Nat512.mul(x, y, zz);
+
+ int x16 = x[16], y16 = y[16];
+ zz[32] = Nat.mul31BothAdd(16, x16, y, y16, x, zz, 16) + (x16 * y16);
+ }
+
+ protected static void implSquare(int[] x, int[] zz)
+ {
+ Nat512.square(x, zz);
+
+ int x16 = x[16];
+ zz[32] = Nat.mulWordAddTo(16, x16 << 1, x, 0, zz, 16) + (x16 * x16);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1FieldElement.java
new file mode 100644
index 0000000..ce9b639
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1FieldElement.java
@@ -0,0 +1,169 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.raw.Mod;
+import org.bouncycastle.math.raw.Nat;
+import org.bouncycastle.util.Arrays;
+
+public class SecP521R1FieldElement extends ECFieldElement
+{
+ public static final BigInteger Q = SecP521R1Curve.q;
+
+ protected int[] x;
+
+ public SecP521R1FieldElement(BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
+ {
+ throw new IllegalArgumentException("x value invalid for SecP521R1FieldElement");
+ }
+
+ this.x = SecP521R1Field.fromBigInteger(x);
+ }
+
+ public SecP521R1FieldElement()
+ {
+ this.x = Nat.create(17);
+ }
+
+ protected SecP521R1FieldElement(int[] x)
+ {
+ this.x = x;
+ }
+
+ public boolean isZero()
+ {
+ return Nat.isZero(17, x);
+ }
+
+ public boolean isOne()
+ {
+ return Nat.isOne(17, x);
+ }
+
+ public boolean testBitZero()
+ {
+ return Nat.getBit(x, 0) == 1;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ return Nat.toBigInteger(17, x);
+ }
+
+ public String getFieldName()
+ {
+ return "SecP521R1Field";
+ }
+
+ public int getFieldSize()
+ {
+ return Q.bitLength();
+ }
+
+ public ECFieldElement add(ECFieldElement b)
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.add(x, ((SecP521R1FieldElement)b).x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement addOne()
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.addOne(x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement subtract(ECFieldElement b)
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.subtract(x, ((SecP521R1FieldElement)b).x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement multiply(ECFieldElement b)
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.multiply(x, ((SecP521R1FieldElement)b).x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement divide(ECFieldElement b)
+ {
+// return multiply(b.invert());
+ int[] z = Nat.create(17);
+ Mod.invert(SecP521R1Field.P, ((SecP521R1FieldElement)b).x, z);
+ SecP521R1Field.multiply(z, x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement negate()
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.negate(x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement square()
+ {
+ int[] z = Nat.create(17);
+ SecP521R1Field.square(x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ public ECFieldElement invert()
+ {
+// return new SecP521R1FieldElement(toBigInteger().modInverse(Q));
+ int[] z = Nat.create(17);
+ Mod.invert(SecP521R1Field.P, x, z);
+ return new SecP521R1FieldElement(z);
+ }
+
+ // 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()
+ {
+ // Raise this element to the exponent 2^519
+
+ int[] x1 = this.x;
+ if (Nat.isZero(17, x1) || Nat.isOne(17, x1))
+ {
+ return this;
+ }
+
+ int[] t1 = Nat.create(17);
+ int[] t2 = Nat.create(17);
+
+ SecP521R1Field.squareN(x1, 519, t1);
+ SecP521R1Field.square(t1, t2);
+
+ return Nat.eq(17, x1, t2) ? new SecP521R1FieldElement(t1) : null;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof SecP521R1FieldElement))
+ {
+ return false;
+ }
+
+ SecP521R1FieldElement o = (SecP521R1FieldElement)other;
+ return Nat.eq(17, x, o.x);
+ }
+
+ public int hashCode()
+ {
+ return Q.hashCode() ^ Arrays.hashCode(x, 0, 17);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java
new file mode 100644
index 0000000..d973715
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Point.java
@@ -0,0 +1,333 @@
+package org.bouncycastle.math.ec.custom.sec;
+
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
+
+public class SecP521R1Point extends ECPoint.AbstractFp
+{
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve
+ * the curve to use
+ * @param x
+ * affine x co-ordinate
+ * @param y
+ * affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
+ */
+ public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ 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
+ *
+ * @deprecated per-point compression property will be removed, refer
+ * {@link #getEncoded(boolean)}
+ */
+ public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x == null) != (y == null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
+ {
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected ECPoint detach()
+ {
+ return new SecP521R1Point(null, getAffineXCoord(), getAffineYCoord());
+ }
+
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Y1 = (SecP521R1FieldElement)this.y;
+ SecP521R1FieldElement X2 = (SecP521R1FieldElement)b.getXCoord(), Y2 = (SecP521R1FieldElement)b.getYCoord();
+
+ SecP521R1FieldElement Z1 = (SecP521R1FieldElement)this.zs[0];
+ SecP521R1FieldElement Z2 = (SecP521R1FieldElement)b.getZCoord(0);
+
+ int[] t1 = Nat.create(17);
+ int[] t2 = Nat.create(17);
+ int[] t3 = Nat.create(17);
+ int[] t4 = Nat.create(17);
+
+ boolean Z1IsOne = Z1.isOne();
+ int[] U2, S2;
+ if (Z1IsOne)
+ {
+ U2 = X2.x;
+ S2 = Y2.x;
+ }
+ else
+ {
+ S2 = t3;
+ SecP521R1Field.square(Z1.x, S2);
+
+ U2 = t2;
+ SecP521R1Field.multiply(S2, X2.x, U2);
+
+ SecP521R1Field.multiply(S2, Z1.x, S2);
+ SecP521R1Field.multiply(S2, Y2.x, S2);
+ }
+
+ boolean Z2IsOne = Z2.isOne();
+ int[] U1, S1;
+ if (Z2IsOne)
+ {
+ U1 = X1.x;
+ S1 = Y1.x;
+ }
+ else
+ {
+ S1 = t4;
+ SecP521R1Field.square(Z2.x, S1);
+
+ U1 = t1;
+ SecP521R1Field.multiply(S1, X1.x, U1);
+
+ SecP521R1Field.multiply(S1, Z2.x, S1);
+ SecP521R1Field.multiply(S1, Y1.x, S1);
+ }
+
+ int[] H = Nat.create(17);
+ SecP521R1Field.subtract(U1, U2, H);
+
+ int[] R = t2;
+ SecP521R1Field.subtract(S1, S2, R);
+
+ // Check if b == this or b == -this
+ if (Nat.isZero(17, H))
+ {
+ if (Nat.isZero(17, R))
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
+
+ int[] HSquared = t3;
+ SecP521R1Field.square(H, HSquared);
+
+ int[] G = Nat.create(17);
+ SecP521R1Field.multiply(HSquared, H, G);
+
+ int[] V = t3;
+ SecP521R1Field.multiply(HSquared, U1, V);
+
+ SecP521R1Field.multiply(S1, G, t1);
+
+ SecP521R1FieldElement X3 = new SecP521R1FieldElement(t4);
+ SecP521R1Field.square(R, X3.x);
+ SecP521R1Field.add(X3.x, G, X3.x);
+ SecP521R1Field.subtract(X3.x, V, X3.x);
+ SecP521R1Field.subtract(X3.x, V, X3.x);
+
+ SecP521R1FieldElement Y3 = new SecP521R1FieldElement(G);
+ SecP521R1Field.subtract(V, X3.x, Y3.x);
+ SecP521R1Field.multiply(Y3.x, R, t2);
+ SecP521R1Field.subtract(t2, t1, Y3.x);
+
+ SecP521R1FieldElement Z3 = new SecP521R1FieldElement(H);
+ if (!Z1IsOne)
+ {
+ SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+ if (!Z2IsOne)
+ {
+ SecP521R1Field.multiply(Z3.x, Z2.x, Z3.x);
+ }
+
+ ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+ return new SecP521R1Point(curve, X3, Y3, zs, this.withCompression);
+ }
+
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ SecP521R1FieldElement Y1 = (SecP521R1FieldElement)this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Z1 = (SecP521R1FieldElement)this.zs[0];
+
+ int[] t1 = Nat.create(17);
+ int[] t2 = Nat.create(17);
+
+ int[] Y1Squared = Nat.create(17);
+ SecP521R1Field.square(Y1.x, Y1Squared);
+
+ int[] T = Nat.create(17);
+ SecP521R1Field.square(Y1Squared, T);
+
+ boolean Z1IsOne = Z1.isOne();
+
+ int[] Z1Squared = Z1.x;
+ if (!Z1IsOne)
+ {
+ Z1Squared = t2;
+ SecP521R1Field.square(Z1.x, Z1Squared);
+ }
+
+ SecP521R1Field.subtract(X1.x, Z1Squared, t1);
+
+ int[] M = t2;
+ SecP521R1Field.add(X1.x, Z1Squared, M);
+ SecP521R1Field.multiply(M, t1, M);
+ Nat.addBothTo(17, M, M, M);
+ SecP521R1Field.reduce23(M);
+
+ int[] S = Y1Squared;
+ SecP521R1Field.multiply(Y1Squared, X1.x, S);
+ Nat.shiftUpBits(17, S, 2, 0);
+ SecP521R1Field.reduce23(S);
+
+ Nat.shiftUpBits(17, T, 3, 0, t1);
+ SecP521R1Field.reduce23(t1);
+
+ SecP521R1FieldElement X3 = new SecP521R1FieldElement(T);
+ SecP521R1Field.square(M, X3.x);
+ SecP521R1Field.subtract(X3.x, S, X3.x);
+ SecP521R1Field.subtract(X3.x, S, X3.x);
+
+ SecP521R1FieldElement Y3 = new SecP521R1FieldElement(S);
+ SecP521R1Field.subtract(S, X3.x, Y3.x);
+ SecP521R1Field.multiply(Y3.x, M, Y3.x);
+ SecP521R1Field.subtract(Y3.x, t1, Y3.x);
+
+ SecP521R1FieldElement Z3 = new SecP521R1FieldElement(M);
+ SecP521R1Field.twice(Y1.x, Z3.x);
+ if (!Z1IsOne)
+ {
+ SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x);
+ }
+
+ return new SecP521R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ if (this == b)
+ {
+ return threeTimes();
+ }
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
+ }
+
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ if (this.isInfinity() || this.y.isZero())
+ {
+ return this;
+ }
+
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
+ }
+
+ protected ECFieldElement two(ECFieldElement x)
+ {
+ return x.add(x);
+ }
+
+ protected ECFieldElement three(ECFieldElement x)
+ {
+ return two(x).add(x);
+ }
+
+ protected ECFieldElement four(ECFieldElement x)
+ {
+ return two(two(x));
+ }
+
+ protected ECFieldElement eight(ECFieldElement x)
+ {
+ return four(two(x));
+ }
+
+ protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b,
+ ECFieldElement aSquared, ECFieldElement bSquared)
+ {
+ /*
+ * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
+ * way to calculate 2.A.B, if A^2 and B^2 are already known.
+ */
+ return a.add(b).square().subtract(aSquared).subtract(bSquared);
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ return new SecP521R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/endo/ECEndomorphism.java b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/ECEndomorphism.java
new file mode 100644
index 0000000..2be0c01
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/ECEndomorphism.java
@@ -0,0 +1,10 @@
+package org.bouncycastle.math.ec.endo;
+
+import org.bouncycastle.math.ec.ECPointMap;
+
+public interface ECEndomorphism
+{
+ ECPointMap getPointMap();
+
+ boolean hasEfficientPointMap();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVEndomorphism.java b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVEndomorphism.java
new file mode 100644
index 0000000..8897bb3
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVEndomorphism.java
@@ -0,0 +1,8 @@
+package org.bouncycastle.math.ec.endo;
+
+import java.math.BigInteger;
+
+public interface GLVEndomorphism extends ECEndomorphism
+{
+ BigInteger[] decomposeScalar(BigInteger k);
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java
new file mode 100644
index 0000000..ab710d1
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBEndomorphism.java
@@ -0,0 +1,58 @@
+package org.bouncycastle.math.ec.endo;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECConstants;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECPointMap;
+import org.bouncycastle.math.ec.ScaleXPointMap;
+
+public class GLVTypeBEndomorphism implements GLVEndomorphism
+{
+ protected final ECCurve curve;
+ protected final GLVTypeBParameters parameters;
+ protected final ECPointMap pointMap;
+
+ public GLVTypeBEndomorphism(ECCurve curve, GLVTypeBParameters parameters)
+ {
+ this.curve = curve;
+ this.parameters = parameters;
+ this.pointMap = new ScaleXPointMap(curve.fromBigInteger(parameters.getBeta()));
+ }
+
+ public BigInteger[] decomposeScalar(BigInteger k)
+ {
+ int bits = parameters.getBits();
+ BigInteger b1 = calculateB(k, parameters.getG1(), bits);
+ BigInteger b2 = calculateB(k, parameters.getG2(), bits);
+
+ BigInteger[] v1 = parameters.getV1(), v2 = parameters.getV2();
+ BigInteger a = k.subtract((b1.multiply(v1[0])).add(b2.multiply(v2[0])));
+ BigInteger b = (b1.multiply(v1[1])).add(b2.multiply(v2[1])).negate();
+
+ return new BigInteger[]{ a, b };
+ }
+
+ public ECPointMap getPointMap()
+ {
+ return pointMap;
+ }
+
+ public boolean hasEfficientPointMap()
+ {
+ return true;
+ }
+
+ protected BigInteger calculateB(BigInteger k, BigInteger g, int t)
+ {
+ boolean negative = (g.signum() < 0);
+ BigInteger b = k.multiply(g.abs());
+ boolean extra = b.testBit(t - 1);
+ b = b.shiftRight(t);
+ if (extra)
+ {
+ b = b.add(ECConstants.ONE);
+ }
+ return negative ? b.negate() : b;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java
new file mode 100644
index 0000000..f02a882
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/endo/GLVTypeBParameters.java
@@ -0,0 +1,59 @@
+package org.bouncycastle.math.ec.endo;
+
+import java.math.BigInteger;
+
+public class GLVTypeBParameters
+{
+ protected final BigInteger beta;
+ protected final BigInteger lambda;
+ protected final BigInteger[] v1, v2;
+ protected final BigInteger g1, g2;
+ protected final int bits;
+
+ public GLVTypeBParameters(BigInteger beta, BigInteger lambda, BigInteger[] v1, BigInteger[] v2, BigInteger g1,
+ BigInteger g2, int bits)
+ {
+ this.beta = beta;
+ this.lambda = lambda;
+ this.v1 = v1;
+ this.v2 = v2;
+ this.g1 = g1;
+ this.g2 = g2;
+ this.bits = bits;
+ }
+
+ public BigInteger getBeta()
+ {
+ return beta;
+ }
+
+ public BigInteger getLambda()
+ {
+ return lambda;
+ }
+
+ public BigInteger[] getV1()
+ {
+ return v1;
+ }
+
+ public BigInteger[] getV2()
+ {
+ return v2;
+ }
+
+ public BigInteger getG1()
+ {
+ return g1;
+ }
+
+ public BigInteger getG2()
+ {
+ return g2;
+ }
+
+ public int getBits()
+ {
+ return bits;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/field/ExtensionField.java b/bcprov/src/main/java/org/bouncycastle/math/field/ExtensionField.java
new file mode 100644
index 0000000..dfefba7
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/field/ExtensionField.java
@@ -0,0 +1,8 @@
+package org.bouncycastle.math.field;
+
+public interface ExtensionField extends FiniteField
+{
+ FiniteField getSubfield();
+
+ int getDegree();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/field/FiniteField.java b/bcprov/src/main/java/org/bouncycastle/math/field/FiniteField.java
new file mode 100644
index 0000000..0a5baa0
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/field/FiniteField.java
@@ -0,0 +1,10 @@
+package org.bouncycastle.math.field;
+
+import java.math.BigInteger;
+
+public interface FiniteField
+{
+ BigInteger getCharacteristic();
+
+ int getDimension();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/field/FiniteFields.java b/bcprov/src/main/java/org/bouncycastle/math/field/FiniteFields.java
new file mode 100644
index 0000000..7197ffd
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/field/FiniteFields.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.math.field;
+
+import java.math.BigInteger;
+
+public abstract class FiniteFields
+{
+ static final FiniteField GF_2 = new PrimeField(BigInteger.valueOf(2));
+ static final FiniteField GF_3 = new PrimeField(BigInteger.valueOf(3));
+
+ public static PolynomialExtensionField getBinaryExtensionField(int[] exponents)
+ {
+ if (exponents[0] != 0)
+ {
+ throw new IllegalArgumentException("Irreducible polynomials in GF(2) must have constant term");
+ }
+ for (int i = 1; i < exponents.length; ++i)
+ {
+ if (exponents[i] <= exponents[i - 1])
+ {
+ throw new IllegalArgumentException("Polynomial exponents must be montonically increasing");
+ }
+ }
+
+ return new GenericPolynomialExtensionField(GF_2, new GF2Polynomial(exponents));
+ }
+
+// public static PolynomialExtensionField getTernaryExtensionField(Term[] terms)
+// {
+// return new GenericPolynomialExtensionField(GF_3, new GF3Polynomial(terms));
+// }
+
+ public static FiniteField getPrimeField(BigInteger characteristic)
+ {
+ int bitLength = characteristic.bitLength();
+ if (characteristic.signum() <= 0 || bitLength < 2)
+ {
+ throw new IllegalArgumentException("'characteristic' must be >= 2");
+ }
+
+ if (bitLength < 3)
+ {
+ switch (characteristic.intValue())
+ {
+ case 2:
+ return GF_2;
+ case 3:
+ return GF_3;
+ }
+ }
+
+ return new PrimeField(characteristic);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/field/GF2Polynomial.java b/bcprov/src/main/java/org/bouncycastle/math/field/GF2Polynomial.java
new file mode 100644
index 0000000..73be768
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/field/GF2Polynomial.java
@@ -0,0 +1,42 @@
+package org.bouncycastle.math.field;
+
+import org.bouncycastle.util.Arrays;
+
+class GF2Polynomial implements Polynomial
+{
+ protected final int[] exponents;
+
+ GF2Polynomial(int[] exponents)
+ {
+ this.exponents = Arrays.clone(exponents);
+ }
+
+ public int getDegree()
+ {
+ return exponents[exponents.length - 1];
+ }
+
+ public int[] getExponentsPresent()
+ {
+ return Arrays.clone(exponents);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof GF2Polynomial))
+ {
+ return false;
+ }
+ GF2Polynomial other = (GF2Polynomial)obj;
+ return Arrays.areEqual(exponents, other.exponents);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(exponents);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/field/GenericPolynomialExtensionField.java b/bcprov/src/main/java/org/bouncycastle/math/field/GenericPolynomialExtensionField.java
new file mode 100644
index 0000000..0b93a71
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/field/GenericPolynomialExtensionField.java
@@ -0,0 +1,62 @@
+package org.bouncycastle.math.field;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.util.Integers;
+
+class GenericPolynomialExtensionField implements PolynomialExtensionField
+{
+ protected final FiniteField subfield;
+ protected final Polynomial minimalPolynomial;
+
+ GenericPolynomialExtensionField(FiniteField subfield, Polynomial polynomial)
+ {
+ this.subfield = subfield;
+ this.minimalPolynomial = polynomial;
+ }
+
+ public BigInteger getCharacteristic()
+ {
+ return subfield.getCharacteristic();
+ }
+
+ public int getDimension()
+ {
+ return subfield.getDimension() * minimalPolynomial.getDegree();
+ }
+
+ public FiniteField getSubfield()
+ {
+ return subfield;
+ }
+
+ public int getDegree()
+ {
+ return minimalPolynomial.getDegree();
+ }
+
+ public Polynomial getMinimalPolynomial()
+ {
+ return minimalPolynomial;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof GenericPolynomialExtensionField))
+ {
+ return false;
+ }
+ GenericPolynomialExtensionField other = (GenericPolynomialExtensionField)obj;
+ return subfield.equals(other.subfield) && minimalPolynomial.equals(other.minimalPolynomial);
+ }
+
+ public int hashCode()
+ {
+ return subfield.hashCode()
+ ^ Integers.rotateLeft(minimalPolynomial.hashCode(), 16);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/field/Polynomial.java b/bcprov/src/main/java/org/bouncycastle/math/field/Polynomial.java
new file mode 100644
index 0000000..e5ccd61
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/field/Polynomial.java
@@ -0,0 +1,12 @@
+package org.bouncycastle.math.field;
+
+public interface Polynomial
+{
+ int getDegree();
+
+// BigInteger[] getCoefficients();
+
+ int[] getExponentsPresent();
+
+// Term[] getNonZeroTerms();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/field/PolynomialExtensionField.java b/bcprov/src/main/java/org/bouncycastle/math/field/PolynomialExtensionField.java
new file mode 100644
index 0000000..aedcbee
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/field/PolynomialExtensionField.java
@@ -0,0 +1,6 @@
+package org.bouncycastle.math.field;
+
+public interface PolynomialExtensionField extends ExtensionField
+{
+ Polynomial getMinimalPolynomial();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/field/PrimeField.java b/bcprov/src/main/java/org/bouncycastle/math/field/PrimeField.java
new file mode 100644
index 0000000..fd1e253
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/field/PrimeField.java
@@ -0,0 +1,42 @@
+package org.bouncycastle.math.field;
+
+import java.math.BigInteger;
+
+class PrimeField implements FiniteField
+{
+ protected final BigInteger characteristic;
+
+ PrimeField(BigInteger characteristic)
+ {
+ this.characteristic = characteristic;
+ }
+
+ public BigInteger getCharacteristic()
+ {
+ return characteristic;
+ }
+
+ public int getDimension()
+ {
+ return 1;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof PrimeField))
+ {
+ return false;
+ }
+ PrimeField other = (PrimeField)obj;
+ return characteristic.equals(other.characteristic);
+ }
+
+ public int hashCode()
+ {
+ return characteristic.hashCode();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Mod.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Mod.java
new file mode 100644
index 0000000..47e6d8c
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Mod.java
@@ -0,0 +1,199 @@
+package org.bouncycastle.math.raw;
+
+import java.util.Random;
+
+import org.bouncycastle.util.Pack;
+
+public abstract class Mod
+{
+ public static int inverse32(int d)
+ {
+// int x = d + (((d + 1) & 4) << 1); // d.x == 1 mod 2**4
+ int x = d; // d.x == 1 mod 2**3
+ x *= 2 - d * x; // d.x == 1 mod 2**6
+ x *= 2 - d * x; // d.x == 1 mod 2**12
+ x *= 2 - d * x; // d.x == 1 mod 2**24
+ x *= 2 - d * x; // d.x == 1 mod 2**48
+// assert d * x == 1;
+ return x;
+ }
+
+ public static void invert(int[] p, int[] x, int[] z)
+ {
+ int len = p.length;
+ if (Nat.isZero(len, x))
+ {
+ throw new IllegalArgumentException("'x' cannot be 0");
+ }
+ if (Nat.isOne(len, x))
+ {
+ System.arraycopy(x, 0, z, 0, len);
+ return;
+ }
+
+ int[] u = Nat.copy(len, x);
+ int[] a = Nat.create(len);
+ a[0] = 1;
+ int ac = 0;
+
+ if ((u[0] & 1) == 0)
+ {
+ ac = inversionStep(p, u, len, a, ac);
+ }
+ if (Nat.isOne(len, u))
+ {
+ inversionResult(p, ac, a, z);
+ return;
+ }
+
+ int[] v = Nat.copy(len, p);
+ int[] b = Nat.create(len);
+ int bc = 0;
+
+ int uvLen = len;
+
+ for (;;)
+ {
+ while (u[uvLen - 1] == 0 && v[uvLen - 1] == 0)
+ {
+ --uvLen;
+ }
+
+ if (Nat.gte(uvLen, u, v))
+ {
+ Nat.subFrom(uvLen, v, u);
+// assert (u[0] & 1) == 0;
+ ac += Nat.subFrom(len, b, a) - bc;
+ ac = inversionStep(p, u, uvLen, a, ac);
+ if (Nat.isOne(uvLen, u))
+ {
+ inversionResult(p, ac, a, z);
+ return;
+ }
+ }
+ else
+ {
+ Nat.subFrom(uvLen, u, v);
+// assert (v[0] & 1) == 0;
+ bc += Nat.subFrom(len, a, b) - ac;
+ bc = inversionStep(p, v, uvLen, b, bc);
+ if (Nat.isOne(uvLen, v))
+ {
+ inversionResult(p, bc, b, z);
+ return;
+ }
+ }
+ }
+ }
+
+ public static int[] random(int[] p)
+ {
+ int len = p.length;
+ Random rand = new Random();
+ int[] s = Nat.create(len);
+
+ int m = p[len - 1];
+ m |= m >>> 1;
+ m |= m >>> 2;
+ m |= m >>> 4;
+ m |= m >>> 8;
+ m |= m >>> 16;
+
+ do
+ {
+ for (int i = 0; i != len; i++)
+ {
+ s[i] = rand.nextInt();
+ }
+ s[len - 1] &= m;
+ }
+ while (Nat.gte(len, s, p));
+
+ return s;
+ }
+
+ public static void add(int[] p, int[] x, int[] y, int[] z)
+ {
+ int len = p.length;
+ int c = Nat.add(len, x, y, z);
+ if (c != 0)
+ {
+ Nat.subFrom(len, p, z);
+ }
+ }
+
+ public static void subtract(int[] p, int[] x, int[] y, int[] z)
+ {
+ int len = p.length;
+ int c = Nat.sub(len, x, y, z);
+ if (c != 0)
+ {
+ Nat.addTo(len, p, z);
+ }
+ }
+
+ private static void inversionResult(int[] p, int ac, int[] a, int[] z)
+ {
+ if (ac < 0)
+ {
+ Nat.add(p.length, a, p, z);
+ }
+ else
+ {
+ System.arraycopy(a, 0, z, 0, p.length);
+ }
+ }
+
+ private static int inversionStep(int[] p, int[] u, int uLen, int[] x, int xc)
+ {
+ int len = p.length;
+ int count = 0;
+ while (u[0] == 0)
+ {
+ Nat.shiftDownWord(uLen, u, 0);
+ count += 32;
+ }
+
+ {
+ int zeroes = getTrailingZeroes(u[0]);
+ if (zeroes > 0)
+ {
+ Nat.shiftDownBits(uLen, u, zeroes, 0);
+ count += zeroes;
+ }
+ }
+
+ for (int i = 0; i < count; ++i)
+ {
+ if ((x[0] & 1) != 0)
+ {
+ if (xc < 0)
+ {
+ xc += Nat.addTo(len, p, x);
+ }
+ else
+ {
+ xc += Nat.subFrom(len, p, x);
+ }
+ }
+
+// assert xc == 0 || xc == 1;
+ Nat.shiftDownBit(len, x, xc);
+ }
+
+ return xc;
+ }
+
+ private static int getTrailingZeroes(int x)
+ {
+// assert x != 0;
+
+ int count = 0;
+ while ((x & 1) == 0)
+ {
+ x >>>= 1;
+ ++count;
+ }
+ return count;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java
new file mode 100644
index 0000000..75e1543
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java
@@ -0,0 +1,1038 @@
+package org.bouncycastle.math.raw;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.util.Pack;
+
+public abstract class Nat
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ public static int add(int len, int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) + (y[i] & M);
+ z[i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int add33At(int len, int x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zPos + 0] & M) + (x & M);
+ z[zPos + 0] = (int)c;
+ c >>>= 32;
+ c += (z[zPos + 1] & M) + 1L;
+ z[zPos + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zPos + 2);
+ }
+
+ public static int add33At(int len, int x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zOff + zPos] & M) + (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + zPos + 1] & M) + 1L;
+ z[zOff + zPos + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, zPos + 2);
+ }
+
+ public static int add33To(int len, int x, int[] z)
+ {
+ long c = (z[0] & M) + (x & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (z[1] & M) + 1L;
+ z[1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, 2);
+ }
+
+ public static int add33To(int len, int x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) + (x & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 1] & M) + 1L;
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, 2);
+ }
+
+ public static int addBothTo(int len, int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) + (y[i] & M) + (z[i] & M);
+ z[i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int addBothTo(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[xOff + i] & M) + (y[yOff + i] & M) + (z[zOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int addDWordAt(int len, long x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zPos + 0] & M) + (x & M);
+ z[zPos + 0] = (int)c;
+ c >>>= 32;
+ c += (z[zPos + 1] & M) + (x >>> 32);
+ z[zPos + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zPos + 2);
+ }
+
+ public static int addDWordAt(int len, long x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zOff + zPos] & M) + (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + zPos + 1] & M) + (x >>> 32);
+ z[zOff + zPos + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, zPos + 2);
+ }
+
+ public static int addDWordTo(int len, long x, int[] z)
+ {
+ long c = (z[0] & M) + (x & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (z[1] & M) + (x >>> 32);
+ z[1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, 2);
+ }
+
+ public static int addDWordTo(int len, long x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) + (x & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 1] & M) + (x >>> 32);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, 2);
+ }
+
+ public static int addTo(int len, int[] x, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) + (z[i] & M);
+ z[i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int addTo(int len, int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[xOff + i] & M) + (z[zOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int addWordAt(int len, int x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 1);
+ long c = (x & M) + (z[zPos] & M);
+ z[zPos] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zPos + 1);
+ }
+
+ public static int addWordAt(int len, int x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 1);
+ long c = (x & M) + (z[zOff + zPos] & M);
+ z[zOff + zPos] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, zPos + 1);
+ }
+
+ public static int addWordTo(int len, int x, int[] z)
+ {
+ long c = (x & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, 1);
+ }
+
+ public static int addWordTo(int len, int x, int[] z, int zOff)
+ {
+ long c = (x & M) + (z[zOff] & M);
+ z[zOff] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zOff, 1);
+ }
+
+ public static int[] copy(int len, int[] x)
+ {
+ int[] z = new int[len];
+ System.arraycopy(x, 0, z, 0, len);
+ return z;
+ }
+
+ public static void copy(int len, int[] x, int[] z)
+ {
+ System.arraycopy(x, 0, z, 0, len);
+ }
+
+ public static int[] create(int len)
+ {
+ return new int[len];
+ }
+
+ public static int dec(int len, int[] z)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ if (--z[i] != -1)
+ {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public static int dec(int len, int[] x, int[] z)
+ {
+ int i = 0;
+ while (i < len)
+ {
+ int c = x[i] - 1;
+ z[i] = c;
+ ++i;
+ if (c != -1)
+ {
+ while (i < len)
+ {
+ z[i] = x[i];
+ ++i;
+ }
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public static int decAt(int len, int[] z, int zPos)
+ {
+ // assert zPos <= len;
+ for (int i = zPos; i < len; ++i)
+ {
+ if (--z[i] != -1)
+ {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public static int decAt(int len, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= len;
+ for (int i = zPos; i < len; ++i)
+ {
+ if (--z[zOff + i] != -1)
+ {
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public static boolean eq(int len, int[] x, int[] y)
+ {
+ for (int i = len - 1; i >= 0; --i)
+ {
+ if (x[i] != y[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int[] fromBigInteger(int bits, BigInteger x)
+ {
+ if (x.signum() < 0 || x.bitLength() > bits)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int len = (bits + 31) >> 5;
+ int[] z = create(len);
+ int i = 0;
+ while (x.signum() != 0)
+ {
+ z[i++] = x.intValue();
+ x = x.shiftRight(32);
+ }
+ return z;
+ }
+
+ public static int getBit(int[] x, int bit)
+ {
+ if (bit == 0)
+ {
+ return x[0] & 1;
+ }
+ int w = bit >> 5;
+ if (w < 0 || w >= x.length)
+ {
+ return 0;
+ }
+ int b = bit & 31;
+ return (x[w] >>> b) & 1;
+ }
+
+ public static boolean gte(int len, int[] x, int[] y)
+ {
+ for (int i = len - 1; i >= 0; --i)
+ {
+ int x_i = x[i] ^ Integer.MIN_VALUE;
+ int y_i = y[i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static int inc(int len, int[] z)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ if (++z[i] != 0)
+ {
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ public static int inc(int len, int[] x, int[] z)
+ {
+ int i = 0;
+ while (i < len)
+ {
+ int c = x[i] + 1;
+ z[i] = c;
+ ++i;
+ if (c != 0)
+ {
+ while (i < len)
+ {
+ z[i] = x[i];
+ ++i;
+ }
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ public static int incAt(int len, int[] z, int zPos)
+ {
+ // assert zPos <= len;
+ for (int i = zPos; i < len; ++i)
+ {
+ if (++z[i] != 0)
+ {
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ public static int incAt(int len, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= len;
+ for (int i = zPos; i < len; ++i)
+ {
+ if (++z[zOff + i] != 0)
+ {
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ public static boolean isOne(int len, int[] x)
+ {
+ if (x[0] != 1)
+ {
+ return false;
+ }
+ for (int i = 1; i < len; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isZero(int len, int[] x)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void mul(int len, int[] x, int[] y, int[] zz)
+ {
+ zz[len] = mulWord(len, x[0], y, zz);
+
+ for (int i = 1; i < len; ++i)
+ {
+ zz[i + len] = mulWordAddTo(len, x[i], y, 0, zz, i);
+ }
+ }
+
+ public static void mul(int len, int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ zz[zzOff + len] = mulWord(len, x[xOff], y, yOff, zz, zzOff);
+
+ for (int i = 1; i < len; ++i)
+ {
+ zz[zzOff + i + len] = mulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff + i);
+ }
+ }
+
+ public static int mulAddTo(int len, int[] x, int[] y, int[] zz)
+ {
+ long zc = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ long c = mulWordAddTo(len, x[i], y, 0, zz, i) & M;
+ c += zc + (zz[i + len] & M);
+ zz[i + len] = (int)c;
+ zc = c >>> 32;
+ }
+ return (int)zc;
+ }
+
+ public static int mulAddTo(int len, int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long zc = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ long c = mulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff) & M;
+ c += zc + (zz[zzOff + len] & M);
+ zz[zzOff + len] = (int)c;
+ zc = c >>> 32;
+ ++zzOff;
+ }
+ return (int)zc;
+ }
+
+ public static int mul31BothAdd(int len, int a, int[] x, int b, int[] y, int[] z, int zOff)
+ {
+ long c = 0, aVal = a & M, bVal = b & M;
+ int i = 0;
+ do
+ {
+ c += aVal * (x[i] & M) + bVal * (y[i] & M) + (z[zOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < len);
+ return (int)c;
+ }
+
+ public static int mulWord(int len, int x, int[] y, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[i] & M);
+ z[i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < len);
+ return (int)c;
+ }
+
+ public static int mulWord(int len, int x, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[yOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < len);
+ return (int)c;
+ }
+
+ public static int mulWordAddTo(int len, int x, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[yOff + i] & M) + (z[zOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < len);
+ return (int)c;
+ }
+
+ public static int mulWordDwordAddAt(int len, int x, long y, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 3);
+ long c = 0, xVal = x & M;
+ c += xVal * (y & M) + (z[zPos + 0] & M);
+ z[zPos + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y >>> 32) + (z[zPos + 1] & M);
+ z[zPos + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zPos + 2] & M);
+ z[zPos + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : incAt(len, z, zPos + 3);
+ }
+
+ public static int shiftDownBit(int len, int[] z, int c)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[i];
+ z[i] = (next >>> 1) | (c << 31);
+ c = next;
+ }
+ return c << 31;
+ }
+
+ public static int shiftDownBit(int len, int[] z, int zOff, int c)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[zOff + i];
+ z[zOff + i] = (next >>> 1) | (c << 31);
+ c = next;
+ }
+ return c << 31;
+ }
+
+ public static int shiftDownBit(int len, int[] x, int c, int[] z)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = x[i];
+ z[i] = (next >>> 1) | (c << 31);
+ c = next;
+ }
+ return c << 31;
+ }
+
+ public static int shiftDownBit(int len, int[] x, int xOff, int c, int[] z, int zOff)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = x[xOff + i];
+ z[zOff + i] = (next >>> 1) | (c << 31);
+ c = next;
+ }
+ return c << 31;
+ }
+
+ public static int shiftDownBits(int len, int[] z, int bits, int c)
+ {
+// assert bits > 0 && bits < 32;
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[i];
+ z[i] = (next >>> bits) | (c << -bits);
+ c = next;
+ }
+ return c << -bits;
+ }
+
+ public static int shiftDownBits(int len, int[] z, int zOff, int bits, int c)
+ {
+// assert bits > 0 && bits < 32;
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[zOff + i];
+ z[zOff + i] = (next >>> bits) | (c << -bits);
+ c = next;
+ }
+ return c << -bits;
+ }
+
+ public static int shiftDownBits(int len, int[] x, int bits, int c, int[] z)
+ {
+// assert bits > 0 && bits < 32;
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = x[i];
+ z[i] = (next >>> bits) | (c << -bits);
+ c = next;
+ }
+ return c << -bits;
+ }
+
+ public static int shiftDownBits(int len, int[] x, int xOff, int bits, int c, int[] z, int zOff)
+ {
+// assert bits > 0 && bits < 32;
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = x[xOff + i];
+ z[zOff + i] = (next >>> bits) | (c << -bits);
+ c = next;
+ }
+ return c << -bits;
+ }
+
+ public static int shiftDownWord(int len, int[] z, int c)
+ {
+ int i = len;
+ while (--i >= 0)
+ {
+ int next = z[i];
+ z[i] = c;
+ c = next;
+ }
+ return c;
+ }
+
+ public static int shiftUpBit(int len, int[] z, int c)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ int next = z[i];
+ z[i] = (next << 1) | (c >>> 31);
+ c = next;
+ }
+ return c >>> 31;
+ }
+
+ public static int shiftUpBit(int len, int[] z, int zOff, int c)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ int next = z[zOff + i];
+ z[zOff + i] = (next << 1) | (c >>> 31);
+ c = next;
+ }
+ return c >>> 31;
+ }
+
+ public static int shiftUpBit(int len, int[] x, int c, int[] z)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ int next = x[i];
+ z[i] = (next << 1) | (c >>> 31);
+ c = next;
+ }
+ return c >>> 31;
+ }
+
+ public static int shiftUpBit(int len, int[] x, int xOff, int c, int[] z, int zOff)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ int next = x[xOff + i];
+ z[zOff + i] = (next << 1) | (c >>> 31);
+ c = next;
+ }
+ return c >>> 31;
+ }
+
+ public static int shiftUpBits(int len, int[] z, int bits, int c)
+ {
+// assert bits > 0 && bits < 32;
+ for (int i = 0; i < len; ++i)
+ {
+ int next = z[i];
+ z[i] = (next << bits) | (c >>> -bits);
+ c = next;
+ }
+ return c >>> -bits;
+ }
+
+ public static int shiftUpBits(int len, int[] z, int zOff, int bits, int c)
+ {
+// assert bits > 0 && bits < 32;
+ for (int i = 0; i < len; ++i)
+ {
+ int next = z[zOff + i];
+ z[zOff + i] = (next << bits) | (c >>> -bits);
+ c = next;
+ }
+ return c >>> -bits;
+ }
+
+ public static int shiftUpBits(int len, int[] x, int bits, int c, int[] z)
+ {
+// assert bits > 0 && bits < 32;
+ for (int i = 0; i < len; ++i)
+ {
+ int next = x[i];
+ z[i] = (next << bits) | (c >>> -bits);
+ c = next;
+ }
+ return c >>> -bits;
+ }
+
+ public static int shiftUpBits(int len, int[] x, int xOff, int bits, int c, int[] z, int zOff)
+ {
+// assert bits > 0 && bits < 32;
+ for (int i = 0; i < len; ++i)
+ {
+ int next = x[xOff + i];
+ z[zOff + i] = (next << bits) | (c >>> -bits);
+ c = next;
+ }
+ return c >>> -bits;
+ }
+
+ public static void square(int len, int[] x, int[] zz)
+ {
+ int extLen = len << 1;
+ int c = 0;
+ int j = len, k = extLen;
+ do
+ {
+ long xVal = (x[--j] & M);
+ long p = xVal * xVal;
+ zz[--k] = (c << 31) | (int)(p >>> 33);
+ zz[--k] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (j > 0);
+
+ for (int i = 1; i < len; ++i)
+ {
+ c = squareWordAdd(x, i, zz);
+ addWordAt(extLen, c, zz, i << 1);
+ }
+
+ shiftUpBit(extLen, zz, x[0] << 31);
+ }
+
+ public static void square(int len, int[] x, int xOff, int[] zz, int zzOff)
+ {
+ int extLen = len << 1;
+ int c = 0;
+ int j = len, k = extLen;
+ do
+ {
+ long xVal = (x[xOff + --j] & M);
+ long p = xVal * xVal;
+ zz[zzOff + --k] = (c << 31) | (int)(p >>> 33);
+ zz[zzOff + --k] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (j > 0);
+
+ for (int i = 1; i < len; ++i)
+ {
+ c = squareWordAdd(x, xOff, i, zz, zzOff);
+ addWordAt(extLen, c, zz, zzOff, i << 1);
+ }
+
+ shiftUpBit(extLen, zz, zzOff, x[xOff] << 31);
+ }
+
+ public static int squareWordAdd(int[] x, int xPos, int[] z)
+ {
+ long c = 0, xVal = x[xPos] & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (x[i] & M) + (z[xPos + i] & M);
+ z[xPos + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < xPos);
+ return (int)c;
+ }
+
+ public static int squareWordAdd(int[] x, int xOff, int xPos, int[] z, int zOff)
+ {
+ long c = 0, xVal = x[xOff + xPos] & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (x[xOff + i] & M) + (z[xPos + zOff] & M);
+ z[xPos + zOff] = (int)c;
+ c >>>= 32;
+ ++zOff;
+ }
+ while (++i < xPos);
+ return (int)c;
+ }
+
+ public static int sub(int len, int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) - (y[i] & M);
+ z[i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int sub(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[xOff + i] & M) - (y[yOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int sub33At(int len, int x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zPos + 0] & M) - (x & M);
+ z[zPos + 0] = (int)c;
+ c >>= 32;
+ c += (z[zPos + 1] & M) - 1;
+ z[zPos + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zPos + 2);
+ }
+
+ public static int sub33At(int len, int x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zOff + zPos] & M) - (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>= 32;
+ c += (z[zOff + zPos + 1] & M) - 1;
+ z[zOff + zPos + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, zPos + 2);
+ }
+
+ public static int sub33From(int len, int x, int[] z)
+ {
+ long c = (z[0] & M) - (x & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - 1;
+ z[1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, 2);
+ }
+
+ public static int sub33From(int len, int x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) - (x & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - 1;
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, 2);
+ }
+
+ public static int subBothFrom(int len, int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (z[i] & M) - (x[i] & M) - (y[i] & M);
+ z[i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int subBothFrom(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (z[zOff + i] & M) - (x[xOff + i] & M) - (y[yOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int subDWordAt(int len, long x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zPos + 0] & M) - (x & M);
+ z[zPos + 0] = (int)c;
+ c >>= 32;
+ c += (z[zPos + 1] & M) - (x >>> 32);
+ z[zPos + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zPos + 2);
+ }
+
+ public static int subDWordAt(int len, long x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 2);
+ long c = (z[zOff + zPos] & M) - (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>= 32;
+ c += (z[zOff + zPos + 1] & M) - (x >>> 32);
+ z[zOff + zPos + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, zPos + 2);
+ }
+
+ public static int subDWordFrom(int len, long x, int[] z)
+ {
+ long c = (z[0] & M) - (x & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x >>> 32);
+ z[1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, 2);
+ }
+
+ public static int subDWordFrom(int len, long x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) - (x & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - (x >>> 32);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, 2);
+ }
+
+ public static int subFrom(int len, int[] x, int[] z)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (z[i] & M) - (x[i] & M);
+ z[i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int subFrom(int len, int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (z[zOff + i] & M) - (x[xOff + i] & M);
+ z[zOff + i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
+ public static int subWordAt(int len, int x, int[] z, int zPos)
+ {
+ // assert zPos <= (len - 1);
+ long c = (z[zPos] & M) - (x & M);
+ z[zPos] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zPos + 1);
+ }
+
+ public static int subWordAt(int len, int x, int[] z, int zOff, int zPos)
+ {
+ // assert zPos <= (len - 1);
+ long c = (z[zOff + zPos] & M) - (x & M);
+ z[zOff + zPos] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, zPos + 1);
+ }
+
+ public static int subWordFrom(int len, int x, int[] z)
+ {
+ long c = (z[0] & M) - (x & M);
+ z[0] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, 1);
+ }
+
+ public static int subWordFrom(int len, int x, int[] z, int zOff)
+ {
+ long c = (z[zOff + 0] & M) - (x & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ return c == 0 ? 0 : decAt(len, z, zOff, 1);
+ }
+
+ public static BigInteger toBigInteger(int len, int[] x)
+ {
+ byte[] bs = new byte[len << 2];
+ for (int i = 0; i < len; ++i)
+ {
+ int x_i = x[i];
+ if (x_i != 0)
+ {
+ Pack.intToBigEndian(x_i, bs, (len - 1 - i) << 2);
+ }
+ }
+ return new BigInteger(1, bs);
+ }
+
+ public static void zero(int len, int[] z)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ z[i] = 0;
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java
new file mode 100644
index 0000000..e7e3dfa
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java
@@ -0,0 +1,968 @@
+package org.bouncycastle.math.raw;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.util.Pack;
+
+public abstract class Nat192
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ public static int add(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
+ {
+ long c = cIn & M;
+ c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
+ {
+ long c = 0;
+ c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
+ u[uOff + 0] = (int)c;
+ v[vOff + 0] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
+ u[uOff + 1] = (int)c;
+ v[vOff + 1] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
+ u[uOff + 2] = (int)c;
+ v[vOff + 2] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
+ u[uOff + 3] = (int)c;
+ v[vOff + 3] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
+ u[uOff + 4] = (int)c;
+ v[vOff + 4] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
+ u[uOff + 5] = (int)c;
+ v[vOff + 5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static void copy(int[] x, int[] z)
+ {
+ z[0] = x[0];
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ z[4] = x[4];
+ z[5] = x[5];
+ }
+
+ public static int[] create()
+ {
+ return new int[6];
+ }
+
+ public static int[] createExt()
+ {
+ return new int[12];
+ }
+
+ public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ boolean pos = gte(x, xOff, y, yOff);
+ if (pos)
+ {
+ sub(x, xOff, y, yOff, z, zOff);
+ }
+ else
+ {
+ sub(y, yOff, x, xOff, z, zOff);
+ }
+ return pos;
+ }
+
+ public static boolean eq(int[] x, int[] y)
+ {
+ for (int i = 5; i >= 0; --i)
+ {
+ if (x[i] != y[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ if (x.signum() < 0 || x.bitLength() > 192)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[] z = create();
+ int i = 0;
+ while (x.signum() != 0)
+ {
+ z[i++] = x.intValue();
+ x = x.shiftRight(32);
+ }
+ return z;
+ }
+
+ public static int getBit(int[] x, int bit)
+ {
+ if (bit == 0)
+ {
+ return x[0] & 1;
+ }
+ int w = bit >> 5;
+ if (w < 0 || w >= 6)
+ {
+ return 0;
+ }
+ int b = bit & 31;
+ return (x[w] >>> b) & 1;
+ }
+
+ public static boolean gte(int[] x, int[] y)
+ {
+ for (int i = 5; i >= 0; --i)
+ {
+ int x_i = x[i] ^ Integer.MIN_VALUE;
+ int y_i = y[i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean gte(int[] x, int xOff, int[] y, int yOff)
+ {
+ for (int i = 5; i >= 0; --i)
+ {
+ int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
+ int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean isOne(int[] x)
+ {
+ if (x[0] != 1)
+ {
+ return false;
+ }
+ for (int i = 1; i < 6; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isZero(int[] x)
+ {
+ for (int i = 0; i < 6; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+
+ {
+ long c = 0, x_0 = x[0] & M;
+ c += x_0 * y_0;
+ zz[0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[5] = (int)c;
+ c >>>= 32;
+ zz[6] = (int)c;
+ }
+
+ for (int i = 1; i < 6; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ zz[i + 6] = (int)c;
+ }
+ }
+
+ public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+
+ {
+ long c = 0, x_0 = x[xOff + 0] & M;
+ c += x_0 * y_0;
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 6] = (int)c;
+ }
+
+ for (int i = 1; i < 6; ++i)
+ {
+ ++zzOff;
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 6] = (int)c;
+ }
+ }
+
+ public static int mulAddTo(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 6; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ zc = c >>> 32;
+ }
+ return (int)zc;
+ }
+
+ public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 6; ++i)
+ {
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ zc = c >>> 32;
+ ++zzOff;
+ }
+ return (int)zc;
+ }
+
+ public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ // assert w >>> 31 == 0;
+
+ long c = 0, wVal = w & M;
+ long x0 = x[xOff + 0] & M;
+ c += wVal * x0 + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long x1 = x[xOff + 1] & M;
+ c += wVal * x1 + x0 + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ long x2 = x[xOff + 2] & M;
+ c += wVal * x2 + x1 + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ long x3 = x[xOff + 3] & M;
+ c += wVal * x3 + x2 + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ long x4 = x[xOff + 4] & M;
+ c += wVal * x4 + x3 + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ long x5 = x[xOff + 5] & M;
+ c += wVal * x5 + x4 + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += x5;
+ return c;
+ }
+
+ public static int mulWordAddExt(int x, int[] yy, int yyOff, int[] zz, int zzOff)
+ {
+ // assert yyOff <= 6;
+ // assert zzOff <= 6;
+ long c = 0, xVal = x & M;
+ c += xVal * (yy[yyOff + 0] & M) + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 1] & M) + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 2] & M) + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 3] & M) + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 4] & M) + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += xVal * (yy[yyOff + 5] & M) + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 2;
+
+ long c = 0, xVal = x & M;
+ long y00 = y & M;
+ c += xVal * y00 + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long y01 = y >>> 32;
+ c += xVal * y01 + y00 + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += y01 + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(6, z, zOff, 4);
+ }
+
+ public static int mul33WordAdd(int x, int y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 3;
+
+ long c = 0, xVal = x & M, yVal = y & M;
+ c += yVal * xVal + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += yVal + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3);
+ }
+
+ public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert zOff <= 3;
+ long c = 0, xVal = x & M;
+ c += xVal * (y & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y >>> 32) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3);
+ }
+
+ public static int mulWord(int x, int[] y, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < 6);
+ return (int)c;
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ long x_0 = x[0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 5, j = 12;
+ do
+ {
+ long xVal = (x[i--] & M);
+ long p = xVal * xVal;
+ zz[--j] = (c << 31) | (int)(p >>> 33);
+ zz[--j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[1] & M;
+ long zz_2 = zz[2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[2] & M;
+ long zz_3 = zz[3] & M;
+ long zz_4 = zz[4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[3] & M;
+ long zz_5 = zz[5] & M;
+ long zz_6 = zz[6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[4] & M;
+ long zz_7 = zz[7] & M;
+ long zz_8 = zz[8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[5] & M;
+ long zz_9 = zz[9] & M;
+ long zz_10 = zz[10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_10 += zz_9 >>> 32;
+ }
+
+ w = (int)zz_6;
+ zz[6] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_7;
+ zz[7] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_8;
+ zz[8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[10] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[11] + (int)(zz_10 >> 32);
+ zz[11] = (w << 1) | c;
+ }
+
+ public static void square(int[] x, int xOff, int[] zz, int zzOff)
+ {
+ long x_0 = x[xOff + 0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 5, j = 12;
+ do
+ {
+ long xVal = (x[xOff + i--] & M);
+ long p = xVal * xVal;
+ zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
+ zz[zzOff + --j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[zzOff + 0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[xOff + 1] & M;
+ long zz_2 = zz[zzOff + 2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[zzOff + 1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[xOff + 2] & M;
+ long zz_3 = zz[zzOff + 3] & M;
+ long zz_4 = zz[zzOff + 4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[zzOff + 2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[xOff + 3] & M;
+ long zz_5 = zz[zzOff + 5] & M;
+ long zz_6 = zz[zzOff + 6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[zzOff + 3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[xOff + 4] & M;
+ long zz_7 = zz[zzOff + 7] & M;
+ long zz_8 = zz[zzOff + 8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[zzOff + 4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[xOff + 5] & M;
+ long zz_9 = zz[zzOff + 9] & M;
+ long zz_10 = zz[zzOff + 10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[zzOff + 5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_10 += zz_9 >>> 32;
+ }
+
+ w = (int)zz_6;
+ zz[zzOff + 6] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_7;
+ zz[zzOff + 7] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_8;
+ zz[zzOff + 8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[zzOff + 9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[zzOff + 10] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[zzOff + 11] + (int)(zz_10 >> 32);
+ zz[zzOff + 11] = (w << 1) | c;
+ }
+
+ public static int sub(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subBothFrom(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static BigInteger toBigInteger(int[] x)
+ {
+ byte[] bs = new byte[24];
+ for (int i = 0; i < 6; ++i)
+ {
+ int x_i = x[i];
+ if (x_i != 0)
+ {
+ Pack.intToBigEndian(x_i, bs, (5 - i) << 2);
+ }
+ }
+ return new BigInteger(1, bs);
+ }
+
+ public static void zero(int[] z)
+ {
+ z[0] = 0;
+ z[1] = 0;
+ z[2] = 0;
+ z[3] = 0;
+ z[4] = 0;
+ z[5] = 0;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java
new file mode 100644
index 0000000..bbe81ca
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java
@@ -0,0 +1,1182 @@
+package org.bouncycastle.math.raw;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.util.Pack;
+
+public abstract class Nat224
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ public static int add(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (y[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (y[6] & M) + (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
+ {
+ long c = cIn & M;
+ c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
+ {
+ long c = 0;
+ c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
+ u[uOff + 0] = (int)c;
+ v[vOff + 0] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
+ u[uOff + 1] = (int)c;
+ v[vOff + 1] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
+ u[uOff + 2] = (int)c;
+ v[vOff + 2] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
+ u[uOff + 3] = (int)c;
+ v[vOff + 3] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
+ u[uOff + 4] = (int)c;
+ v[vOff + 4] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
+ u[uOff + 5] = (int)c;
+ v[vOff + 5] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 6] & M) + (v[vOff + 6] & M);
+ u[uOff + 6] = (int)c;
+ v[vOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static void copy(int[] x, int[] z)
+ {
+ z[0] = x[0];
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ z[4] = x[4];
+ z[5] = x[5];
+ z[6] = x[6];
+ }
+
+ public static int[] create()
+ {
+ return new int[7];
+ }
+
+ public static int[] createExt()
+ {
+ return new int[14];
+ }
+
+ public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ boolean pos = gte(x, xOff, y, yOff);
+ if (pos)
+ {
+ sub(x, xOff, y, yOff, z, zOff);
+ }
+ else
+ {
+ sub(y, yOff, x, xOff, z, zOff);
+ }
+ return pos;
+ }
+
+ public static boolean eq(int[] x, int[] y)
+ {
+ for (int i = 6; i >= 0; --i)
+ {
+ if (x[i] != y[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ if (x.signum() < 0 || x.bitLength() > 224)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[] z = create();
+ int i = 0;
+ while (x.signum() != 0)
+ {
+ z[i++] = x.intValue();
+ x = x.shiftRight(32);
+ }
+ return z;
+ }
+
+ public static int getBit(int[] x, int bit)
+ {
+ if (bit == 0)
+ {
+ return x[0] & 1;
+ }
+ int w = bit >> 5;
+ if (w < 0 || w >= 7)
+ {
+ return 0;
+ }
+ int b = bit & 31;
+ return (x[w] >>> b) & 1;
+ }
+
+ public static boolean gte(int[] x, int[] y)
+ {
+ for (int i = 6; i >= 0; --i)
+ {
+ int x_i = x[i] ^ Integer.MIN_VALUE;
+ int y_i = y[i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean gte(int[] x, int xOff, int[] y, int yOff)
+ {
+ for (int i = 6; i >= 0; --i)
+ {
+ int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
+ int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean isOne(int[] x)
+ {
+ if (x[0] != 1)
+ {
+ return false;
+ }
+ for (int i = 1; i < 7; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isZero(int[] x)
+ {
+ for (int i = 0; i < 7; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+ long y_6 = y[6] & M;
+
+ {
+ long c = 0, x_0 = x[0] & M;
+ c += x_0 * y_0;
+ zz[0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[5] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_6;
+ zz[6] = (int)c;
+ c >>>= 32;
+ zz[7] = (int)c;
+ }
+
+ for (int i = 1; i < 7; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ c >>>= 32;
+ zz[i + 7] = (int)c;
+ }
+ }
+
+ public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+ long y_6 = y[yOff + 6] & M;
+
+ {
+ long c = 0, x_0 = x[xOff + 0] & M;
+ c += x_0 * y_0;
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_6;
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 7] = (int)c;
+ }
+
+ for (int i = 1; i < 7; ++i)
+ {
+ ++zzOff;
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 7] = (int)c;
+ }
+ }
+
+ public static int mulAddTo(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+ long y_6 = y[6] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 7; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[i + 7] & M);
+ zz[i + 7] = (int)c;
+ zc = c >>> 32;
+ }
+ return (int)zc;
+ }
+
+ public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+ long y_6 = y[yOff + 6] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 7; ++i)
+ {
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[zzOff + 7] & M);
+ zz[zzOff + 7] = (int)c;
+ zc = c >>> 32;
+ ++zzOff;
+ }
+ return (int)zc;
+ }
+
+ public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ // assert w >>> 31 == 0;
+
+ long c = 0, wVal = w & M;
+ long x0 = x[xOff + 0] & M;
+ c += wVal * x0 + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long x1 = x[xOff + 1] & M;
+ c += wVal * x1 + x0 + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ long x2 = x[xOff + 2] & M;
+ c += wVal * x2 + x1 + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ long x3 = x[xOff + 3] & M;
+ c += wVal * x3 + x2 + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ long x4 = x[xOff + 4] & M;
+ c += wVal * x4 + x3 + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ long x5 = x[xOff + 5] & M;
+ c += wVal * x5 + x4 + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ long x6 = x[xOff + 6] & M;
+ c += wVal * x6 + x5 + (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += x6;
+ return c;
+ }
+
+ public static int mulByWord(int x, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mulByWordAddTo(int x, int[] y, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (z[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[6] & M) + (y[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 3;
+
+ long c = 0, xVal = x & M;
+ long y00 = y & M;
+ c += xVal * y00 + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long y01 = y >>> 32;
+ c += xVal * y01 + y00 + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += y01 + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(7, z, zOff, 4);
+ }
+
+ public static int mul33WordAdd(int x, int y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 4;
+
+ long c = 0, xVal = x & M, yVal = y & M;
+ c += yVal * xVal + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += yVal + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(7, z, zOff, 3);
+ }
+
+ public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert zOff <= 4;
+ long c = 0, xVal = x & M;
+ c += xVal * (y & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y >>> 32) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(7, z, zOff, 3);
+ }
+
+ public static int mulWord(int x, int[] y, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < 7);
+ return (int)c;
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ long x_0 = x[0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 6, j = 14;
+ do
+ {
+ long xVal = (x[i--] & M);
+ long p = xVal * xVal;
+ zz[--j] = (c << 31) | (int)(p >>> 33);
+ zz[--j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[1] & M;
+ long zz_2 = zz[2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[2] & M;
+ long zz_3 = zz[3] & M;
+ long zz_4 = zz[4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[3] & M;
+ long zz_5 = zz[5] & M;
+ long zz_6 = zz[6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[4] & M;
+ long zz_7 = zz[7] & M;
+ long zz_8 = zz[8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[5] & M;
+ long zz_9 = zz[9] & M;
+ long zz_10 = zz[10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_6 &= M;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_8 &= M;
+ zz_10 += zz_9 >>> 32;
+ zz_9 &= M;
+ }
+
+ long x_6 = x[6] & M;
+ long zz_11 = zz[11] & M;
+ long zz_12 = zz[12] & M;
+ {
+ zz_6 += x_6 * x_0;
+ w = (int)zz_6;
+ zz[6] = (w << 1) | c;
+ c = w >>> 31;
+ zz_7 += (zz_6 >>> 32) + x_6 * x_1;
+ zz_8 += (zz_7 >>> 32) + x_6 * x_2;
+ zz_9 += (zz_8 >>> 32) + x_6 * x_3;
+ zz_10 += (zz_9 >>> 32) + x_6 * x_4;
+ zz_11 += (zz_10 >>> 32) + x_6 * x_5;
+ zz_12 += zz_11 >>> 32;
+ }
+
+ w = (int)zz_7;
+ zz[7] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_8;
+ zz[8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[10] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_11;
+ zz[11] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_12;
+ zz[12] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[13] + (int)(zz_12 >> 32);
+ zz[13] = (w << 1) | c;
+ }
+
+ public static void square(int[] x, int xOff, int[] zz, int zzOff)
+ {
+ long x_0 = x[xOff + 0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 6, j = 14;
+ do
+ {
+ long xVal = (x[xOff + i--] & M);
+ long p = xVal * xVal;
+ zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
+ zz[zzOff + --j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[zzOff + 0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[xOff + 1] & M;
+ long zz_2 = zz[zzOff + 2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[zzOff + 1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[xOff + 2] & M;
+ long zz_3 = zz[zzOff + 3] & M;
+ long zz_4 = zz[zzOff + 4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[zzOff + 2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[xOff + 3] & M;
+ long zz_5 = zz[zzOff + 5] & M;
+ long zz_6 = zz[zzOff + 6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[zzOff + 3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[xOff + 4] & M;
+ long zz_7 = zz[zzOff + 7] & M;
+ long zz_8 = zz[zzOff + 8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[zzOff + 4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[xOff + 5] & M;
+ long zz_9 = zz[zzOff + 9] & M;
+ long zz_10 = zz[zzOff + 10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[zzOff + 5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_6 &= M;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_8 &= M;
+ zz_10 += zz_9 >>> 32;
+ zz_9 &= M;
+ }
+
+ long x_6 = x[xOff + 6] & M;
+ long zz_11 = zz[zzOff + 11] & M;
+ long zz_12 = zz[zzOff + 12] & M;
+ {
+ zz_6 += x_6 * x_0;
+ w = (int)zz_6;
+ zz[zzOff + 6] = (w << 1) | c;
+ c = w >>> 31;
+ zz_7 += (zz_6 >>> 32) + x_6 * x_1;
+ zz_8 += (zz_7 >>> 32) + x_6 * x_2;
+ zz_9 += (zz_8 >>> 32) + x_6 * x_3;
+ zz_10 += (zz_9 >>> 32) + x_6 * x_4;
+ zz_11 += (zz_10 >>> 32) + x_6 * x_5;
+ zz_12 += zz_11 >>> 32;
+ }
+
+ w = (int)zz_7;
+ zz[zzOff + 7] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_8;
+ zz[zzOff + 8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[zzOff + 9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[zzOff + 10] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_11;
+ zz[zzOff + 11] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_12;
+ zz[zzOff + 12] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[zzOff + 13] + (int)(zz_12 >> 32);
+ zz[zzOff + 13] = (w << 1) | c;
+ }
+
+ public static int sub(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (x[6] & M) - (y[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 6] & M) - (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subBothFrom(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (z[6] & M) - (x[6] & M) - (y[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (z[6] & M) - (x[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 6] & M) - (x[xOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static BigInteger toBigInteger(int[] x)
+ {
+ byte[] bs = new byte[28];
+ for (int i = 0; i < 7; ++i)
+ {
+ int x_i = x[i];
+ if (x_i != 0)
+ {
+ Pack.intToBigEndian(x_i, bs, (6 - i) << 2);
+ }
+ }
+ return new BigInteger(1, bs);
+ }
+
+ public static void zero(int[] z)
+ {
+ z[0] = 0;
+ z[1] = 0;
+ z[2] = 0;
+ z[3] = 0;
+ z[4] = 0;
+ z[5] = 0;
+ z[6] = 0;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java
new file mode 100644
index 0000000..9886678
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java
@@ -0,0 +1,1306 @@
+package org.bouncycastle.math.raw;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.util.Pack;
+
+public abstract class Nat256
+{
+ private static final long M = 0xFFFFFFFFL;
+
+ public static int add(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (y[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += (x[7] & M) + (y[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 7] & M) + (y[yOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (y[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (y[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (y[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (y[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (y[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (y[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (y[6] & M) + (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += (x[7] & M) + (y[7] & M) + (z[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 7] & M) + (y[yOff + 7] & M) + (z[zOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) + (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += (x[1] & M) + (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += (x[2] & M) + (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += (x[3] & M) + (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += (x[4] & M) + (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += (x[5] & M) + (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += (x[6] & M) + (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += (x[7] & M) + (z[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn)
+ {
+ long c = cIn & M;
+ c += (x[xOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += (x[xOff + 7] & M) + (z[zOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int addToEachOther(int[] u, int uOff, int[] v, int vOff)
+ {
+ long c = 0;
+ c += (u[uOff + 0] & M) + (v[vOff + 0] & M);
+ u[uOff + 0] = (int)c;
+ v[vOff + 0] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 1] & M) + (v[vOff + 1] & M);
+ u[uOff + 1] = (int)c;
+ v[vOff + 1] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 2] & M) + (v[vOff + 2] & M);
+ u[uOff + 2] = (int)c;
+ v[vOff + 2] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 3] & M) + (v[vOff + 3] & M);
+ u[uOff + 3] = (int)c;
+ v[vOff + 3] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 4] & M) + (v[vOff + 4] & M);
+ u[uOff + 4] = (int)c;
+ v[vOff + 4] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 5] & M) + (v[vOff + 5] & M);
+ u[uOff + 5] = (int)c;
+ v[vOff + 5] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 6] & M) + (v[vOff + 6] & M);
+ u[uOff + 6] = (int)c;
+ v[vOff + 6] = (int)c;
+ c >>>= 32;
+ c += (u[uOff + 7] & M) + (v[vOff + 7] & M);
+ u[uOff + 7] = (int)c;
+ v[vOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static void copy(int[] x, int[] z)
+ {
+ z[0] = x[0];
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ z[4] = x[4];
+ z[5] = x[5];
+ z[6] = x[6];
+ z[7] = x[7];
+ }
+
+ public static int[] create()
+ {
+ return new int[8];
+ }
+
+ public static int[] createExt()
+ {
+ return new int[16];
+ }
+
+ public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ boolean pos = gte(x, xOff, y, yOff);
+ if (pos)
+ {
+ sub(x, xOff, y, yOff, z, zOff);
+ }
+ else
+ {
+ sub(y, yOff, x, xOff, z, zOff);
+ }
+ return pos;
+ }
+
+ public static boolean eq(int[] x, int[] y)
+ {
+ for (int i = 7; i >= 0; --i)
+ {
+ if (x[i] != y[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int[] fromBigInteger(BigInteger x)
+ {
+ if (x.signum() < 0 || x.bitLength() > 256)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[] z = create();
+ int i = 0;
+ while (x.signum() != 0)
+ {
+ z[i++] = x.intValue();
+ x = x.shiftRight(32);
+ }
+ return z;
+ }
+
+ public static int getBit(int[] x, int bit)
+ {
+ if (bit == 0)
+ {
+ return x[0] & 1;
+ }
+ if ((bit & 255) != bit)
+ {
+ return 0;
+ }
+ int w = bit >>> 5;
+ int b = bit & 31;
+ return (x[w] >>> b) & 1;
+ }
+
+ public static boolean gte(int[] x, int[] y)
+ {
+ for (int i = 7; i >= 0; --i)
+ {
+ int x_i = x[i] ^ Integer.MIN_VALUE;
+ int y_i = y[i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean gte(int[] x, int xOff, int[] y, int yOff)
+ {
+ for (int i = 7; i >= 0; --i)
+ {
+ int x_i = x[xOff + i] ^ Integer.MIN_VALUE;
+ int y_i = y[yOff + i] ^ Integer.MIN_VALUE;
+ if (x_i < y_i)
+ return false;
+ if (x_i > y_i)
+ return true;
+ }
+ return true;
+ }
+
+ public static boolean isOne(int[] x)
+ {
+ if (x[0] != 1)
+ {
+ return false;
+ }
+ for (int i = 1; i < 8; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean isZero(int[] x)
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ if (x[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+ long y_6 = y[6] & M;
+ long y_7 = y[7] & M;
+
+ {
+ long c = 0, x_0 = x[0] & M;
+ c += x_0 * y_0;
+ zz[0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[5] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_6;
+ zz[6] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_7;
+ zz[7] = (int)c;
+ c >>>= 32;
+ zz[8] = (int)c;
+ }
+
+ for (int i = 1; i < 8; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ c >>>= 32;
+ c += x_i * y_7 + (zz[i + 7] & M);
+ zz[i + 7] = (int)c;
+ c >>>= 32;
+ zz[i + 8] = (int)c;
+ }
+ }
+
+ public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+ long y_6 = y[yOff + 6] & M;
+ long y_7 = y[yOff + 7] & M;
+
+ {
+ long c = 0, x_0 = x[xOff + 0] & M;
+ c += x_0 * y_0;
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_1;
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_2;
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_3;
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_4;
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_5;
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_6;
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ c += x_0 * y_7;
+ zz[zzOff + 7] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 8] = (int)c;
+ }
+
+ for (int i = 1; i < 8; ++i)
+ {
+ ++zzOff;
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ c += x_i * y_7 + (zz[zzOff + 7] & M);
+ zz[zzOff + 7] = (int)c;
+ c >>>= 32;
+ zz[zzOff + 8] = (int)c;
+ }
+ }
+
+ public static int mulAddTo(int[] x, int[] y, int[] zz)
+ {
+ long y_0 = y[0] & M;
+ long y_1 = y[1] & M;
+ long y_2 = y[2] & M;
+ long y_3 = y[3] & M;
+ long y_4 = y[4] & M;
+ long y_5 = y[5] & M;
+ long y_6 = y[6] & M;
+ long y_7 = y[7] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 8; ++i)
+ {
+ long c = 0, x_i = x[i] & M;
+ c += x_i * y_0 + (zz[i + 0] & M);
+ zz[i + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[i + 1] & M);
+ zz[i + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[i + 2] & M);
+ zz[i + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[i + 3] & M);
+ zz[i + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[i + 4] & M);
+ zz[i + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[i + 5] & M);
+ zz[i + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[i + 6] & M);
+ zz[i + 6] = (int)c;
+ c >>>= 32;
+ c += x_i * y_7 + (zz[i + 7] & M);
+ zz[i + 7] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[i + 8] & M);
+ zz[i + 8] = (int)c;
+ zc = c >>> 32;
+ }
+ return (int)zc;
+ }
+
+ public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)
+ {
+ long y_0 = y[yOff + 0] & M;
+ long y_1 = y[yOff + 1] & M;
+ long y_2 = y[yOff + 2] & M;
+ long y_3 = y[yOff + 3] & M;
+ long y_4 = y[yOff + 4] & M;
+ long y_5 = y[yOff + 5] & M;
+ long y_6 = y[yOff + 6] & M;
+ long y_7 = y[yOff + 7] & M;
+
+ long zc = 0;
+ for (int i = 0; i < 8; ++i)
+ {
+ long c = 0, x_i = x[xOff + i] & M;
+ c += x_i * y_0 + (zz[zzOff + 0] & M);
+ zz[zzOff + 0] = (int)c;
+ c >>>= 32;
+ c += x_i * y_1 + (zz[zzOff + 1] & M);
+ zz[zzOff + 1] = (int)c;
+ c >>>= 32;
+ c += x_i * y_2 + (zz[zzOff + 2] & M);
+ zz[zzOff + 2] = (int)c;
+ c >>>= 32;
+ c += x_i * y_3 + (zz[zzOff + 3] & M);
+ zz[zzOff + 3] = (int)c;
+ c >>>= 32;
+ c += x_i * y_4 + (zz[zzOff + 4] & M);
+ zz[zzOff + 4] = (int)c;
+ c >>>= 32;
+ c += x_i * y_5 + (zz[zzOff + 5] & M);
+ zz[zzOff + 5] = (int)c;
+ c >>>= 32;
+ c += x_i * y_6 + (zz[zzOff + 6] & M);
+ zz[zzOff + 6] = (int)c;
+ c >>>= 32;
+ c += x_i * y_7 + (zz[zzOff + 7] & M);
+ zz[zzOff + 7] = (int)c;
+ c >>>= 32;
+ c += zc + (zz[zzOff + 8] & M);
+ zz[zzOff + 8] = (int)c;
+ zc = c >>> 32;
+ ++zzOff;
+ }
+ return (int)zc;
+ }
+
+ public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ // assert w >>> 31 == 0;
+
+ long c = 0, wVal = w & M;
+ long x0 = x[xOff + 0] & M;
+ c += wVal * x0 + (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long x1 = x[xOff + 1] & M;
+ c += wVal * x1 + x0 + (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ long x2 = x[xOff + 2] & M;
+ c += wVal * x2 + x1 + (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ long x3 = x[xOff + 3] & M;
+ c += wVal * x3 + x2 + (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ long x4 = x[xOff + 4] & M;
+ c += wVal * x4 + x3 + (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ long x5 = x[xOff + 5] & M;
+ c += wVal * x5 + x4 + (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ long x6 = x[xOff + 6] & M;
+ c += wVal * x6 + x5 + (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ long x7 = x[xOff + 7] & M;
+ c += wVal * x7 + x6 + (y[yOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ c += x7;
+ return c;
+ }
+
+ public static int mulByWord(int x, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (z[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mulByWordAddTo(int x, int[] y, int[] z)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (z[0] & M) + (y[0] & M);
+ z[0] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[1] & M) + (y[1] & M);
+ z[1] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[2] & M) + (y[2] & M);
+ z[2] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[3] & M) + (y[3] & M);
+ z[3] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[4] & M) + (y[4] & M);
+ z[4] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[5] & M) + (y[5] & M);
+ z[5] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[6] & M) + (y[6] & M);
+ z[6] = (int)c;
+ c >>>= 32;
+ c += xVal * (z[7] & M) + (y[7] & M);
+ z[7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>>= 32;
+ c += xVal * (y[yOff + 7] & M) + (z[zOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>>= 32;
+ return (int)c;
+ }
+
+ public static int mul33DWordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 4;
+
+ long c = 0, xVal = x & M;
+ long y00 = y & M;
+ c += xVal * y00 + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ long y01 = y >>> 32;
+ c += xVal * y01 + y00 + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += y01 + (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(8, z, zOff, 4);
+ }
+
+ public static int mul33WordAdd(int x, int y, int[] z, int zOff)
+ {
+ // assert x >>> 31 == 0;
+ // assert zOff <= 5;
+
+ long c = 0, xVal = x & M, yVal = y & M;
+ c += yVal * xVal + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += yVal + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
+ }
+
+ public static int mulWordDwordAdd(int x, long y, int[] z, int zOff)
+ {
+ // assert zOff <= 5;
+ long c = 0, xVal = x & M;
+ c += xVal * (y & M) + (z[zOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>>= 32;
+ c += xVal * (y >>> 32) + (z[zOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>>= 32;
+ c += (z[zOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>>= 32;
+ return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3);
+ }
+
+ public static int mulWord(int x, int[] y, int[] z, int zOff)
+ {
+ long c = 0, xVal = x & M;
+ int i = 0;
+ do
+ {
+ c += xVal * (y[i] & M);
+ z[zOff + i] = (int)c;
+ c >>>= 32;
+ }
+ while (++i < 8);
+ return (int)c;
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ long x_0 = x[0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 7, j = 16;
+ do
+ {
+ long xVal = (x[i--] & M);
+ long p = xVal * xVal;
+ zz[--j] = (c << 31) | (int)(p >>> 33);
+ zz[--j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[1] & M;
+ long zz_2 = zz[2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[2] & M;
+ long zz_3 = zz[3] & M;
+ long zz_4 = zz[4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[3] & M;
+ long zz_5 = zz[5] & M;
+ long zz_6 = zz[6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[4] & M;
+ long zz_7 = zz[7] & M;
+ long zz_8 = zz[8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[5] & M;
+ long zz_9 = zz[9] & M;
+ long zz_10 = zz[10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_6 &= M;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_8 &= M;
+ zz_10 += zz_9 >>> 32;
+ zz_9 &= M;
+ }
+
+ long x_6 = x[6] & M;
+ long zz_11 = zz[11] & M;
+ long zz_12 = zz[12] & M;
+ {
+ zz_6 += x_6 * x_0;
+ w = (int)zz_6;
+ zz[6] = (w << 1) | c;
+ c = w >>> 31;
+ zz_7 += (zz_6 >>> 32) + x_6 * x_1;
+ zz_8 += (zz_7 >>> 32) + x_6 * x_2;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_6 * x_3;
+ zz_8 &= M;
+ zz_10 += (zz_9 >>> 32) + x_6 * x_4;
+ zz_9 &= M;
+ zz_11 += (zz_10 >>> 32) + x_6 * x_5;
+ zz_10 &= M;
+ zz_12 += zz_11 >>> 32;
+ zz_11 &= M;
+ }
+
+ long x_7 = x[7] & M;
+ long zz_13 = zz[13] & M;
+ long zz_14 = zz[14] & M;
+ {
+ zz_7 += x_7 * x_0;
+ w = (int)zz_7;
+ zz[7] = (w << 1) | c;
+ c = w >>> 31;
+ zz_8 += (zz_7 >>> 32) + x_7 * x_1;
+ zz_9 += (zz_8 >>> 32) + x_7 * x_2;
+ zz_10 += (zz_9 >>> 32) + x_7 * x_3;
+ zz_11 += (zz_10 >>> 32) + x_7 * x_4;
+ zz_12 += (zz_11 >>> 32) + x_7 * x_5;
+ zz_13 += (zz_12 >>> 32) + x_7 * x_6;
+ zz_14 += zz_13 >>> 32;
+ }
+
+ w = (int)zz_8;
+ zz[8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[10] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_11;
+ zz[11] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_12;
+ zz[12] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_13;
+ zz[13] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_14;
+ zz[14] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[15] + (int)(zz_14 >> 32);
+ zz[15] = (w << 1) | c;
+ }
+
+ public static void square(int[] x, int xOff, int[] zz, int zzOff)
+ {
+ long x_0 = x[xOff + 0] & M;
+ long zz_1;
+
+ int c = 0, w;
+ {
+ int i = 7, j = 16;
+ do
+ {
+ long xVal = (x[xOff + i--] & M);
+ long p = xVal * xVal;
+ zz[zzOff + --j] = (c << 31) | (int)(p >>> 33);
+ zz[zzOff + --j] = (int)(p >>> 1);
+ c = (int)p;
+ }
+ while (i > 0);
+
+ {
+ long p = x_0 * x_0;
+ zz_1 = ((c << 31) & M) | (p >>> 33);
+ zz[zzOff + 0] = (int)p;
+ c = (int)(p >>> 32) & 1;
+ }
+ }
+
+ long x_1 = x[xOff + 1] & M;
+ long zz_2 = zz[zzOff + 2] & M;
+
+ {
+ zz_1 += x_1 * x_0;
+ w = (int)zz_1;
+ zz[zzOff + 1] = (w << 1) | c;
+ c = w >>> 31;
+ zz_2 += zz_1 >>> 32;
+ }
+
+ long x_2 = x[xOff + 2] & M;
+ long zz_3 = zz[zzOff + 3] & M;
+ long zz_4 = zz[zzOff + 4] & M;
+ {
+ zz_2 += x_2 * x_0;
+ w = (int)zz_2;
+ zz[zzOff + 2] = (w << 1) | c;
+ c = w >>> 31;
+ zz_3 += (zz_2 >>> 32) + x_2 * x_1;
+ zz_4 += zz_3 >>> 32;
+ zz_3 &= M;
+ }
+
+ long x_3 = x[xOff + 3] & M;
+ long zz_5 = zz[zzOff + 5] & M;
+ long zz_6 = zz[zzOff + 6] & M;
+ {
+ zz_3 += x_3 * x_0;
+ w = (int)zz_3;
+ zz[zzOff + 3] = (w << 1) | c;
+ c = w >>> 31;
+ zz_4 += (zz_3 >>> 32) + x_3 * x_1;
+ zz_5 += (zz_4 >>> 32) + x_3 * x_2;
+ zz_4 &= M;
+ zz_6 += zz_5 >>> 32;
+ zz_5 &= M;
+ }
+
+ long x_4 = x[xOff + 4] & M;
+ long zz_7 = zz[zzOff + 7] & M;
+ long zz_8 = zz[zzOff + 8] & M;
+ {
+ zz_4 += x_4 * x_0;
+ w = (int)zz_4;
+ zz[zzOff + 4] = (w << 1) | c;
+ c = w >>> 31;
+ zz_5 += (zz_4 >>> 32) + x_4 * x_1;
+ zz_6 += (zz_5 >>> 32) + x_4 * x_2;
+ zz_5 &= M;
+ zz_7 += (zz_6 >>> 32) + x_4 * x_3;
+ zz_6 &= M;
+ zz_8 += zz_7 >>> 32;
+ zz_7 &= M;
+ }
+
+ long x_5 = x[xOff + 5] & M;
+ long zz_9 = zz[zzOff + 9] & M;
+ long zz_10 = zz[zzOff + 10] & M;
+ {
+ zz_5 += x_5 * x_0;
+ w = (int)zz_5;
+ zz[zzOff + 5] = (w << 1) | c;
+ c = w >>> 31;
+ zz_6 += (zz_5 >>> 32) + x_5 * x_1;
+ zz_7 += (zz_6 >>> 32) + x_5 * x_2;
+ zz_6 &= M;
+ zz_8 += (zz_7 >>> 32) + x_5 * x_3;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_5 * x_4;
+ zz_8 &= M;
+ zz_10 += zz_9 >>> 32;
+ zz_9 &= M;
+ }
+
+ long x_6 = x[xOff + 6] & M;
+ long zz_11 = zz[zzOff + 11] & M;
+ long zz_12 = zz[zzOff + 12] & M;
+ {
+ zz_6 += x_6 * x_0;
+ w = (int)zz_6;
+ zz[zzOff + 6] = (w << 1) | c;
+ c = w >>> 31;
+ zz_7 += (zz_6 >>> 32) + x_6 * x_1;
+ zz_8 += (zz_7 >>> 32) + x_6 * x_2;
+ zz_7 &= M;
+ zz_9 += (zz_8 >>> 32) + x_6 * x_3;
+ zz_8 &= M;
+ zz_10 += (zz_9 >>> 32) + x_6 * x_4;
+ zz_9 &= M;
+ zz_11 += (zz_10 >>> 32) + x_6 * x_5;
+ zz_10 &= M;
+ zz_12 += zz_11 >>> 32;
+ zz_11 &= M;
+ }
+
+ long x_7 = x[xOff + 7] & M;
+ long zz_13 = zz[zzOff + 13] & M;
+ long zz_14 = zz[zzOff + 14] & M;
+ {
+ zz_7 += x_7 * x_0;
+ w = (int)zz_7;
+ zz[zzOff + 7] = (w << 1) | c;
+ c = w >>> 31;
+ zz_8 += (zz_7 >>> 32) + x_7 * x_1;
+ zz_9 += (zz_8 >>> 32) + x_7 * x_2;
+ zz_10 += (zz_9 >>> 32) + x_7 * x_3;
+ zz_11 += (zz_10 >>> 32) + x_7 * x_4;
+ zz_12 += (zz_11 >>> 32) + x_7 * x_5;
+ zz_13 += (zz_12 >>> 32) + x_7 * x_6;
+ zz_14 += zz_13 >>> 32;
+ }
+
+ w = (int)zz_8;
+ zz[zzOff + 8] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_9;
+ zz[zzOff + 9] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_10;
+ zz[zzOff + 10] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_11;
+ zz[zzOff + 11] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_12;
+ zz[zzOff + 12] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_13;
+ zz[zzOff + 13] = (w << 1) | c;
+ c = w >>> 31;
+ w = (int)zz_14;
+ zz[zzOff + 14] = (w << 1) | c;
+ c = w >>> 31;
+ w = zz[zzOff + 15] + (int)(zz_14 >> 32);
+ zz[zzOff + 15] = (w << 1) | c;
+ }
+
+ public static int sub(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (x[6] & M) - (y[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ c += (x[7] & M) - (y[7] & M);
+ z[7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (x[xOff + 0] & M) - (y[yOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 1] & M) - (y[yOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 2] & M) - (y[yOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 3] & M) - (y[yOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 4] & M) - (y[yOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 5] & M) - (y[yOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 6] & M) - (y[yOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>= 32;
+ c += (x[xOff + 7] & M) - (y[yOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subBothFrom(int[] x, int[] y, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M) - (y[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M) - (y[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M) - (y[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M) - (y[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M) - (y[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M) - (y[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (z[6] & M) - (x[6] & M) - (y[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ c += (z[7] & M) - (x[7] & M) - (y[7] & M);
+ z[7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int[] z)
+ {
+ long c = 0;
+ c += (z[0] & M) - (x[0] & M);
+ z[0] = (int)c;
+ c >>= 32;
+ c += (z[1] & M) - (x[1] & M);
+ z[1] = (int)c;
+ c >>= 32;
+ c += (z[2] & M) - (x[2] & M);
+ z[2] = (int)c;
+ c >>= 32;
+ c += (z[3] & M) - (x[3] & M);
+ z[3] = (int)c;
+ c >>= 32;
+ c += (z[4] & M) - (x[4] & M);
+ z[4] = (int)c;
+ c >>= 32;
+ c += (z[5] & M) - (x[5] & M);
+ z[5] = (int)c;
+ c >>= 32;
+ c += (z[6] & M) - (x[6] & M);
+ z[6] = (int)c;
+ c >>= 32;
+ c += (z[7] & M) - (x[7] & M);
+ z[7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static int subFrom(int[] x, int xOff, int[] z, int zOff)
+ {
+ long c = 0;
+ c += (z[zOff + 0] & M) - (x[xOff + 0] & M);
+ z[zOff + 0] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 1] & M) - (x[xOff + 1] & M);
+ z[zOff + 1] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 2] & M) - (x[xOff + 2] & M);
+ z[zOff + 2] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 3] & M) - (x[xOff + 3] & M);
+ z[zOff + 3] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 4] & M) - (x[xOff + 4] & M);
+ z[zOff + 4] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 5] & M) - (x[xOff + 5] & M);
+ z[zOff + 5] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 6] & M) - (x[xOff + 6] & M);
+ z[zOff + 6] = (int)c;
+ c >>= 32;
+ c += (z[zOff + 7] & M) - (x[xOff + 7] & M);
+ z[zOff + 7] = (int)c;
+ c >>= 32;
+ return (int)c;
+ }
+
+ public static BigInteger toBigInteger(int[] x)
+ {
+ byte[] bs = new byte[32];
+ for (int i = 0; i < 8; ++i)
+ {
+ int x_i = x[i];
+ if (x_i != 0)
+ {
+ Pack.intToBigEndian(x_i, bs, (7 - i) << 2);
+ }
+ }
+ return new BigInteger(1, bs);
+ }
+
+ public static void zero(int[] z)
+ {
+ z[0] = 0;
+ z[1] = 0;
+ z[2] = 0;
+ z[3] = 0;
+ z[4] = 0;
+ z[5] = 0;
+ z[6] = 0;
+ z[7] = 0;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat384.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat384.java
new file mode 100644
index 0000000..889550e
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat384.java
@@ -0,0 +1,43 @@
+package org.bouncycastle.math.raw;
+
+
+public abstract class Nat384
+{
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ Nat192.mul(x, y, zz);
+ Nat192.mul(x, 6, y, 6, zz, 12);
+
+ int c18 = Nat192.addToEachOther(zz, 6, zz, 12);
+ int c12 = c18 + Nat192.addTo(zz, 0, zz, 6, 0);
+ c18 += Nat192.addTo(zz, 18, zz, 12, c12);
+
+ int[] dx = Nat192.create(), dy = Nat192.create();
+ boolean neg = Nat192.diff(x, 6, x, 0, dx, 0) != Nat192.diff(y, 6, y, 0, dy, 0);
+
+ int[] tt = Nat192.createExt();
+ Nat192.mul(dx, dy, tt);
+
+ c18 += neg ? Nat.addTo(12, tt, 0, zz, 6) : Nat.subFrom(12, tt, 0, zz, 6);
+ Nat.addWordAt(24, c18, zz, 18);
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ Nat192.square(x, zz);
+ Nat192.square(x, 6, zz, 12);
+
+ int c18 = Nat192.addToEachOther(zz, 6, zz, 12);
+ int c12 = c18 + Nat192.addTo(zz, 0, zz, 6, 0);
+ c18 += Nat192.addTo(zz, 18, zz, 12, c12);
+
+ int[] dx = Nat192.create();
+ Nat192.diff(x, 6, x, 0, dx, 0);
+
+ int[] tt = Nat192.createExt();
+ Nat192.square(dx, tt);
+
+ c18 += Nat.subFrom(12, tt, 0, zz, 6);
+ Nat.addWordAt(24, c18, zz, 18);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat512.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat512.java
new file mode 100644
index 0000000..594e8f5
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat512.java
@@ -0,0 +1,43 @@
+package org.bouncycastle.math.raw;
+
+
+public abstract class Nat512
+{
+ public static void mul(int[] x, int[] y, int[] zz)
+ {
+ Nat256.mul(x, y, zz);
+ Nat256.mul(x, 8, y, 8, zz, 16);
+
+ int c24 = Nat256.addToEachOther(zz, 8, zz, 16);
+ int c16 = c24 + Nat256.addTo(zz, 0, zz, 8, 0);
+ c24 += Nat256.addTo(zz, 24, zz, 16, c16);
+
+ int[] dx = Nat256.create(), dy = Nat256.create();
+ boolean neg = Nat256.diff(x, 8, x, 0, dx, 0) != Nat256.diff(y, 8, y, 0, dy, 0);
+
+ int[] tt = Nat256.createExt();
+ Nat256.mul(dx, dy, tt);
+
+ c24 += neg ? Nat.addTo(16, tt, 0, zz, 8) : Nat.subFrom(16, tt, 0, zz, 8);
+ Nat.addWordAt(32, c24, zz, 24);
+ }
+
+ public static void square(int[] x, int[] zz)
+ {
+ Nat256.square(x, zz);
+ Nat256.square(x, 8, zz, 16);
+
+ int c24 = Nat256.addToEachOther(zz, 8, zz, 16);
+ int c16 = c24 + Nat256.addTo(zz, 0, zz, 8, 0);
+ c24 += Nat256.addTo(zz, 24, zz, 16, c16);
+
+ int[] dx = Nat256.create();
+ Nat256.diff(x, 8, x, 0, dx, 0);
+
+ int[] tt = Nat256.createExt();
+ Nat256.square(dx, tt);
+
+ c24 += Nat.subFrom(16, tt, 0, zz, 8);
+ Nat.addWordAt(32, c24, zz, 24);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
index 3f7677c..64ce17c 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
@@ -323,6 +323,25 @@ public final class Arrays
return hc;
}
+
+ public static int hashCode(byte[] data, int off, int len)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = len;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[off + i];
+ }
+
+ return hc;
+ }
public static int hashCode(char[] data)
{
@@ -374,6 +393,25 @@ public final class Arrays
return hc;
}
+ public static int hashCode(int[] data, int off, int len)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = len;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[off + i];
+ }
+
+ return hc;
+ }
+
public static int hashCode(short[][][] shorts)
{
int hc = 0;
@@ -752,6 +790,20 @@ public final class Arrays
return result;
}
+ public static short[] append(short[] a, short b)
+ {
+ if (a == null)
+ {
+ return new short[]{ b };
+ }
+
+ int length = a.length;
+ short[] result = new short[length + 1];
+ System.arraycopy(a, 0, result, 0, length);
+ result[length] = b;
+ return result;
+ }
+
public static int[] append(int[] a, int b)
{
if (a == null)
@@ -840,6 +892,23 @@ public final class Arrays
}
}
+ public static int[] concatenate(int[] a, int[] b)
+ {
+ if (a == null)
+ {
+ return clone(b);
+ }
+ if (b == null)
+ {
+ return clone(a);
+ }
+
+ int[] c = new int[a.length + b.length];
+ System.arraycopy(a, 0, c, 0, a.length);
+ System.arraycopy(b, 0, c, a.length, b.length);
+ return c;
+ }
+
public static byte[] prepend(byte[] a, byte b)
{
if (a == null)
@@ -853,4 +922,50 @@ public final class Arrays
result[0] = b;
return result;
}
+
+ public static short[] prepend(short[] a, short b)
+ {
+ if (a == null)
+ {
+ return new short[]{ b };
+ }
+
+ int length = a.length;
+ short[] result = new short[length + 1];
+ System.arraycopy(a, 0, result, 1, length);
+ result[0] = b;
+ return result;
+ }
+
+ public static int[] prepend(int[] a, int b)
+ {
+ if (a == null)
+ {
+ return new int[]{ b };
+ }
+
+ int length = a.length;
+ int[] result = new int[length + 1];
+ System.arraycopy(a, 0, result, 1, length);
+ result[0] = b;
+ return result;
+ }
+
+ public static byte[] reverse(byte[] a)
+ {
+ if (a == null)
+ {
+ return null;
+ }
+
+ int p1 = 0, p2 = a.length;
+ byte[] result = new byte[p2];
+
+ while (--p2 >= 0)
+ {
+ result[p2] = a[p1++];
+ }
+
+ return result;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Integers.java b/bcprov/src/main/java/org/bouncycastle/util/Integers.java
index 599a9e0..f52baf5 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Integers.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Integers.java
@@ -2,6 +2,16 @@ package org.bouncycastle.util;
public class Integers
{
+ public static int rotateLeft(int i, int distance)
+ {
+ return Integer.rotateLeft(i, distance);
+ }
+
+ public static int rotateRight(int i, int distance)
+ {
+ return Integer.rotateRight(i, distance);
+ }
+
public static Integer valueOf(int value)
{
return Integer.valueOf(value);
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Memoable.java b/bcprov/src/main/java/org/bouncycastle/util/Memoable.java
index 0be9171..ee0beda 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Memoable.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Memoable.java
@@ -4,7 +4,7 @@ public interface Memoable
{
/**
* Produce a copy of this object with its configuration and in its current state.
- * <p/>
+ * <p>
* The returned object may be used simply to store the state, or may be used as a similar object
* starting from the copied state.
*/
@@ -12,7 +12,7 @@ public interface Memoable
/**
* Restore a copied object state into this object.
- * <p/>
+ * <p>
* Implementations of this method <em>should</em> try to avoid or minimise memory allocation to perform the reset.
*
* @param other an object originally {@link #copy() copied} from an object of the same type as this instance.
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Pack.java b/bcprov/src/main/java/org/bouncycastle/util/Pack.java
new file mode 100644
index 0000000..2f96af8
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/util/Pack.java
@@ -0,0 +1,201 @@
+package org.bouncycastle.util;
+
+public abstract class Pack
+{
+ public static int bigEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] << 24;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff);
+ return n;
+ }
+
+ public static void bigEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = bigEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static byte[] intToBigEndian(int n)
+ {
+ byte[] bs = new byte[4];
+ intToBigEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void intToBigEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n >>> 24);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n );
+ }
+
+ public static byte[] intToBigEndian(int[] ns)
+ {
+ byte[] bs = new byte[4 * ns.length];
+ intToBigEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void intToBigEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToBigEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long bigEndianToLong(byte[] bs, int off)
+ {
+ int hi = bigEndianToInt(bs, off);
+ int lo = bigEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void bigEndianToLong(byte[] bs, int off, long[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = bigEndianToLong(bs, off);
+ off += 8;
+ }
+ }
+
+ public static byte[] longToBigEndian(long n)
+ {
+ byte[] bs = new byte[8];
+ longToBigEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void longToBigEndian(long n, byte[] bs, int off)
+ {
+ intToBigEndian((int)(n >>> 32), bs, off);
+ intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
+ }
+
+ public static byte[] longToBigEndian(long[] ns)
+ {
+ byte[] bs = new byte[8 * ns.length];
+ longToBigEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void longToBigEndian(long[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ longToBigEndian(ns[i], bs, off);
+ off += 8;
+ }
+ }
+
+ public static int littleEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] & 0xff;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= bs[++off] << 24;
+ return n;
+ }
+
+ public static void littleEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = littleEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ ns[nOff + i] = littleEndianToInt(bs, bOff);
+ bOff += 4;
+ }
+ }
+
+ public static byte[] intToLittleEndian(int n)
+ {
+ byte[] bs = new byte[4];
+ intToLittleEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void intToLittleEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n );
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 24);
+ }
+
+ public static byte[] intToLittleEndian(int[] ns)
+ {
+ byte[] bs = new byte[4 * ns.length];
+ intToLittleEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void intToLittleEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToLittleEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long littleEndianToLong(byte[] bs, int off)
+ {
+ int lo = littleEndianToInt(bs, off);
+ int hi = littleEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void littleEndianToLong(byte[] bs, int off, long[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = littleEndianToLong(bs, off);
+ off += 8;
+ }
+ }
+
+ public static byte[] longToLittleEndian(long n)
+ {
+ byte[] bs = new byte[8];
+ longToLittleEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void longToLittleEndian(long n, byte[] bs, int off)
+ {
+ intToLittleEndian((int)(n & 0xffffffffL), bs, off);
+ intToLittleEndian((int)(n >>> 32), bs, off + 4);
+ }
+
+ public static byte[] longToLittleEndian(long[] ns)
+ {
+ byte[] bs = new byte[8 * ns.length];
+ longToLittleEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void longToLittleEndian(long[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ longToLittleEndian(ns[i], bs, off);
+ off += 8;
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Strings.java b/bcprov/src/main/java/org/bouncycastle/util/Strings.java
index 7f67404..770edaa 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Strings.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Strings.java
@@ -241,6 +241,17 @@ public final class Strings
return bytes;
}
+ public static int toByteArray(String s, byte[] buf, int off)
+ {
+ int count = s.length();
+ for (int i = 0; i < count; ++i)
+ {
+ char c = s.charAt(i);
+ buf[off + i] = (byte)c;
+ }
+ return count;
+ }
+
/**
* Convert an array of 8 bit characters into a string.
*
diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64.java b/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64.java
index 8380629..c04a8cc 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64.java
@@ -6,6 +6,9 @@ import java.io.OutputStream;
import org.bouncycastle.util.Strings;
+/**
+ * Utility class for converting Base64 data to bytes and back again.
+ */
public class Base64
{
private static final Encoder encoder = new Base64Encoder();
diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java b/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java
index 1ef8f51..abad02c 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java
@@ -3,24 +3,27 @@ package org.bouncycastle.util.encoders;
import java.io.IOException;
import java.io.OutputStream;
+/**
+ * A streaming Base64 encoder.
+ */
public class Base64Encoder
implements Encoder
{
protected final byte[] encodingTable =
- {
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v',
- (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
- (byte)'7', (byte)'8', (byte)'9',
- (byte)'+', (byte)'/'
- };
+ {
+ (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+ (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+ (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+ (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+ (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+ (byte)'v',
+ (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
+ (byte)'7', (byte)'8', (byte)'9',
+ (byte)'+', (byte)'/'
+ };
protected byte padding = (byte)'=';
diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/DecoderException.java b/bcprov/src/main/java/org/bouncycastle/util/encoders/DecoderException.java
index d9914a2..1e6782a 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/encoders/DecoderException.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/DecoderException.java
@@ -1,5 +1,8 @@
package org.bouncycastle.util.encoders;
+/**
+ * Exception thrown if an attempt is made to decode invalid data, or some other failure occurs.
+ */
public class DecoderException
extends IllegalStateException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/EncoderException.java b/bcprov/src/main/java/org/bouncycastle/util/encoders/EncoderException.java
index 2d09a63..a1eb411 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/encoders/EncoderException.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/EncoderException.java
@@ -1,5 +1,8 @@
package org.bouncycastle.util.encoders;
+/**
+ * Exception thrown if an attempt is made to encode invalid data, or some other failure occurs.
+ */
public class EncoderException
extends IllegalStateException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/Hex.java b/bcprov/src/main/java/org/bouncycastle/util/encoders/Hex.java
index d49f1ef..63e9c71 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/encoders/Hex.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/Hex.java
@@ -6,6 +6,9 @@ import java.io.OutputStream;
import org.bouncycastle.util.Strings;
+/**
+ * Utility class for converting hex data to bytes and back again.
+ */
public class Hex
{
private static final Encoder encoder = new HexEncoder();
diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/HexEncoder.java b/bcprov/src/main/java/org/bouncycastle/util/encoders/HexEncoder.java
index 3bb594b..52f8fa6 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/encoders/HexEncoder.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/HexEncoder.java
@@ -3,15 +3,18 @@ package org.bouncycastle.util.encoders;
import java.io.IOException;
import java.io.OutputStream;
+/**
+ * A streaming Hex encoder.
+ */
public class HexEncoder
implements Encoder
{
protected final byte[] encodingTable =
- {
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
- (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
- };
-
+ {
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+ (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
+ };
+
/*
* set up the decoding table.
*/
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java b/bcprov/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java
index 01af8da..ed5518d 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java
@@ -2,6 +2,9 @@ package org.bouncycastle.util.io;
import java.io.IOException;
+/**
+ * Exception thrown when too much data is written to an InputStream
+ */
public class StreamOverflowException
extends IOException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java b/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java
index 41560b5..0dea236 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java
@@ -5,10 +5,19 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+/**
+ * Utility methods to assist with stream processing.
+ */
public final class Streams
{
private static int BUFFER_SIZE = 512;
+ /**
+ * Read stream till EOF is encountered.
+ *
+ * @param inStr stream to be emptied.
+ * @throws IOException in case of underlying IOException.
+ */
public static void drain(InputStream inStr)
throws IOException
{
@@ -18,6 +27,13 @@ public final class Streams
}
}
+ /**
+ * Read stream fully, returning contents in a byte array.
+ *
+ * @param inStr stream to be read.
+ * @return a byte array representing the contents of inStr.
+ * @throws IOException in case of underlying IOException.
+ */
public static byte[] readAll(InputStream inStr)
throws IOException
{
@@ -26,6 +42,15 @@ public final class Streams
return buf.toByteArray();
}
+ /**
+ * Read from inStr up to a maximum number of bytes, throwing an exception if more the maximum amount
+ * of requested data is available.
+ *
+ * @param inStr stream to be read.
+ * @param limit maximum number of bytes that can be read.
+ * @return a byte array representing the contents of inStr.
+ * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it.
+ */
public static byte[] readAllLimited(InputStream inStr, int limit)
throws IOException
{
@@ -34,12 +59,30 @@ public final class Streams
return buf.toByteArray();
}
+ /**
+ * Fully read in buf's length in data, or up to EOF, whichever occurs first,
+ *
+ * @param inStr the stream to be read.
+ * @param buf the buffer to be read into.
+ * @return the number of bytes read into the buffer.
+ * @throws IOException in case of underlying IOException.
+ */
public static int readFully(InputStream inStr, byte[] buf)
throws IOException
{
return readFully(inStr, buf, 0, buf.length);
}
+ /**
+ * Fully read in len's bytes of data into buf, or up to EOF, whichever occurs first,
+ *
+ * @param inStr the stream to be read.
+ * @param buf the buffer to be read into.
+ * @param off offset into buf to start putting bytes into.
+ * @param len the number of bytes to be read.
+ * @return the number of bytes read into the buffer.
+ * @throws IOException in case of underlying IOException.
+ */
public static int readFully(InputStream inStr, byte[] buf, int off, int len)
throws IOException
{
@@ -56,6 +99,13 @@ public final class Streams
return totalRead;
}
+ /**
+ * Write the full contents of inStr to the destination stream outStr.
+ *
+ * @param inStr source input stream.
+ * @param outStr destination output stream.
+ * @throws IOException in case of underlying IOException.
+ */
public static void pipeAll(InputStream inStr, OutputStream outStr)
throws IOException
{
@@ -67,6 +117,14 @@ public final class Streams
}
}
+ /**
+ * Write up to limit bytes of data from inStr to the destination stream outStr.
+ *
+ * @param inStr source input stream.
+ * @param limit the maximum number of bytes allowed to be read.
+ * @param outStr destination output stream.
+ * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it.
+ */
public static long pipeAllLimited(InputStream inStr, long limit, OutputStream outStr)
throws IOException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/TeeInputStream.java b/bcprov/src/main/java/org/bouncycastle/util/io/TeeInputStream.java
index 9154246..96da169 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/TeeInputStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/TeeInputStream.java
@@ -4,12 +4,21 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+/**
+ * An input stream which copies anything read through it to another stream.
+ */
public class TeeInputStream
extends InputStream
{
private final InputStream input;
private final OutputStream output;
+ /**
+ * Base constructor.
+ *
+ * @param input input stream to be wrapped.
+ * @param output output stream to copy any input read to.
+ */
public TeeInputStream(InputStream input, OutputStream output)
{
this.input = input;
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java b/bcprov/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java
index a4919cd..05b2b56 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java
@@ -3,12 +3,22 @@ package org.bouncycastle.util.io;
import java.io.IOException;
import java.io.OutputStream;
+
+/**
+ * An output stream which copies anything written into it to another stream.
+ */
public class TeeOutputStream
extends OutputStream
{
private OutputStream output1;
private OutputStream output2;
+ /**
+ * Base constructor.
+ *
+ * @param output1 the output stream that is wrapped.
+ * @param output2 a secondary stream that anything written to output1 is also written to.
+ */
public TeeOutputStream(OutputStream output1, OutputStream output2)
{
this.output1 = output1;
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java
index 69a773e..63f61f2 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java
@@ -2,6 +2,9 @@ package org.bouncycastle.util.io.pem;
import java.io.IOException;
+/**
+ * Exception thrown on failure to generate a PEM object.
+ */
public class PemGenerationException
extends IOException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java
index b201c13..bbc6108 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java
@@ -1,10 +1,19 @@
package org.bouncycastle.util.io.pem;
+/**
+ * Class representing a PEM header (name, value) pair.
+ */
public class PemHeader
{
private String name;
private String value;
+ /**
+ * Base constructor.
+ *
+ * @param name name of the header property.
+ * @param value value of the header property.
+ */
public PemHeader(String name, String value)
{
this.name = name;
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObject.java b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObject.java
index 2199520..606330d 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObject.java
@@ -4,6 +4,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+/**
+ * A generic PEM object - type, header properties, and byte content.
+ */
public class PemObject
implements PemObjectGenerator
{
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java
index 6fffdc5..9664639 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java
@@ -1,7 +1,16 @@
package org.bouncycastle.util.io.pem;
+/**
+ * Base interface for generators of PEM objects.
+ */
public interface PemObjectGenerator
{
+ /**
+ * Generate a PEM object.
+ *
+ * @return the generated object.
+ * @throws PemGenerationException on failure.
+ */
PemObject generate()
throws PemGenerationException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java
index b18b550..933da6a 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java
@@ -2,8 +2,18 @@ package org.bouncycastle.util.io.pem;
import java.io.IOException;
+/**
+ * Base interface for parsers to convert PEM objects into specific objects.
+ */
public interface PemObjectParser
{
+ /**
+ * Parse an object out of the PEM object passed in.
+ *
+ * @param obj the PEM object containing the details for the specific object.
+ * @return a specific object represented by the PEM object.
+ * @throws IOException on a parsing error.
+ */
Object parseObject(PemObject obj)
throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemReader.java b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemReader.java
index 7664725..3045b4d 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemReader.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/pem/PemReader.java
@@ -8,6 +8,9 @@ import java.util.List;
import org.bouncycastle.util.encoders.Base64;
+/**
+ * A generic PEM reader, based on the format outlined in RFC 1421
+ */
public class PemReader
extends BufferedReader
{
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509AttributeCertificate.java b/bcprov/src/main/java/org/bouncycastle/x509/X509AttributeCertificate.java
index 48a825f..d65ec78 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/X509AttributeCertificate.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/X509AttributeCertificate.java
@@ -15,6 +15,7 @@ import java.util.Date;
/**
* Interface for an X.509 Attribute Certificate.
+ * @deprecated use X509CertificateHolder class in the PKIX package.
*/
public interface X509AttributeCertificate
extends X509Extension
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java b/bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java
index cc50b8f..2486d20 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java
@@ -1,17 +1,17 @@
package org.bouncycastle.x509;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Selector;
-import org.bouncycastle.x509.extension.X509ExtensionUtil;
-
import java.io.IOException;
import java.math.BigInteger;
import java.security.cert.CRL;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLSelector;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.x509.X509Extensions;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Selector;
+import org.bouncycastle.x509.extension.X509ExtensionUtil;
+
/**
* This class is a Selector implementation for X.509 certificate revocation
* lists.
@@ -96,14 +96,14 @@ public class X509CRLStoreSelector
return false;
}
X509CRL crl = (X509CRL)obj;
- DERInteger dci = null;
+ ASN1Integer dci = null;
try
{
byte[] bytes = crl
.getExtensionValue(X509Extensions.DeltaCRLIndicator.getId());
if (bytes != null)
{
- dci = DERInteger.getInstance(X509ExtensionUtil
+ dci = ASN1Integer.getInstance(X509ExtensionUtil
.fromExtensionValue(bytes));
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509CertStoreSelector.java b/bcprov/src/main/java/org/bouncycastle/x509/X509CertStoreSelector.java
index b272649..6535328 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/X509CertStoreSelector.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/X509CertStoreSelector.java
@@ -1,18 +1,19 @@
package org.bouncycastle.x509;
-import org.bouncycastle.util.Selector;
-
import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
+import org.bouncycastle.util.Selector;
+
/**
* This class is a Selector implementation for X.509 certificates.
*
* @see org.bouncycastle.util.Selector
* @see org.bouncycastle.x509.X509Store
* @see org.bouncycastle.jce.provider.X509StoreCertCollection
+ * @deprecated use the classes under org.bouncycastle.cert.selector
*/
public class X509CertStoreSelector
extends X509CertSelector
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509Util.java b/bcprov/src/main/java/org/bouncycastle/x509/X509Util.java
index 7cf2e9d..ecf910f 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/X509Util.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/X509Util.java
@@ -23,8 +23,8 @@ import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
// BEGIN android-removed
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
// END android-removed
@@ -148,21 +148,21 @@ class X509Util
new ASN1Integer(1));
}
- static DERObjectIdentifier getAlgorithmOID(
+ static ASN1ObjectIdentifier getAlgorithmOID(
String algorithmName)
{
algorithmName = Strings.toUpperCase(algorithmName);
if (algorithms.containsKey(algorithmName))
{
- return (DERObjectIdentifier)algorithms.get(algorithmName);
+ return (ASN1ObjectIdentifier)algorithms.get(algorithmName);
}
- return new DERObjectIdentifier(algorithmName);
+ return new ASN1ObjectIdentifier(algorithmName);
}
static AlgorithmIdentifier getSigAlgID(
- DERObjectIdentifier sigOid,
+ ASN1ObjectIdentifier sigOid,
String algorithmName)
{
if (noParams.contains(sigOid))
@@ -218,7 +218,7 @@ class X509Util
}
static byte[] calculateSignature(
- DERObjectIdentifier sigOid,
+ ASN1ObjectIdentifier sigOid,
String sigName,
PrivateKey key,
SecureRandom random,
@@ -249,7 +249,7 @@ class X509Util
}
static byte[] calculateSignature(
- DERObjectIdentifier sigOid,
+ ASN1ObjectIdentifier sigOid,
String sigName,
String provider,
PrivateKey key,
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java b/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java
index ac44d73..f7ff3e4 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java
@@ -22,9 +22,9 @@ import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.Certificate;
@@ -43,7 +43,7 @@ import org.bouncycastle.jce.provider.X509CertificateObject;
public class X509V1CertificateGenerator
{
private V1TBSCertificateGenerator tbsGen;
- private DERObjectIdentifier sigOID;
+ private ASN1ObjectIdentifier sigOID;
private AlgorithmIdentifier sigAlgId;
private String signatureAlgorithm;
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509V3CertificateGenerator.java b/bcprov/src/main/java/org/bouncycastle/x509/X509V3CertificateGenerator.java
index d216295..c422cb2 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/X509V3CertificateGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/X509V3CertificateGenerator.java
@@ -24,7 +24,6 @@ import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.Certificate;
@@ -45,7 +44,7 @@ import org.bouncycastle.x509.extension.X509ExtensionUtil;
public class X509V3CertificateGenerator
{
private V3TBSCertificateGenerator tbsGen;
- private DERObjectIdentifier sigOID;
+ private ASN1ObjectIdentifier sigOID;
private AlgorithmIdentifier sigAlgId;
private String signatureAlgorithm;
private X509ExtensionsGenerator extGenerator;
@@ -228,14 +227,14 @@ public class X509V3CertificateGenerator
boolean critical,
ASN1Encodable value)
{
- this.addExtension(new DERObjectIdentifier(oid), critical, value);
+ this.addExtension(new ASN1ObjectIdentifier(oid), critical, value);
}
/**
* add a given extension field for the standard extensions tag (tag 3)
*/
public void addExtension(
- DERObjectIdentifier oid,
+ ASN1ObjectIdentifier oid,
boolean critical,
ASN1Encodable value)
{
@@ -252,14 +251,14 @@ public class X509V3CertificateGenerator
boolean critical,
byte[] value)
{
- this.addExtension(new DERObjectIdentifier(oid), critical, value);
+ this.addExtension(new ASN1ObjectIdentifier(oid), critical, value);
}
/**
* add a given extension field for the standard extensions tag (tag 3)
*/
public void addExtension(
- DERObjectIdentifier oid,
+ ASN1ObjectIdentifier oid,
boolean critical,
byte[] value)
{
@@ -302,7 +301,7 @@ public class X509V3CertificateGenerator
* @throws CertificateParsingException if the extension cannot be extracted.
*/
public void copyAndAddExtension(
- DERObjectIdentifier oid,
+ ASN1ObjectIdentifier oid,
boolean critical,
X509Certificate cert)
throws CertificateParsingException
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/extension/SubjectKeyIdentifierStructure.java b/bcprov/src/main/java/org/bouncycastle/x509/extension/SubjectKeyIdentifierStructure.java
deleted file mode 100644
index 2c7afd3..0000000
--- a/bcprov/src/main/java/org/bouncycastle/x509/extension/SubjectKeyIdentifierStructure.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.x509.extension;
-
-import java.io.IOException;
-import java.security.InvalidKeyException;
-import java.security.PublicKey;
-
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-
-/**
- * A high level subject key identifier.
- * @deprecated use JcaX509ExtensionUtils andSubjectKeyIdentifier.getInstance()
- */
-public class SubjectKeyIdentifierStructure
- extends SubjectKeyIdentifier
-{
- /**
- * Constructor which will take the byte[] returned from getExtensionValue()
- *
- * @param encodedValue a DER octet encoded string with the extension structure in it.
- * @throws IOException on parsing errors.
- */
- public SubjectKeyIdentifierStructure(
- byte[] encodedValue)
- throws IOException
- {
- super((ASN1OctetString)X509ExtensionUtil.fromExtensionValue(encodedValue));
- }
-
- private static ASN1OctetString fromPublicKey(
- PublicKey pubKey)
- throws InvalidKeyException
- {
- try
- {
- SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded());
-
- return (ASN1OctetString)(new SubjectKeyIdentifier(info).toASN1Object());
- }
- catch (Exception e)
- {
- throw new InvalidKeyException("Exception extracting key details: " + e.toString());
- }
- }
-
- public SubjectKeyIdentifierStructure(
- PublicKey pubKey)
- throws InvalidKeyException
- {
- super(fromPublicKey(pubKey));
- }
-}
diff --git a/bouncycastle.config b/bouncycastle.config
index 51521c8..f8caa2c 100644
--- a/bouncycastle.config
+++ b/bouncycastle.config
@@ -1,6 +1,7 @@
# directories
UNNEEDED_BCPROV_SOURCES=" \
org/bouncycastle/apache \
+org/bouncycastle/asn1/bsi \
org/bouncycastle/asn1/cmp \
org/bouncycastle/asn1/cms/ecc \
org/bouncycastle/asn1/crmf \
@@ -14,17 +15,22 @@ org/bouncycastle/asn1/microsoft \
org/bouncycastle/asn1/mozilla \
org/bouncycastle/asn1/ocsp \
org/bouncycastle/asn1/smime \
+org/bouncycastle/asn1/test \
org/bouncycastle/asn1/tsp \
+org/bouncycastle/asn1/ua \
org/bouncycastle/asn1/x509/qualified \
org/bouncycastle/asn1/x509/sigi \
org/bouncycastle/crypto/agreement/jpake \
org/bouncycastle/crypto/agreement/kdf \
org/bouncycastle/crypto/agreement/srp \
+org/bouncycastle/crypto/agreement/test \
org/bouncycastle/crypto/commitments \
-org/bouncycastle/crypto/ec \
+org/bouncycastle/crypto/ec/test \
org/bouncycastle/crypto/examples \
org/bouncycastle/crypto/kems \
+org/bouncycastle/crypto/parsers \
org/bouncycastle/crypto/prng \
+org/bouncycastle/crypto/test/ \
org/bouncycastle/crypto/tls/ \
org/bouncycastle/i18n/ \
org/bouncycastle/jcajce/io \
@@ -35,6 +41,8 @@ org/bouncycastle/jcajce/provider/asymmetric/gost \
org/bouncycastle/jcajce/provider/asymmetric/ies \
org/bouncycastle/jce/examples \
org/bouncycastle/jce/provider/test \
+org/bouncycastle/math/ec/custom/djb \
+org/bouncycastle/math/ec/tools \
org/bouncycastle/ocsp \
org/bouncycastle/pqc \
org/bouncycastle/util/test \
@@ -118,13 +126,6 @@ org/bouncycastle/asn1/pkcs/Attribute.java \
org/bouncycastle/asn1/pkcs/RC2CBCParameter.java \
org/bouncycastle/asn1/pkcs/SignerInfo.java \
org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java \
-org/bouncycastle/asn1/ua/DSTU4145BinaryField.java \
-org/bouncycastle/asn1/ua/DSTU4145ECBinary.java \
-org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java \
-org/bouncycastle/asn1/ua/DSTU4145Params.java \
-org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java \
-org/bouncycastle/asn1/ua/DSTU4145PublicKey.java \
-org/bouncycastle/asn1/ua/UAObjectIdentifiers.java \
org/bouncycastle/asn1/util/DERDump.java \
org/bouncycastle/asn1/util/Dump.java \
org/bouncycastle/asn1/x509/AccessDescription.java \
@@ -181,14 +182,28 @@ org/bouncycastle/crypto/digests/SkeinDigest.java \
org/bouncycastle/crypto/digests/SkeinEngine.java \
org/bouncycastle/crypto/digests/TigerDigest.java \
org/bouncycastle/crypto/digests/WhirlpoolDigest.java \
+org/bouncycastle/crypto/ec/ECDecryptor.java \
+org/bouncycastle/crypto/ec/ECElGamalDecryptor.java \
+org/bouncycastle/crypto/ec/ECElGamalEncryptor.java \
+org/bouncycastle/crypto/ec/ECEncryptor.java \
+org/bouncycastle/crypto/ec/ECFixedTransform.java \
+org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java \
+org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java \
+org/bouncycastle/crypto/ec/ECPair.java \
+org/bouncycastle/crypto/ec/ECPairFactorTransform.java \
+org/bouncycastle/crypto/ec/ECPairTransform.java \
+org/bouncycastle/crypto/ec/ECUtil.java \
org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java \
org/bouncycastle/crypto/engines/AESLightEngine.java \
+org/bouncycastle/crypto/engines/AESWrapPadEngine.java \
org/bouncycastle/crypto/engines/CAST5Engine.java \
org/bouncycastle/crypto/engines/CAST6Engine.java \
org/bouncycastle/crypto/engines/CamelliaEngine.java \
org/bouncycastle/crypto/engines/CamelliaLightEngine.java \
org/bouncycastle/crypto/engines/CamelliaWrapEngine.java \
org/bouncycastle/crypto/engines/ChaChaEngine.java \
+org/bouncycastle/crypto/engines/CramerShoupCiphertext.java \
+org/bouncycastle/crypto/engines/CramerShoupCoreEngine.java \
org/bouncycastle/crypto/engines/ElGamalEngine.java \
org/bouncycastle/crypto/engines/GOST28147Engine.java \
org/bouncycastle/crypto/engines/Grain128Engine.java \
@@ -206,6 +221,7 @@ org/bouncycastle/crypto/engines/RC532Engine.java \
org/bouncycastle/crypto/engines/RC564Engine.java \
org/bouncycastle/crypto/engines/RC6Engine.java \
org/bouncycastle/crypto/engines/RFC3211WrapEngine.java \
+org/bouncycastle/crypto/engines/RFC5649WrapEngine.java \
org/bouncycastle/crypto/engines/RSABlindingEngine.java \
org/bouncycastle/crypto/engines/RSAEngine.java \
org/bouncycastle/crypto/engines/RijndaelEngine.java \
@@ -222,6 +238,8 @@ org/bouncycastle/crypto/engines/VMPCKSA3Engine.java \
org/bouncycastle/crypto/engines/XSalsa20Engine.java \
org/bouncycastle/crypto/engines/XTEAEngine.java \
org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java \
+org/bouncycastle/crypto/generators/CramerShoupKeyPairGenerator.java \
+org/bouncycastle/crypto/generators/CramerShoupParametersGenerator.java \
org/bouncycastle/crypto/generators/DHKeyPairGenerator.java \
org/bouncycastle/crypto/generators/DSTU4145KeyPairGenerator.java \
org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java \
@@ -240,6 +258,7 @@ org/bouncycastle/crypto/generators/NaccacheSternKeyPairGenerator.java \
org/bouncycastle/crypto/generators/Poly1305KeyGenerator.java \
org/bouncycastle/crypto/generators/RSABlindingFactorGenerator.java \
org/bouncycastle/crypto/generators/SCrypt.java \
+org/bouncycastle/crypto/io/CipherIOException.java \
org/bouncycastle/crypto/io/CipherInputStream.java \
org/bouncycastle/crypto/io/CipherOutputStream.java \
org/bouncycastle/crypto/io/InvalidCipherTextIOException.java \
@@ -248,6 +267,7 @@ org/bouncycastle/crypto/io/SignerOutputStream.java \
org/bouncycastle/crypto/macs/BlockCipherMac.java \
org/bouncycastle/crypto/macs/CFBBlockCipherMac.java \
org/bouncycastle/crypto/macs/CMac.java \
+org/bouncycastle/crypto/macs/CMacWithIV.java \
org/bouncycastle/crypto/macs/GMac.java \
org/bouncycastle/crypto/macs/GOST28147Mac.java \
org/bouncycastle/crypto/macs/ISO9797Alg3Mac.java \
@@ -268,6 +288,11 @@ org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java \
org/bouncycastle/crypto/modes/gcm/BasicGCMMultiplier.java \
org/bouncycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java \
org/bouncycastle/crypto/params/CCMParameters.java \
+org/bouncycastle/crypto/params/CramerShoupKeyGenerationParameters.java \
+org/bouncycastle/crypto/params/CramerShoupKeyParameters.java \
+org/bouncycastle/crypto/params/CramerShoupParameters.java \
+org/bouncycastle/crypto/params/CramerShoupPrivateKeyParameters.java \
+org/bouncycastle/crypto/params/CramerShoupPublicKeyParameters.java \
org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java \
org/bouncycastle/crypto/params/ElGamalKeyParameters.java \
org/bouncycastle/crypto/params/ElGamalParameters.java \
@@ -299,8 +324,6 @@ org/bouncycastle/crypto/params/RC5Parameters.java \
org/bouncycastle/crypto/params/RSABlindingParameters.java \
org/bouncycastle/crypto/params/SkeinParameters.java \
org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java \
-org/bouncycastle/crypto/parsers/DHIESPublicKeyParser.java \
-org/bouncycastle/crypto/parsers/ECIESPublicKeyParser.java \
org/bouncycastle/crypto/signers/DSADigestSigner.java \
org/bouncycastle/crypto/signers/DSTU4145Signer.java \
org/bouncycastle/crypto/signers/ECGOST3410Signer.java \
@@ -428,12 +451,15 @@ org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java \
org/bouncycastle/math/ec/NafL2RMultiplier.java \
org/bouncycastle/math/ec/NafR2LMultiplier.java \
org/bouncycastle/math/ec/ReferenceMultiplier.java \
+org/bouncycastle/math/ec/ScaleYPointMap.java \
org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java \
org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java \
+org/bouncycastle/math/raw/Mont256.java \
org/bouncycastle/util/MemoableResetException.java \
org/bouncycastle/util/Shorts.java \
org/bouncycastle/util/StreamParser.java \
org/bouncycastle/util/StreamParsingException.java \
+org/bouncycastle/util/Times.java \
org/bouncycastle/util/encoders/BufferedDecoder.java \
org/bouncycastle/util/encoders/BufferedEncoder.java \
org/bouncycastle/util/encoders/HexTranslator.java \
@@ -451,7 +477,6 @@ org/bouncycastle/x509/X509CertificatePair.java \
org/bouncycastle/x509/X509Store.java \
org/bouncycastle/x509/X509StreamParser.java \
org/bouncycastle/x509/X509StreamParserSpi.java \
-org/bouncycastle/x509/X509V2AttributeCertificateGenerator.java \
org/bouncycastle/x509/X509V2CRLGenerator.java \
org/bouncycastle/x509/util/LDAPStoreHelper.java \
org/bouncycastle/x509/util/StreamParser.java \
@@ -491,6 +516,7 @@ org/bouncycastle/cert/X509v3CertificateBuilder.java \
org/bouncycastle/cert/jcajce/CertHelper.java \
org/bouncycastle/cert/jcajce/DefaultCertHelper.java \
org/bouncycastle/cert/jcajce/JcaAttrCertStore.java \
+org/bouncycastle/cert/jcajce/JcaAttributeCertificateIssuer.java \
org/bouncycastle/cert/jcajce/JcaCRLStore.java \
org/bouncycastle/cert/jcajce/JcaCertStoreBuilder.java \
org/bouncycastle/cert/jcajce/JcaX500NameUtil.java \
@@ -555,16 +581,13 @@ org/bouncycastle/cms/KeyTransRecipientInformation.java \
org/bouncycastle/cms/OriginatorId.java \
org/bouncycastle/cms/OriginatorInfoGenerator.java \
org/bouncycastle/cms/OriginatorInformation.java \
-org/bouncycastle/cms/PasswordRecipient.java \
org/bouncycastle/cms/PasswordRecipientId.java \
org/bouncycastle/cms/PasswordRecipientInfoGenerator.java \
org/bouncycastle/cms/PasswordRecipientInformation.java \
-org/bouncycastle/cms/Recipient.java \
org/bouncycastle/cms/RecipientId.java \
org/bouncycastle/cms/RecipientInfoGenerator.java \
org/bouncycastle/cms/RecipientInformation.java \
org/bouncycastle/cms/RecipientInformationStore.java \
-org/bouncycastle/cms/RecipientOperator.java \
org/bouncycastle/cms/SignerInformationVerifierProvider.java \
org/bouncycastle/cms/jcajce/CMSUtils.java \
org/bouncycastle/cms/jcajce/DefaultJcaJceExtHelper.java \
@@ -603,14 +626,11 @@ org/bouncycastle/operator/AsymmetricKeyUnwrapper.java \
org/bouncycastle/operator/AsymmetricKeyWrapper.java \
org/bouncycastle/operator/BufferingContentSigner.java \
org/bouncycastle/operator/DefaultSecretKeySizeProvider.java \
-org/bouncycastle/operator/GenericKey.java \
-org/bouncycastle/operator/InputDecryptor.java \
org/bouncycastle/operator/InputDecryptorProvider.java \
org/bouncycastle/operator/InputExpander.java \
org/bouncycastle/operator/InputExpanderProvider.java \
org/bouncycastle/operator/KeyUnwrapper.java \
org/bouncycastle/operator/KeyWrapper.java \
-org/bouncycastle/operator/MacCalculator.java \
org/bouncycastle/operator/MacCalculatorProvider.java \
org/bouncycastle/operator/OutputCompressor.java \
org/bouncycastle/operator/OutputEncryptor.java \
diff --git a/bouncycastle.version b/bouncycastle.version
index 45c0f80..1c9ab99 100644
--- a/bouncycastle.version
+++ b/bouncycastle.version
@@ -1,2 +1,2 @@
BOUNCYCASTLE_JDK=15on
-BOUNCYCASTLE_VERSION=150
+BOUNCYCASTLE_VERSION=151
diff --git a/import_bouncycastle.sh b/import_bouncycastle.sh
index 0dfe484..45cdae8 100755
--- a/import_bouncycastle.sh
+++ b/import_bouncycastle.sh
@@ -222,6 +222,10 @@ function untar() {
echo "Removing $unneeded_sources"
(cd $bouncycastle_dir_orig && rm -rf $unneeded_sources)
(cd $bouncycastle_dir && rm -r $unneeded_sources)
+
+ echo "Removing package.html files"
+ find $bouncycastle_dir_orig -name package.html -print0 | xargs -0 rm
+ find $bouncycastle_dir -name package.html -print0 | xargs -0 rm
}
function cleantar() {
diff --git a/patches/bcpkix.patch b/patches/bcpkix.patch
index b18c53c..b12caf7 100644
--- a/patches/bcpkix.patch
+++ b/patches/bcpkix.patch
@@ -1,6 +1,6 @@
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSSignedData.java bcpkix-jdk15on-150/org/bouncycastle/cms/CMSSignedData.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSSignedData.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/cms/CMSSignedData.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedData.java bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedData.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedData.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedData.java 2014-07-28 23:57:30.811988142 +0000
@@ -285,18 +285,20 @@
return HELPER.getAttributeCertificates(signedData.getCertificates());
}
@@ -173,9 +173,9 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSSignedData.java bcpki
/**
* Replace the SignerInformation store associated with this
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSSignedGenerator.java bcpkix-jdk15on-150/org/bouncycastle/cms/CMSSignedGenerator.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSSignedGenerator.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/cms/CMSSignedGenerator.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedGenerator.java bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedGenerator.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedGenerator.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedGenerator.java 2014-07-28 23:57:30.815988170 +0000
@@ -12,8 +12,10 @@
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERTaggedObject;
@@ -276,9 +276,9 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSSignedGenerator.java
/**
* Add a store of pre-calculated signers to the generator.
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSSignedHelper.java bcpkix-jdk15on-150/org/bouncycastle/cms/CMSSignedHelper.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSSignedHelper.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/cms/CMSSignedHelper.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedHelper.java bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedHelper.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedHelper.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedHelper.java 2014-07-28 23:57:30.795988031 +0000
@@ -13,8 +13,10 @@
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.ASN1TaggedObject;
@@ -427,10 +427,10 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSSignedHelper.java bcp
+ // return new CollectionStore(new ArrayList());
+ // }
}
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSUtils.java bcpkix-jdk15on-150/org/bouncycastle/cms/CMSUtils.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSUtils.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/cms/CMSUtils.java 2013-12-12 00:35:05.000000000 +0000
-@@ -19,9 +19,11 @@
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSUtils.java bcpkix-jdk15on-151/org/bouncycastle/cms/CMSUtils.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSUtils.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/cms/CMSUtils.java 2014-07-28 23:57:30.775987892 +0000
+@@ -20,9 +20,11 @@
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.ContentInfo;
@@ -445,10 +445,48 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSUtils.java bcpkix-jdk
import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509CertificateHolder;
-@@ -116,29 +118,31 @@
+@@ -113,14 +115,16 @@
+
+ crls.add(c.toASN1Structure());
+ }
+- else if (rev instanceof OtherRevocationInfoFormat)
+- {
+- OtherRevocationInfoFormat infoFormat = OtherRevocationInfoFormat.getInstance(rev);
+-
+- validateInfoFormat(infoFormat);
+-
+- crls.add(new DERTaggedObject(false, 1, infoFormat));
+- }
++ // BEGIN android-removed
++ // else if (rev instanceof OtherRevocationInfoFormat)
++ // {
++ // OtherRevocationInfoFormat infoFormat = OtherRevocationInfoFormat.getInstance(rev);
++ //
++ // validateInfoFormat(infoFormat);
++ //
++ // crls.add(new DERTaggedObject(false, 1, infoFormat));
++ // }
++ // END android-removed
+ else if (rev instanceof ASN1TaggedObject)
+ {
+ crls.add(rev);
+@@ -135,35 +139,36 @@
}
}
+- private static void validateInfoFormat(OtherRevocationInfoFormat infoFormat)
+- {
+- if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(infoFormat.getInfoFormat()))
+- {
+- OCSPResponse resp = OCSPResponse.getInstance(infoFormat.getInfo());
+-
+- if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
+- {
+- throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
+- }
+- }
+- }
+-
- static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos)
- {
- List others = new ArrayList();
@@ -456,23 +494,29 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSUtils.java bcpkix-jdk
- for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext();)
- {
- ASN1Encodable info = (ASN1Encodable)it.next();
+- OtherRevocationInfoFormat infoFormat = new OtherRevocationInfoFormat(otherRevocationInfoFormat, info);
-
-- if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(otherRevocationInfoFormat))
-- {
-- OCSPResponse resp = OCSPResponse.getInstance(info);
+- validateInfoFormat(infoFormat);
-
-- if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
-- {
-- throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
-- }
-- }
--
-- others.add(new DERTaggedObject(false, 1, new OtherRevocationInfoFormat(otherRevocationInfoFormat, info)));
+- others.add(new DERTaggedObject(false, 1, infoFormat));
- }
-
- return others;
- }
+ // BEGIN android-removed
++ // private static void validateInfoFormat(OtherRevocationInfoFormat infoFormat)
++ // {
++ // if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(infoFormat.getInfoFormat()))
++ // {
++ // OCSPResponse resp = OCSPResponse.getInstance(infoFormat.getInfo());
++ //
++ // if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
++ // {
++ // throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
++ // }
++ // }
++ // }
++ //
+ // static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos)
+ // {
+ // List others = new ArrayList();
@@ -480,18 +524,10 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSUtils.java bcpkix-jdk
+ // for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext();)
+ // {
+ // ASN1Encodable info = (ASN1Encodable)it.next();
++ // OtherRevocationInfoFormat infoFormat = new OtherRevocationInfoFormat(otherRevocationInfoFormat, info);
++ // validateInfoFormat(infoFormat);
+ //
-+ // if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(otherRevocationInfoFormat))
-+ // {
-+ // OCSPResponse resp = OCSPResponse.getInstance(info);
-+ //
-+ // if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
-+ // {
-+ // throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
-+ // }
-+ // }
-+ //
-+ // others.add(new DERTaggedObject(false, 1, new OtherRevocationInfoFormat(otherRevocationInfoFormat, info)));
++ // others.add(new DERTaggedObject(false, 1, infoFormat));
+ // }
+ //
+ // return others;
@@ -500,21 +536,23 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/CMSUtils.java bcpkix-jdk
static ASN1Set createBerSetFromList(List derObjects)
{
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java bcpkix-jdk15on-150/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java 2013-09-26 18:06:21.000000000 +0000
-@@ -4,7 +4,9 @@
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java bcpkix-jdk15on-151/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java 2014-07-28 23:57:30.779987920 +0000
+@@ -4,8 +4,10 @@
import java.util.Map;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+-import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// BEGIN android-removed
++// import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// END android-removed
import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-@@ -33,12 +35,16 @@
+@@ -34,12 +36,16 @@
addEntries(NISTObjectIdentifiers.dsa_with_sha384, "SHA384", "DSA");
addEntries(NISTObjectIdentifiers.dsa_with_sha512, "SHA512", "DSA");
addEntries(OIWObjectIdentifiers.dsaWithSHA1, "SHA1", "DSA");
@@ -535,7 +573,27 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgor
addEntries(PKCSObjectIdentifiers.md5WithRSAEncryption, "MD5", "RSA");
addEntries(PKCSObjectIdentifiers.sha1WithRSAEncryption, "SHA1", "RSA");
addEntries(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224", "RSA");
-@@ -66,26 +72,30 @@
+@@ -61,38 +67,44 @@
+ addEntries(EACObjectIdentifiers.id_TA_RSA_v1_5_SHA_256, "SHA256", "RSA");
+ addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_1, "SHA1", "RSAandMGF1");
+ addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_256, "SHA256", "RSAandMGF1");
+- addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA1, "SHA1", "PLAIN-ECDSA");
+- addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA224, "SHA224", "PLAIN-ECDSA");
+- addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA256, "SHA256", "PLAIN-ECDSA");
+- addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA384, "SHA384", "PLAIN-ECDSA");
+- addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA512, "SHA512", "PLAIN-ECDSA");
+- addEntries(BSIObjectIdentifiers.ecdsa_plain_RIPEMD160, "RIPEMD160", "PLAIN-ECDSA");
++ // BEGIN android-removed
++ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA1, "SHA1", "PLAIN-ECDSA");
++ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA224, "SHA224", "PLAIN-ECDSA");
++ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA256, "SHA256", "PLAIN-ECDSA");
++ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA384, "SHA384", "PLAIN-ECDSA");
++ // addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA512, "SHA512", "PLAIN-ECDSA");
++ // addEntries(BSIObjectIdentifiers.ecdsa_plain_RIPEMD160, "RIPEMD160", "PLAIN-ECDSA");
++ // END android-removed
+
+ encryptionAlgs.put(X9ObjectIdentifiers.id_dsa, "DSA");
+ encryptionAlgs.put(PKCSObjectIdentifiers.rsaEncryption, "RSA");
encryptionAlgs.put(TeleTrusTObjectIdentifiers.teleTrusTRSAsignatureAlgorithm, "RSA");
encryptionAlgs.put(X509ObjectIdentifiers.id_ea_rsa, "RSA");
encryptionAlgs.put(PKCSObjectIdentifiers.id_RSASSA_PSS, "RSAandMGF1");
@@ -580,9 +638,9 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgor
}
/**
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java bcpkix-jdk15on-150/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java bcpkix-jdk15on-151/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java 2014-07-28 23:57:30.803988086 +0000
@@ -16,21 +16,27 @@
static
@@ -618,9 +676,9 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/cms/DefaultCMSSignatureEncry
}
public AlgorithmIdentifier findEncryptionAlgorithm(AlgorithmIdentifier signatureAlgorithm)
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java bcpkix-jdk15on-150/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java bcpkix-jdk15on-151/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java 2014-07-28 23:57:30.735987614 +0000
@@ -5,7 +5,9 @@
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -705,21 +763,25 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultDigestAlgori
}
public AlgorithmIdentifier find(AlgorithmIdentifier sigAlgId)
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java bcpkix-jdk15on-150/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java 2013-09-26 18:06:21.000000000 +0000
-@@ -9,7 +9,9 @@
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java bcpkix-jdk15on-151/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java 2014-07-28 23:57:30.695987337 +0000
+@@ -9,9 +9,11 @@
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERNull;
+-import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+-import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
+// BEGIN android-removed
++// import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
++// import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
+// END android-removed
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-@@ -32,13 +34,17 @@
+@@ -34,13 +36,17 @@
private static final ASN1ObjectIdentifier ENCRYPTION_DSA = X9ObjectIdentifiers.id_dsa_with_sha1;
private static final ASN1ObjectIdentifier ENCRYPTION_ECDSA = X9ObjectIdentifiers.ecdsa_with_SHA1;
private static final ASN1ObjectIdentifier ENCRYPTION_RSA_PSS = PKCSObjectIdentifiers.id_RSASSA_PSS;
@@ -741,7 +803,7 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultSignatureAlg
algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption);
algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption);
algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption);
-@@ -56,12 +62,14 @@
+@@ -58,12 +64,14 @@
algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
@@ -762,7 +824,7 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultSignatureAlg
algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1);
algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1);
algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224);
-@@ -74,11 +82,13 @@
+@@ -76,22 +84,24 @@
algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256);
algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384);
algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512);
@@ -771,17 +833,39 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultSignatureAlg
- algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
- algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
- algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
+- algorithms.put("SHA1WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA1);
+- algorithms.put("SHA224WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA224);
+- algorithms.put("SHA256WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA256);
+- algorithms.put("SHA384WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA384);
+- algorithms.put("SHA512WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA512);
+- algorithms.put("RIPEMD160WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_RIPEMD160);
+- algorithms.put("SHA1WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1);
+- algorithms.put("SHA224WITHPCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_224);
+- algorithms.put("SHA256WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_256);
+- algorithms.put("SHA384WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_384);
+- algorithms.put("SHA512WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_512);
+ // BEGIN android-removed
+ // algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
+ // algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
+ // algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
+ // algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
+ // algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
++ // algorithms.put("SHA1WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA1);
++ // algorithms.put("SHA224WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA224);
++ // algorithms.put("SHA256WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA256);
++ // algorithms.put("SHA384WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA384);
++ // algorithms.put("SHA512WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA512);
++ // algorithms.put("RIPEMD160WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_RIPEMD160);
++ // algorithms.put("SHA1WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1);
++ // algorithms.put("SHA224WITHPCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_224);
++ // algorithms.put("SHA256WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_256);
++ // algorithms.put("SHA384WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_384);
++ // algorithms.put("SHA512WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_512);
+ // END android-removed
-
//
// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
-@@ -98,8 +108,10 @@
+ // The parameters field SHALL be NULL for RSA based signature algorithms.
+@@ -110,8 +120,10 @@
//
// RFC 4491
//
@@ -794,7 +878,7 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultSignatureAlg
//
// PKCS 1.5 encrypted algorithms
-@@ -109,9 +121,11 @@
+@@ -121,9 +133,11 @@
pkcs15RsaEncryption.add(PKCSObjectIdentifiers.sha256WithRSAEncryption);
pkcs15RsaEncryption.add(PKCSObjectIdentifiers.sha384WithRSAEncryption);
pkcs15RsaEncryption.add(PKCSObjectIdentifiers.sha512WithRSAEncryption);
@@ -809,7 +893,7 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultSignatureAlg
//
// explicit params
-@@ -138,15 +152,19 @@
+@@ -150,15 +164,19 @@
digestOids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, NISTObjectIdentifiers.id_sha256);
digestOids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, NISTObjectIdentifiers.id_sha384);
digestOids.put(PKCSObjectIdentifiers.sha512WithRSAEncryption, NISTObjectIdentifiers.id_sha512);
@@ -836,9 +920,16 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/DefaultSignatureAlg
}
private static AlgorithmIdentifier generate(String signatureAlgorithm)
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java bcpkix-jdk15on-150/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java 2013-09-26 18:06:21.000000000 +0000
+@@ -221,4 +239,4 @@
+ {
+ return generate(sigAlgName);
+ }
+-}
+\ No newline at end of file
++}
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java bcpkix-jdk15on-151/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java 2014-07-28 23:57:30.731987587 +0000
@@ -4,20 +4,26 @@
import java.util.HashMap;
import java.util.Map;
@@ -966,29 +1057,55 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/bc/BcDefaultDigestP
return Collections.unmodifiableMap(table);
}
-diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/jcajce/OperatorHelper.java bcpkix-jdk15on-150/org/bouncycastle/operator/jcajce/OperatorHelper.java
---- bcpkix-jdk15on-150.orig/org/bouncycastle/operator/jcajce/OperatorHelper.java 2013-12-03 20:18:54.000000000 +0000
-+++ bcpkix-jdk15on-150/org/bouncycastle/operator/jcajce/OperatorHelper.java 2013-12-12 00:35:05.000000000 +0000
-@@ -24,7 +24,9 @@
+diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/operator/jcajce/OperatorHelper.java bcpkix-jdk15on-151/org/bouncycastle/operator/jcajce/OperatorHelper.java
+--- bcpkix-jdk15on-151.orig/org/bouncycastle/operator/jcajce/OperatorHelper.java 2014-07-26 04:18:10.000000000 +0000
++++ bcpkix-jdk15on-151/org/bouncycastle/operator/jcajce/OperatorHelper.java 2014-07-28 23:57:30.711987448 +0000
+@@ -24,9 +24,11 @@
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERNull;
+-import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+-import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
+// BEGIN android-removed
++// import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
++// import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
+// END android-removed
import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
-@@ -57,11 +59,15 @@
+@@ -59,22 +61,26 @@
oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA");
oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA");
oids.put(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512WITHRSA");
- oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, "GOST3411WITHGOST3410");
- oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, "GOST3411WITHECGOST3410");
+- oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA1, "SHA1WITHPLAIN-ECDSA");
+- oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA224, "SHA224WITHPLAIN-ECDSA");
+- oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA256, "SHA256WITHPLAIN-ECDSA");
+- oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA384, "SHA384WITHPLAIN-ECDSA");
+- oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA512, "SHA512WITHPLAIN-ECDSA");
+- oids.put(BSIObjectIdentifiers.ecdsa_plain_RIPEMD160, "RIPEMD160WITHPLAIN-ECDSA");
+- oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_1, "SHA1WITHCVC-ECDSA");
+- oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_224, "SHA224WITHCVC-ECDSA");
+- oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_256, "SHA256WITHCVC-ECDSA");
+- oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_384, "SHA384WITHCVC-ECDSA");
+- oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_512, "SHA512WITHCVC-ECDSA");
+ // BEGIN android-removed
+ // oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, "GOST3411WITHGOST3410");
+ // oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, "GOST3411WITHECGOST3410");
++ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA1, "SHA1WITHPLAIN-ECDSA");
++ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA224, "SHA224WITHPLAIN-ECDSA");
++ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA256, "SHA256WITHPLAIN-ECDSA");
++ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA384, "SHA384WITHPLAIN-ECDSA");
++ // oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA512, "SHA512WITHPLAIN-ECDSA");
++ // oids.put(BSIObjectIdentifiers.ecdsa_plain_RIPEMD160, "RIPEMD160WITHPLAIN-ECDSA");
++ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_1, "SHA1WITHCVC-ECDSA");
++ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_224, "SHA224WITHCVC-ECDSA");
++ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_256, "SHA256WITHCVC-ECDSA");
++ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_384, "SHA384WITHCVC-ECDSA");
++ // oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_512, "SHA512WITHCVC-ECDSA");
+ // END android-removed
oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
@@ -999,44 +1116,3 @@ diff -Naur bcpkix-jdk15on-150.orig/org/bouncycastle/operator/jcajce/OperatorHelp
oids.put(new ASN1ObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA");
oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1WITHECDSA");
oids.put(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224WITHECDSA");
-@@ -362,22 +368,24 @@
- {
- return "SHA512";
- }
-- else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID))
-- {
-- return "RIPEMD128";
-- }
-- else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID))
-- {
-- return "RIPEMD160";
-- }
-- else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID))
-- {
-- return "RIPEMD256";
-- }
-- else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID))
-- {
-- return "GOST3411";
-- }
-+ // BEGIN android-removed
-+ // else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID))
-+ // {
-+ // return "RIPEMD128";
-+ // }
-+ // else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID))
-+ // {
-+ // return "RIPEMD160";
-+ // }
-+ // else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID))
-+ // {
-+ // return "RIPEMD256";
-+ // }
-+ // else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID))
-+ // {
-+ // return "GOST3411";
-+ // }
-+ // END android-removed
- else
- {
- return digestAlgOID.getId();
diff --git a/patches/bcprov.patch b/patches/bcprov.patch
index 0880f97..b824b2f 100644
--- a/patches/bcprov.patch
+++ b/patches/bcprov.patch
@@ -1,23 +1,7 @@
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/ASN1Null.java bcprov-jdk15on-150/org/bouncycastle/asn1/ASN1Null.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/ASN1Null.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/ASN1Null.java 2013-01-31 02:26:40.000000000 +0000
-@@ -11,9 +11,11 @@
- /**
- * @deprecated use DERNull.INSTANCE
- */
-- public ASN1Null()
-+ // BEGIN android-changed
-+ /*package*/ ASN1Null()
- {
- }
-+ // END android-changed
-
- public static ASN1Null getInstance(Object o)
- {
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERBoolean.java bcprov-jdk15on-150/org/bouncycastle/asn1/DERBoolean.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERBoolean.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/DERBoolean.java 2013-12-12 00:35:05.000000000 +0000
-@@ -10,7 +10,9 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1Boolean.java bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1Boolean.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1Boolean.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1Boolean.java 2014-07-28 19:51:54.000000000 +0000
+@@ -23,7 +23,9 @@
private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff };
private static final byte[] FALSE_VALUE = new byte[] { 0 };
@@ -28,15 +12,15 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERBoolean.java bcprov-
public static final ASN1Boolean FALSE = new ASN1Boolean(false);
public static final ASN1Boolean TRUE = new ASN1Boolean(true);
-@@ -55,6 +57,17 @@
+@@ -79,6 +81,17 @@
return (value != 0 ? TRUE : FALSE);
}
+ // BEGIN android-added
+ /**
-+ * return a DERBoolean from the passed in array.
++ * return a ASN1Boolean from the passed in array.
+ */
-+ public static DERBoolean getInstance(
++ public static ASN1Boolean getInstance(
+ byte[] octets)
+ {
+ return (octets[0] != 0) ? TRUE : FALSE;
@@ -46,47 +30,49 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERBoolean.java bcprov-
/**
* return a Boolean from a tagged object.
*
-@@ -80,7 +93,9 @@
+@@ -105,7 +118,9 @@
}
}
-
-- DERBoolean(
+
+- ASN1Boolean(
+ // BEGIN android-changed
-+ protected DERBoolean(
++ protected ASN1Boolean(
+ // END android-changed
- byte[] value)
+ byte[] value)
{
if (value.length != 1)
-@@ -106,8 +121,10 @@
+@@ -131,8 +146,10 @@
* @deprecated use getInstance(boolean) method.
- * @param value
+ * @param value true or false.
*/
-- public DERBoolean(
+- public ASN1Boolean(
+ // BEGIN android-changed
-+ protected DERBoolean(
++ protected ASN1Boolean(
boolean value)
+ // END android-changed
{
this.value = (value) ? TRUE_VALUE : FALSE_VALUE;
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERNull.java bcprov-jdk15on-150/org/bouncycastle/asn1/DERNull.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERNull.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/DERNull.java 2013-01-31 02:26:40.000000000 +0000
-@@ -15,7 +15,9 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1Null.java bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1Null.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1Null.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1Null.java 2014-07-28 19:51:54.000000000 +0000
+@@ -8,6 +8,12 @@
+ public abstract class ASN1Null
+ extends ASN1Primitive
+ {
++ // BEGIN android-added
++ /*package*/ ASN1Null()
++ {
++ }
++
++ // END android-added
/**
- * @deprecated use DERNull.INSTANCE
- */
-- public DERNull()
-+ // BEGIN android-changed
-+ protected DERNull()
-+ // END android-changed
- {
- }
-
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERObjectIdentifier.java bcprov-jdk15on-150/org/bouncycastle/asn1/DERObjectIdentifier.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERObjectIdentifier.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/DERObjectIdentifier.java 2013-12-12 00:35:05.000000000 +0000
-@@ -162,7 +162,13 @@
+ * Return an instance of ASN.1 NULL from the passed in object.
+ * <p>
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1ObjectIdentifier.java bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1ObjectIdentifier.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1ObjectIdentifier.java 2014-07-28 19:51:54.000000000 +0000
+@@ -152,7 +152,13 @@
}
}
@@ -101,7 +87,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERObjectIdentifier.jav
this.body = Arrays.clone(bytes);
}
-@@ -181,7 +187,13 @@
+@@ -173,7 +179,13 @@
throw new IllegalArgumentException("string " + identifier + " not an OID");
}
@@ -115,10 +101,24 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERObjectIdentifier.jav
+ // END android-changed
}
- DERObjectIdentifier(DERObjectIdentifier oid, String branchID)
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERPrintableString.java bcprov-jdk15on-150/org/bouncycastle/asn1/DERPrintableString.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERPrintableString.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/DERPrintableString.java 2013-01-31 02:26:40.000000000 +0000
+ /**
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/DERNull.java bcprov-jdk15on-151/org/bouncycastle/asn1/DERNull.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/DERNull.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/DERNull.java 2013-01-31 02:26:40.000000000 +0000
+@@ -15,7 +15,9 @@
+ /**
+ * @deprecated use DERNull.INSTANCE
+ */
+- public DERNull()
++ // BEGIN android-changed
++ protected DERNull()
++ // END android-changed
+ {
+ }
+
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/DERPrintableString.java bcprov-jdk15on-151/org/bouncycastle/asn1/DERPrintableString.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/DERPrintableString.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/DERPrintableString.java 2014-07-28 19:51:54.000000000 +0000
@@ -12,7 +12,9 @@
extends ASN1Primitive
implements ASN1String
@@ -130,9 +130,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/DERPrintableString.java
/**
* return a printable string from the passed in object.
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/StreamUtil.java bcprov-jdk15on-150/org/bouncycastle/asn1/StreamUtil.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/StreamUtil.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/StreamUtil.java 2014-05-05 17:17:14.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/StreamUtil.java bcprov-jdk15on-151/org/bouncycastle/asn1/StreamUtil.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/StreamUtil.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/StreamUtil.java 2014-05-05 17:17:14.000000000 +0000
@@ -8,7 +8,9 @@
class StreamUtil
@@ -162,9 +162,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/StreamUtil.java bcprov-
}
static int calculateBodyLength(
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/cms/ContentInfo.java bcprov-jdk15on-150/org/bouncycastle/asn1/cms/ContentInfo.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/cms/ContentInfo.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/cms/ContentInfo.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/cms/ContentInfo.java bcprov-jdk15on-151/org/bouncycastle/asn1/cms/ContentInfo.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/cms/ContentInfo.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/cms/ContentInfo.java 2013-12-12 00:35:05.000000000 +0000
@@ -28,7 +28,9 @@
*/
public class ContentInfo
@@ -176,9 +176,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/cms/ContentInfo.java bc
{
private ASN1ObjectIdentifier contentType;
private ASN1Encodable content;
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java bcprov-jdk15on-150/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java bcprov-jdk15on-151/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java 2013-12-12 00:35:05.000000000 +0000
@@ -13,10 +13,12 @@
static final ASN1ObjectIdentifier pkcs_1 = new ASN1ObjectIdentifier("1.2.840.113549.1.1");
/** PKCS#1: 1.2.840.113549.1.1.1 */
@@ -220,9 +220,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifi
//
// md5 OBJECT IDENTIFIER ::=
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java bcprov-jdk15on-150/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java bcprov-jdk15on-151/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java 2014-07-28 19:51:54.000000000 +0000
@@ -14,7 +14,9 @@
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
@@ -245,7 +245,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdenti
byte[] resBuf = new byte[digest.getDigestSize()];
byte[] bytes = spki.getPublicKeyData().getBytes();
-@@ -124,7 +128,9 @@
+@@ -125,7 +129,9 @@
GeneralNames name,
BigInteger serialNumber)
{
@@ -256,34 +256,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdenti
byte[] resBuf = new byte[digest.getDigestSize()];
byte[] bytes = spki.getPublicKeyData().getBytes();
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java bcprov-jdk15on-150/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java 2013-01-31 02:26:40.000000000 +0000
-@@ -6,7 +6,9 @@
- import org.bouncycastle.asn1.ASN1TaggedObject;
- import org.bouncycastle.asn1.DEROctetString;
- import org.bouncycastle.crypto.Digest;
--import org.bouncycastle.crypto.digests.SHA1Digest;
-+// BEGIN android-changed
-+import org.bouncycastle.crypto.digests.AndroidDigestFactory;
-+// END android-changed
-
- /**
- * The SubjectKeyIdentifier object.
-@@ -124,7 +126,9 @@
-
- private static byte[] getDigest(SubjectPublicKeyInfo spki)
- {
-- Digest digest = new SHA1Digest();
-+ // BEGIN android-changed
-+ Digest digest = AndroidDigestFactory.getSHA1();
-+ // END android-changed
- byte[] resBuf = new byte[digest.getDigestSize()];
-
- byte[] bytes = spki.getPublicKeyData().getBytes();
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/X509Name.java bcprov-jdk15on-150/org/bouncycastle/asn1/x509/X509Name.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/X509Name.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/x509/X509Name.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/X509Name.java bcprov-jdk15on-151/org/bouncycastle/asn1/x509/X509Name.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/X509Name.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/x509/X509Name.java 2013-12-12 00:35:05.000000000 +0000
@@ -255,8 +255,10 @@
*/
public static final Hashtable SymbolLookUp = DefaultLookUp;
@@ -308,9 +283,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/X509Name.java bcpr
}
}
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java bcprov-jdk15on-150/org/bouncycastle/asn1/x509/X509NameTokenizer.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/x509/X509NameTokenizer.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java bcprov-jdk15on-151/org/bouncycastle/asn1/x509/X509NameTokenizer.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/x509/X509NameTokenizer.java 2013-05-25 02:14:15.000000000 +0000
@@ -78,6 +78,17 @@
}
else
@@ -329,9 +304,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.
buf.append(c);
}
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.java bcprov-jdk15on-150/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/asn1/x9/ECNamedCurveTable.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.java bcprov-jdk15on-151/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/asn1/x9/ECNamedCurveTable.java 2014-07-28 19:51:54.000000000 +0000
@@ -6,7 +6,9 @@
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
@@ -360,7 +335,24 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.ja
if (ecP == null)
{
-@@ -60,10 +64,12 @@
+@@ -59,10 +63,12 @@
+ oid = SECNamedCurves.getOID(name);
+ }
+
+- if (oid == null)
+- {
+- oid = TeleTrusTNamedCurves.getOID(name);
+- }
++ // BEGIN android-removed
++ // if (oid == null)
++ // {
++ // oid = TeleTrusTNamedCurves.getOID(name);
++ // }
++ // END android-removed
+
+ if (oid == null)
+ {
+@@ -89,10 +95,12 @@
ecP = SECNamedCurves.getByOID(oid);
}
@@ -377,7 +369,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.ja
// NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup
-@@ -82,7 +88,9 @@
+@@ -111,7 +119,9 @@
addEnumeration(v, X962NamedCurves.getNames());
addEnumeration(v, SECNamedCurves.getNames());
addEnumeration(v, NISTNamedCurves.getNames());
@@ -388,9 +380,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.ja
return v.elements();
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigestFactory.java bcprov-jdk15on-150/org/bouncycastle/crypto/digests/AndroidDigestFactory.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigestFactory.java 1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/digests/AndroidDigestFactory.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactory.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactory.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactory.java 1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactory.java 2013-09-26 18:06:21.000000000 +0000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
@@ -479,9 +471,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigest
+ return FACTORY.getSHA512();
+ }
+}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java bcprov-jdk15on-150/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java 1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java 1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java 2013-09-26 18:06:21.000000000 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
@@ -523,9 +515,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigest
+ return new SHA512Digest();
+ }
+}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java bcprov-jdk15on-150/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java 1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java 1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java 2013-09-26 18:06:21.000000000 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
@@ -555,9 +547,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigest
+ public Digest getSHA384();
+ public Digest getSHA512();
+}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java bcprov-jdk15on-150/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java 1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java 1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java 2013-09-26 18:06:21.000000000 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
@@ -599,9 +591,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/AndroidDigest
+ return new OpenSSLDigest.SHA512();
+ }
+}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java bcprov-jdk15on-150/org/bouncycastle/crypto/digests/OpenSSLDigest.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java 1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/digests/OpenSSLDigest.java 2014-02-27 18:09:19.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/OpenSSLDigest.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java 1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/OpenSSLDigest.java 2014-02-27 18:09:19.000000000 +0000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
@@ -700,9 +692,95 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/digests/OpenSSLDigest
+ public SHA512() { super("SHA-512", 128); }
+ }
+}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/encodings/OAEPEncoding.java bcprov-jdk15on-150/org/bouncycastle/crypto/encodings/OAEPEncoding.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/encodings/OAEPEncoding.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/encodings/OAEPEncoding.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/ec/CustomNamedCurves.java bcprov-jdk15on-151/org/bouncycastle/crypto/ec/CustomNamedCurves.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/ec/CustomNamedCurves.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/ec/CustomNamedCurves.java 2014-07-28 19:51:54.000000000 +0000
+@@ -10,7 +10,9 @@
+ import org.bouncycastle.asn1.x9.X9ECParametersHolder;
+ import org.bouncycastle.math.ec.ECCurve;
+ import org.bouncycastle.math.ec.ECPoint;
+-import org.bouncycastle.math.ec.custom.djb.Curve25519;
++// BEGIN android-removed
++// import org.bouncycastle.math.ec.custom.djb.Curve25519;
++// END android-removed
+ import org.bouncycastle.math.ec.custom.sec.SecP192K1Curve;
+ import org.bouncycastle.math.ec.custom.sec.SecP192R1Curve;
+ import org.bouncycastle.math.ec.custom.sec.SecP224K1Curve;
+@@ -36,32 +38,34 @@
+ return c.configure().setEndomorphism(new GLVTypeBEndomorphism(c, p)).create();
+ }
+
+- /*
+- * curve25519
+- */
+- static X9ECParametersHolder curve25519 = new X9ECParametersHolder()
+- {
+- protected X9ECParameters createParameters()
+- {
+- byte[] S = null;
+- ECCurve curve = configureCurve(new Curve25519());
+-
+- /*
+- * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form
+- * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3).
+- *
+- * The Curve25519 paper doesn't say which of the two possible y values the base
+- * point has. The choice here is guided by language in the Ed25519 paper.
+- *
+- * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
+- */
+- ECPoint G = curve.decodePoint(Hex.decode("04"
+- + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
+- + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
+-
+- return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+- }
+- };
++ // BEGIN android-removed
++ // /*
++ // * curve25519
++ // */
++ // static X9ECParametersHolder curve25519 = new X9ECParametersHolder()
++ // {
++ // protected X9ECParameters createParameters()
++ // {
++ // byte[] S = null;
++ // ECCurve curve = configureCurve(new Curve25519());
++ //
++ // /*
++ // * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form
++ // * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3).
++ // *
++ // * The Curve25519 paper doesn't say which of the two possible y values the base
++ // * point has. The choice here is guided by language in the Ed25519 paper.
++ // *
++ // * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
++ // */
++ // ECPoint G = curve.decodePoint(Hex.decode("04"
++ // + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
++ // + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
++ //
++ // return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
++ // }
++ // };
++ // END android-removed
+
+ /*
+ * secp192k1
+@@ -254,7 +258,9 @@
+
+ static
+ {
+- defineCurve("curve25519", curve25519);
++ // BEGIN android-removed
++ // defineCurve("curve25519", curve25519);
++ // END android-removed
+
+ defineCurveWithOID("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1);
+ defineCurveWithOID("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1);
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/encodings/OAEPEncoding.java bcprov-jdk15on-151/org/bouncycastle/crypto/encodings/OAEPEncoding.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/encodings/OAEPEncoding.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/encodings/OAEPEncoding.java 2013-05-25 02:14:15.000000000 +0000
@@ -6,7 +6,9 @@
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
@@ -725,10 +803,10 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/encodings/OAEPEncodin
}
public OAEPEncoding(
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/encodings/PKCS1Encoding.java bcprov-jdk15on-150/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/encodings/PKCS1Encoding.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/encodings/PKCS1Encoding.java 2013-01-31 02:26:40.000000000 +0000
-@@ -216,6 +216,12 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/encodings/PKCS1Encoding.java bcprov-jdk15on-151/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/encodings/PKCS1Encoding.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/encodings/PKCS1Encoding.java 2014-07-28 19:51:54.000000000 +0000
+@@ -377,6 +377,12 @@
throw new InvalidCipherTextException("unknown block type");
}
}
@@ -741,9 +819,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/encodings/PKCS1Encodi
if (useStrictLength && block.length != engine.getOutputBlockSize())
{
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/engines/DESedeWrapEngine.java bcprov-jdk15on-150/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/engines/DESedeWrapEngine.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/engines/DESedeWrapEngine.java 2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/engines/DESedeWrapEngine.java bcprov-jdk15on-151/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/engines/DESedeWrapEngine.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/engines/DESedeWrapEngine.java 2014-07-28 19:51:54.000000000 +0000
@@ -6,7 +6,9 @@
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.InvalidCipherTextException;
@@ -766,16 +844,17 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/engines/DESedeWrapEng
byte[] digest = new byte[20];
/**
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/DHParametersHelper.java bcprov-jdk15on-150/org/bouncycastle/crypto/generators/DHParametersHelper.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/DHParametersHelper.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/generators/DHParametersHelper.java 2012-09-17 23:04:47.000000000 +0000
-@@ -3,10 +3,17 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/DHParametersHelper.java bcprov-jdk15on-151/org/bouncycastle/crypto/generators/DHParametersHelper.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/DHParametersHelper.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/generators/DHParametersHelper.java 2014-07-28 19:51:54.000000000 +0000
+@@ -3,11 +3,18 @@
import java.math.BigInteger;
import java.security.SecureRandom;
+// BEGIN android-added
+import java.util.logging.Logger;
+// END android-added
+ import org.bouncycastle.math.ec.WNafUtil;
import org.bouncycastle.util.BigIntegers;
class DHParametersHelper
@@ -787,7 +866,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/DHParamete
private static final BigInteger ONE = BigInteger.valueOf(1);
private static final BigInteger TWO = BigInteger.valueOf(2);
-@@ -17,11 +24,19 @@
+@@ -18,12 +25,20 @@
*/
static BigInteger[] generateSafePrimes(int size, int certainty, SecureRandom random)
{
@@ -798,6 +877,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/DHParamete
+ // END android-added
BigInteger p, q;
int qLength = size - 1;
+ int minWeight = size >>> 2;
for (;;)
{
@@ -807,9 +887,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/DHParamete
q = new BigInteger(qLength, 2, random);
// p <- 2q + 1
-@@ -32,6 +47,11 @@
- break;
- }
+@@ -52,6 +67,11 @@
+
+ break;
}
+ // BEGIN android-added
+ long end = System.currentTimeMillis();
@@ -819,9 +899,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/DHParamete
return new BigInteger[] { p, q };
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/DSAParametersGenerator.java bcprov-jdk15on-150/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/DSAParametersGenerator.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/generators/DSAParametersGenerator.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/DSAParametersGenerator.java bcprov-jdk15on-151/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/DSAParametersGenerator.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/generators/DSAParametersGenerator.java 2014-07-28 19:51:54.000000000 +0000
@@ -4,7 +4,9 @@
import java.security.SecureRandom;
@@ -855,9 +935,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/DSAParamet
{
throw new IllegalStateException("can only use SHA-1 for generating FIPS 186-2 parameters");
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java bcprov-jdk15on-150/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java 2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java bcprov-jdk15on-151/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java 2012-09-17 23:04:47.000000000 +0000
@@ -3,7 +3,9 @@
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
@@ -880,9 +960,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/OpenSSLPBE
/**
* Construct a OpenSSL Parameters generator.
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java bcprov-jdk15on-150/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java bcprov-jdk15on-151/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java 2013-12-12 00:35:05.000000000 +0000
@@ -4,7 +4,9 @@
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Mac;
@@ -905,9 +985,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/generators/PKCS5S2Par
}
public PKCS5S2ParametersGenerator(Digest digest)
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/macs/HMac.java bcprov-jdk15on-150/org/bouncycastle/crypto/macs/HMac.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/macs/HMac.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/macs/HMac.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/macs/HMac.java bcprov-jdk15on-151/org/bouncycastle/crypto/macs/HMac.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/macs/HMac.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/macs/HMac.java 2013-09-26 18:06:21.000000000 +0000
@@ -36,14 +36,18 @@
{
blockLengths = new Hashtable();
@@ -946,9 +1026,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/macs/HMac.java bcprov
}
private static int getByteLength(
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java bcprov-jdk15on-150/org/bouncycastle/crypto/signers/RSADigestSigner.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/signers/RSADigestSigner.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java bcprov-jdk15on-151/org/bouncycastle/crypto/signers/RSADigestSigner.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/signers/RSADigestSigner.java 2014-07-28 19:51:54.000000000 +0000
@@ -39,9 +39,11 @@
*/
static
@@ -964,9 +1044,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/signers/RSADigestSign
oidMap.put("SHA-1", X509ObjectIdentifiers.id_SHA1);
oidMap.put("SHA-224", NISTObjectIdentifiers.id_sha224);
-@@ -49,8 +51,10 @@
- oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384);
- oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512);
+@@ -51,8 +53,10 @@
+ oidMap.put("SHA-512/224", NISTObjectIdentifiers.id_sha512_224);
+ oidMap.put("SHA-512/256", NISTObjectIdentifiers.id_sha512_256);
- oidMap.put("MD2", PKCSObjectIdentifiers.md2);
- oidMap.put("MD4", PKCSObjectIdentifiers.md4);
@@ -977,13 +1057,13 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/signers/RSADigestSign
oidMap.put("MD5", PKCSObjectIdentifiers.md5);
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java bcprov-jdk15on-150/org/bouncycastle/crypto/util/PrivateKeyFactory.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/util/PrivateKeyFactory.java 2013-12-12 00:35:05.000000000 +0000
-@@ -10,7 +10,9 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java bcprov-jdk15on-151/org/bouncycastle/crypto/util/PrivateKeyFactory.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/util/PrivateKeyFactory.java 2014-07-28 19:51:54.000000000 +0000
+@@ -9,7 +9,9 @@
+ import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
- import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.oiw.ElGamalParameter;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.oiw.ElGamalParameter;
@@ -991,9 +1071,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PrivateKeyFactor
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-@@ -30,8 +32,10 @@
- import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+@@ -31,8 +33,10 @@
import org.bouncycastle.crypto.params.ECDomainParameters;
+ import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
@@ -1004,13 +1084,13 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PrivateKeyFactor
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
/**
-@@ -97,14 +101,16 @@
+@@ -98,14 +102,16 @@
return new DHPrivateKeyParameters(derX.getValue(), dhParams);
}
- else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
- {
-- ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
+- ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
- ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
-
- return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(
@@ -1019,8 +1099,8 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PrivateKeyFactor
+ // BEGIN android-removed
+ // else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
+ // {
-+ // ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
-+ // ASN1Integer = (ASN1Integer)keyInfo.parsePrivateKey();
++ // ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
++ // ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
+ //
+ // return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(
+ // params.getP(), params.getG()));
@@ -1029,12 +1109,12 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PrivateKeyFactor
else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa))
{
ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java bcprov-jdk15on-150/org/bouncycastle/crypto/util/PublicKeyFactory.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/crypto/util/PublicKeyFactory.java 2013-12-12 00:35:05.000000000 +0000
-@@ -12,7 +12,9 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java bcprov-jdk15on-151/org/bouncycastle/crypto/util/PublicKeyFactory.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/crypto/util/PublicKeyFactory.java 2014-07-28 19:51:54.000000000 +0000
+@@ -11,7 +11,9 @@
+ import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
- import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.oiw.ElGamalParameter;
+// BEGIN android-removed
@@ -1043,9 +1123,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PublicKeyFactory
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-@@ -37,8 +39,10 @@
- import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+@@ -38,8 +40,10 @@
import org.bouncycastle.crypto.params.ECDomainParameters;
+ import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
@@ -1056,13 +1136,13 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PublicKeyFactory
import org.bouncycastle.crypto.params.RSAKeyParameters;
/**
-@@ -132,14 +136,16 @@
+@@ -133,14 +137,16 @@
return new DHPublicKeyParameters(derY.getValue(), dhParams);
}
- else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
- {
-- ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
+- ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
- ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
-
- return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
@@ -1071,7 +1151,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PublicKeyFactory
+ // BEGIN android-removed
+ // else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
+ // {
-+ // ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
++ // ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
+ // ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
+ //
+ // return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
@@ -1081,36 +1161,10 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/crypto/util/PublicKeyFactory
else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)
|| algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1))
{
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/DH.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/DH.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/DH.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/DH.java 2014-05-08 00:26:23.000000000 +0000
-@@ -1,7 +1,14 @@
- package org.bouncycastle.jcajce.provider.asymmetric;
-
-+// BEGIN android-added
-+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-+import org.bouncycastle.jcajce.provider.asymmetric.dh.KeyFactorySpi;
-+// END android-added
- import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
- import org.bouncycastle.jcajce.provider.util.AsymmetricAlgorithmProvider;
-+// BEGIN android-added
-+import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
-+// END android-added
-
- public class DH
- {
-@@ -24,6 +31,10 @@
-
- provider.addAlgorithm("KeyFactory.DH", PREFIX + "KeyFactorySpi");
- provider.addAlgorithm("Alg.Alias.KeyFactory.DIFFIEHELLMAN", "DH");
-+ // BEGIN android-added
-+ AsymmetricKeyInfoConverter keyFact = new KeyFactorySpi();
-+ registerOid(provider, PKCSObjectIdentifiers.dhKeyAgreement, "DH", keyFact);
-+ // END android-added
-
- provider.addAlgorithm("AlgorithmParameters.DH", PREFIX + "AlgorithmParametersSpi");
- provider.addAlgorithm("Alg.Alias.AlgorithmParameters.DIFFIEHELLMAN", "DH");
-@@ -32,10 +43,12 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/DH.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/DH.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/DH.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/DH.java 2014-07-28 19:51:54.000000000 +0000
+@@ -35,10 +35,12 @@
provider.addAlgorithm("AlgorithmParameterGenerator.DH", PREFIX + "AlgorithmParameterGeneratorSpi");
@@ -1124,12 +1178,12 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/D
+ // provider.addAlgorithm("Cipher.DHIESWITHAES", PREFIX + "IESCipher$IESwithAES");
+ // provider.addAlgorithm("Cipher.DHIESWITHDESEDE", PREFIX + "IESCipher$IESwithDESede");
+ // END android-removed
- }
- }
- }
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/DSA.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/DSA.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/DSA.java 2013-12-16 16:39:58.000000000 +0000
+
+ registerOid(provider, PKCSObjectIdentifiers.dhKeyAgreement, "DH", new KeyFactorySpi());
+ registerOid(provider, X9ObjectIdentifiers.dhpublicnumber, "DH", new KeyFactorySpi());
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/DSA.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/DSA.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/DSA.java 2013-12-16 16:39:58.000000000 +0000
@@ -27,40 +27,53 @@
provider.addAlgorithm("KeyPairGenerator.DSA", PREFIX + "KeyPairGeneratorSpi");
provider.addAlgorithm("KeyFactory.DSA", PREFIX + "KeyFactorySpi");
@@ -1205,22 +1259,24 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/D
registerOid(provider, DSAUtil.dsaOids[i], "DSA", keyFact);
registerOidAlgorithmParameters(provider, DSAUtil.dsaOids[i], "DSA");
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/EC.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/EC.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/EC.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/EC.java 2013-12-12 00:35:05.000000000 +0000
-@@ -1,7 +1,9 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/EC.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/EC.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/EC.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/EC.java 2014-07-28 19:51:54.000000000 +0000
+@@ -1,8 +1,10 @@
package org.bouncycastle.jcajce.provider.asymmetric;
+-import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
-import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
-import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+// BEGIN android-removed
++// import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers;
+// import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
+// import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+// END android-removed
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
-@@ -21,39 +23,49 @@
+@@ -22,45 +24,55 @@
public void configure(ConfigurableProvider provider)
{
provider.addAlgorithm("KeyAgreement.ECDH", PREFIX + "KeyAgreementSpi$DH");
@@ -1228,30 +1284,28 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/E
- provider.addAlgorithm("KeyAgreement.ECMQV", PREFIX + "KeyAgreementSpi$MQV");
- provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA1KDF");
- provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA1KDF");
+- provider.addAlgorithm("KeyAgreement.ECDHWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHwithSHA1KDF");
+ // BEGIN android-removed
+ // provider.addAlgorithm("KeyAgreement.ECDHC", PREFIX + "KeyAgreementSpi$DHC");
+ // provider.addAlgorithm("KeyAgreement.ECMQV", PREFIX + "KeyAgreementSpi$MQV");
+ // provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA1KDF");
+ // provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA1KDF");
++ // provider.addAlgorithm("KeyAgreement.ECDHWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHwithSHA1KDF");
+ // END android-removed
registerOid(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC", new KeyFactorySpi.EC());
// TODO Should this be an alias for ECDH?
registerOid(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC", new KeyFactorySpi.EC());
- registerOid(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV());
--
-- registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
-- // TODO Should this be an alias for ECDH?
-- registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
-- registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "EC");
+ // BEGIN android-removed
+ // registerOid(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV());
+ // END android-removed
-+
+
+ registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
+ // TODO Should this be an alias for ECDH?
+ registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
+- registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "EC");
+ // BEGIN android-removed
-+ // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
-+ // // TODO Should this be an alias for ECDH?
-+ // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
+ // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "EC");
+ // END android-removed
@@ -1270,6 +1324,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/E
provider.addAlgorithm("KeyPairGenerator.EC", PREFIX + "KeyPairGeneratorSpi$EC");
- provider.addAlgorithm("KeyPairGenerator.ECDSA", PREFIX + "KeyPairGeneratorSpi$ECDSA");
- provider.addAlgorithm("KeyPairGenerator.ECDH", PREFIX + "KeyPairGeneratorSpi$ECDH");
+- provider.addAlgorithm("KeyPairGenerator.ECDHWITHSHA1KDF", PREFIX + "KeyPairGeneratorSpi$ECDH");
- provider.addAlgorithm("KeyPairGenerator.ECDHC", PREFIX + "KeyPairGeneratorSpi$ECDHC");
- provider.addAlgorithm("KeyPairGenerator.ECIES", PREFIX + "KeyPairGeneratorSpi$ECDH");
- provider.addAlgorithm("KeyPairGenerator.ECMQV", PREFIX + "KeyPairGeneratorSpi$ECMQV");
@@ -1279,9 +1334,14 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/E
- provider.addAlgorithm("Cipher.ECIESWITHAES", PREFIX + "IESCipher$ECIESwithAES");
- provider.addAlgorithm("Cipher.ECIESwithDESEDE", PREFIX + "IESCipher$ECIESwithDESede");
- provider.addAlgorithm("Cipher.ECIESWITHDESEDE", PREFIX + "IESCipher$ECIESwithDESede");
+- provider.addAlgorithm("Cipher.ECIESwithAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC");
+- provider.addAlgorithm("Cipher.ECIESWITHAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC");
+- provider.addAlgorithm("Cipher.ECIESwithDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC");
+- provider.addAlgorithm("Cipher.ECIESWITHDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC");
+ // BEGIN android-removed
+ // provider.addAlgorithm("KeyPairGenerator.ECDSA", PREFIX + "KeyPairGeneratorSpi$ECDSA");
+ // provider.addAlgorithm("KeyPairGenerator.ECDH", PREFIX + "KeyPairGeneratorSpi$ECDH");
++ // provider.addAlgorithm("KeyPairGenerator.ECDHWITHSHA1KDF", PREFIX + "KeyPairGeneratorSpi$ECDH");
+ // provider.addAlgorithm("KeyPairGenerator.ECDHC", PREFIX + "KeyPairGeneratorSpi$ECDHC");
+ // provider.addAlgorithm("KeyPairGenerator.ECIES", PREFIX + "KeyPairGeneratorSpi$ECDH");
+ // provider.addAlgorithm("KeyPairGenerator.ECMQV", PREFIX + "KeyPairGeneratorSpi$ECMQV");
@@ -1291,11 +1351,15 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/E
+ // provider.addAlgorithm("Cipher.ECIESWITHAES", PREFIX + "IESCipher$ECIESwithAES");
+ // provider.addAlgorithm("Cipher.ECIESwithDESEDE", PREFIX + "IESCipher$ECIESwithDESede");
+ // provider.addAlgorithm("Cipher.ECIESWITHDESEDE", PREFIX + "IESCipher$ECIESwithDESede");
++ // provider.addAlgorithm("Cipher.ECIESwithAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC");
++ // provider.addAlgorithm("Cipher.ECIESWITHAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC");
++ // provider.addAlgorithm("Cipher.ECIESwithDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC");
++ // provider.addAlgorithm("Cipher.ECIESWITHDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC");
+ // END android-removed
provider.addAlgorithm("Signature.ECDSA", PREFIX + "SignatureSpi$ecDSA");
provider.addAlgorithm("Signature.NONEwithECDSA", PREFIX + "SignatureSpi$ecDSAnone");
-@@ -65,32 +77,36 @@
+@@ -72,39 +84,43 @@
provider.addAlgorithm("Alg.Alias.Signature.SHA1WithECDSA", "ECDSA");
provider.addAlgorithm("Alg.Alias.Signature.ECDSAWithSHA1", "ECDSA");
provider.addAlgorithm("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
@@ -1335,6 +1399,13 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/E
- addSignatureAlgorithm(provider, "SHA256", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA256", EACObjectIdentifiers.id_TA_ECDSA_SHA_256);
- addSignatureAlgorithm(provider, "SHA384", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA384", EACObjectIdentifiers.id_TA_ECDSA_SHA_384);
- addSignatureAlgorithm(provider, "SHA512", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA512", EACObjectIdentifiers.id_TA_ECDSA_SHA_512);
+-
+- addSignatureAlgorithm(provider, "SHA1", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA", BSIObjectIdentifiers.ecdsa_plain_SHA1);
+- addSignatureAlgorithm(provider, "SHA224", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA224", BSIObjectIdentifiers.ecdsa_plain_SHA224);
+- addSignatureAlgorithm(provider, "SHA256", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA256", BSIObjectIdentifiers.ecdsa_plain_SHA256);
+- addSignatureAlgorithm(provider, "SHA384", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA384", BSIObjectIdentifiers.ecdsa_plain_SHA384);
+- addSignatureAlgorithm(provider, "SHA512", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA512", BSIObjectIdentifiers.ecdsa_plain_SHA512);
+- addSignatureAlgorithm(provider, "RIPEMD160", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecPlainDSARP160", BSIObjectIdentifiers.ecdsa_plain_RIPEMD160);
+ // BEGIN android-removed
+ // addSignatureAlgorithm(provider, "RIPEMD160", "ECDSA", PREFIX + "SignatureSpi$ecDSARipeMD160",TeleTrusTObjectIdentifiers.ecSignWithRipemd160);
+ //
@@ -1349,13 +1420,20 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/E
+ // addSignatureAlgorithm(provider, "SHA256", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA256", EACObjectIdentifiers.id_TA_ECDSA_SHA_256);
+ // addSignatureAlgorithm(provider, "SHA384", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA384", EACObjectIdentifiers.id_TA_ECDSA_SHA_384);
+ // addSignatureAlgorithm(provider, "SHA512", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA512", EACObjectIdentifiers.id_TA_ECDSA_SHA_512);
++ //
++ // addSignatureAlgorithm(provider, "SHA1", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA", BSIObjectIdentifiers.ecdsa_plain_SHA1);
++ // addSignatureAlgorithm(provider, "SHA224", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA224", BSIObjectIdentifiers.ecdsa_plain_SHA224);
++ // addSignatureAlgorithm(provider, "SHA256", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA256", BSIObjectIdentifiers.ecdsa_plain_SHA256);
++ // addSignatureAlgorithm(provider, "SHA384", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA384", BSIObjectIdentifiers.ecdsa_plain_SHA384);
++ // addSignatureAlgorithm(provider, "SHA512", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA512", BSIObjectIdentifiers.ecdsa_plain_SHA512);
++ // addSignatureAlgorithm(provider, "RIPEMD160", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecPlainDSARP160", BSIObjectIdentifiers.ecdsa_plain_RIPEMD160);
+ // END android-removed
}
}
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/RSA.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/RSA.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/RSA.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/RSA.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/RSA.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/RSA.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/RSA.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/RSA.java 2014-07-28 19:51:54.000000000 +0000
@@ -3,7 +3,9 @@
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
@@ -1463,6 +1541,10 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/R
- provider.addAlgorithm("Signature." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA");
- provider.addAlgorithm("Signature.OID." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA");
-
+- provider.addAlgorithm("Signature.SHA224WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA224withRSA");
+- provider.addAlgorithm("Signature.SHA256WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA256withRSA");
+- provider.addAlgorithm("Signature.SHA384WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA384withRSA");
+- provider.addAlgorithm("Signature.SHA512WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA512withRSA");
- provider.addAlgorithm("Signature.SHA224withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA224withRSA");
- provider.addAlgorithm("Signature.SHA256withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA256withRSA");
- provider.addAlgorithm("Signature.SHA384withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA384withRSA");
@@ -1484,10 +1566,6 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/R
- provider.addAlgorithm("Alg.Alias.Signature.SHA256withRSAandMGF1", "SHA256withRSA/PSS");
- provider.addAlgorithm("Alg.Alias.Signature.SHA384withRSAandMGF1", "SHA384withRSA/PSS");
- provider.addAlgorithm("Alg.Alias.Signature.SHA512withRSAandMGF1", "SHA512withRSA/PSS");
-- provider.addAlgorithm("Alg.Alias.Signature.SHA224WITHRSAANDMGF1", "SHA224withRSA/PSS");
-- provider.addAlgorithm("Alg.Alias.Signature.SHA256WITHRSAANDMGF1", "SHA256withRSA/PSS");
-- provider.addAlgorithm("Alg.Alias.Signature.SHA384WITHRSAANDMGF1", "SHA384withRSA/PSS");
-- provider.addAlgorithm("Alg.Alias.Signature.SHA512WITHRSAANDMGF1", "SHA512withRSA/PSS");
-
- if (provider.hasAlgorithm("MessageDigest", "MD2"))
- {
@@ -1511,6 +1589,10 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/R
+ // provider.addAlgorithm("Signature." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA");
+ // provider.addAlgorithm("Signature.OID." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA");
+ //
++ // provider.addAlgorithm("Signature.SHA224WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA224withRSA");
++ // provider.addAlgorithm("Signature.SHA256WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA256withRSA");
++ // provider.addAlgorithm("Signature.SHA384WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA384withRSA");
++ // provider.addAlgorithm("Signature.SHA512WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA512withRSA");
+ // provider.addAlgorithm("Signature.SHA224withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA224withRSA");
+ // provider.addAlgorithm("Signature.SHA256withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA256withRSA");
+ // provider.addAlgorithm("Signature.SHA384withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA384withRSA");
@@ -1532,10 +1614,6 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/R
+ // provider.addAlgorithm("Alg.Alias.Signature.SHA256withRSAandMGF1", "SHA256withRSA/PSS");
+ // provider.addAlgorithm("Alg.Alias.Signature.SHA384withRSAandMGF1", "SHA384withRSA/PSS");
+ // provider.addAlgorithm("Alg.Alias.Signature.SHA512withRSAandMGF1", "SHA512withRSA/PSS");
-+ // provider.addAlgorithm("Alg.Alias.Signature.SHA224WITHRSAANDMGF1", "SHA224withRSA/PSS");
-+ // provider.addAlgorithm("Alg.Alias.Signature.SHA256WITHRSAANDMGF1", "SHA256withRSA/PSS");
-+ // provider.addAlgorithm("Alg.Alias.Signature.SHA384WITHRSAANDMGF1", "SHA384withRSA/PSS");
-+ // provider.addAlgorithm("Alg.Alias.Signature.SHA512WITHRSAANDMGF1", "SHA512withRSA/PSS");
+ //
+ // if (provider.hasAlgorithm("MessageDigest", "MD2"))
+ // {
@@ -1553,7 +1631,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/R
addDigestSignature(provider, "MD5", PREFIX + "DigestSignatureSpi$MD5", PKCSObjectIdentifiers.md5WithRSAEncryption);
- provider.addAlgorithm("Signature.MD5withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$MD5WithRSAEncryption");
- provider.addAlgorithm("Alg.Alias.Signature.MD5WithRSA/ISO9796-2", "MD5withRSA/ISO9796-2");
-+ // BEGIN android-removed
++ // END android-removed
+ // provider.addAlgorithm("Signature.MD5withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$MD5WithRSAEncryption");
+ // provider.addAlgorithm("Alg.Alias.Signature.MD5WithRSA/ISO9796-2", "MD5withRSA/ISO9796-2");
+ // END android-removed
@@ -1632,9 +1710,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/R
}
private void addDigestSignature(
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/X509.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/X509.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/X509.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/X509.java 2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/X509.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/X509.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/X509.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/X509.java 2012-09-17 23:04:47.000000000 +0000
@@ -18,8 +18,10 @@
public void configure(ConfigurableProvider provider)
@@ -1648,9 +1726,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/X
//
// certificate factories.
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java 2013-12-12 00:35:05.000000000 +0000
@@ -23,13 +23,20 @@
import org.bouncycastle.crypto.DSA;
import org.bouncycastle.crypto.Digest;
@@ -1844,10 +1922,10 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/d
static public class noneDSA
extends DSASigner
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java 2013-12-12 00:35:05.000000000 +0000
-@@ -23,21 +23,27 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java 2014-07-28 19:51:54.000000000 +0000
+@@ -24,22 +24,28 @@
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
@@ -1862,6 +1940,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+// import org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator;
+// END android-removed
import org.bouncycastle.crypto.digests.SHA1Digest;
+ import org.bouncycastle.crypto.params.DESParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
@@ -1881,9 +1960,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+// import org.bouncycastle.jce.interfaces.MQVPublicKey;
+// END android-removed
import org.bouncycastle.util.Integers;
+ import org.bouncycastle.util.Strings;
- /**
-@@ -71,7 +77,9 @@
+@@ -89,7 +95,9 @@
private BigInteger result;
private ECDomainParameters parameters;
private BasicAgreement agreement;
@@ -1894,7 +1973,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
private byte[] bigIntToBytes(
BigInteger r)
-@@ -86,7 +94,9 @@
+@@ -104,7 +112,9 @@
{
this.kaAlgorithm = kaAlgorithm;
this.agreement = agreement;
@@ -1905,7 +1984,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
}
protected Key engineDoPhase(
-@@ -105,25 +115,27 @@
+@@ -123,25 +133,27 @@
}
CipherParameters pubKey;
@@ -1952,7 +2031,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
{
if (!(key instanceof PublicKey))
{
-@@ -144,11 +156,13 @@
+@@ -162,11 +174,13 @@
protected byte[] engineGenerateSecret()
throws IllegalStateException
{
@@ -1971,20 +2050,20 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
return bigIntToBytes(result);
}
-@@ -176,23 +190,25 @@
- {
- byte[] secret = bigIntToBytes(result);
+@@ -201,23 +215,25 @@
+ oidAlgorithm = ((ASN1ObjectIdentifier)oids.get(algKey)).getId();
+ }
- if (kdf != null)
- {
-- if (!algorithms.containsKey(algorithm))
+- if (!algorithms.containsKey(oidAlgorithm))
- {
- throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm);
- }
-
-- int keySize = ((Integer)algorithms.get(algorithm)).intValue();
+- int keySize = ((Integer)algorithms.get(oidAlgorithm)).intValue();
-
-- DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(algorithm), keySize, secret);
+- DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(oidAlgorithm), keySize, secret);
-
- byte[] keyBytes = new byte[keySize / 8];
- kdf.init(params);
@@ -1995,14 +2074,14 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ // BEGIN android-removed
+ // if (kdf != null)
+ // {
-+ // if (!algorithms.containsKey(algorithm))
++ // if (!algorithms.containsKey(oidAlgorithm))
+ // {
+ // throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm);
+ // }
+ //
-+ // int keySize = ((Integer)algorithms.get(algorithm)).intValue();
++ // int keySize = ((Integer)algorithms.get(oidAlgorithm)).intValue();
+ //
-+ // DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(algorithm), keySize, secret);
++ // DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(oidAlgorithm), keySize, secret);
+ //
+ // byte[] keyBytes = new byte[keySize / 8];
+ // kdf.init(params);
@@ -2012,22 +2091,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ // else
+ // END android-removed
{
- // TODO Should we be ensuring the key is the right length?
- }
-@@ -206,6 +222,12 @@
- SecureRandom random)
- throws InvalidKeyException, InvalidAlgorithmParameterException
- {
-+ // BEGIN android-added
-+ if (params != null)
-+ {
-+ throw new InvalidAlgorithmParameterException("No algorithm parameters supported");
-+ }
-+ // END android-added
- initFromKey(key);
- }
-
-@@ -220,35 +242,37 @@
+ if (algorithms.containsKey(oidAlgorithm))
+ {
+@@ -264,35 +280,37 @@
private void initFromKey(Key key)
throws InvalidKeyException
{
@@ -2094,7 +2160,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
{
if (!(key instanceof PrivateKey))
{
-@@ -279,39 +303,41 @@
+@@ -323,39 +341,41 @@
}
}
@@ -2171,9 +2237,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ // }
+ // END android-removed
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java 2013-05-25 02:14:15.000000000 +0000
@@ -201,14 +201,16 @@
}
}
@@ -2199,9 +2265,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
public static class ECDH
extends KeyFactorySpi
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java 2014-07-28 19:51:54.000000000 +0000
@@ -84,7 +84,13 @@
SecureRandom random)
{
@@ -2213,10 +2279,10 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ // BEGIN android-added
+ }
+ // END android-added
- ECGenParameterSpec ecParams = (ECGenParameterSpec)ecParameters.get(Integers.valueOf(strength));
- if (ecParams != null)
-@@ -109,6 +115,11 @@
+ ECGenParameterSpec ecParams = (ECGenParameterSpec)ecParameters.get(Integers.valueOf(strength));
+ if (ecParams == null)
+@@ -107,6 +113,11 @@
SecureRandom random)
throws InvalidAlgorithmParameterException
{
@@ -2225,12 +2291,19 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ random = this.random;
+ }
+ // END android-added
- if (params instanceof ECParameterSpec)
+ if (params == null)
{
- ECParameterSpec p = (ECParameterSpec)params;
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java 2013-12-12 00:35:05.000000000 +0000
+ ECParameterSpec implicitCA = configuration.getEcImplicitlyCa();
+@@ -267,4 +278,4 @@
+ super("ECMQV", BouncyCastleProvider.CONFIGURATION);
+ }
+ }
+-}
+\ No newline at end of file
++}
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java 2014-07-28 19:51:54.000000000 +0000
@@ -16,16 +16,23 @@
import org.bouncycastle.crypto.DSA;
import org.bouncycastle.crypto.Digest;
@@ -2295,7 +2368,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
static public class ecDSAnone
extends SignatureSpi
-@@ -97,171 +108,187 @@
+@@ -97,180 +108,196 @@
{
public ecDSA224()
{
@@ -2464,7 +2537,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
- {
- public ecCVCDSA()
- {
-- super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder());
+- super(new SHA1Digest(), new ECDSASigner(), new PlainDSAEncoder());
- }
- }
-
@@ -2473,7 +2546,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
- {
- public ecCVCDSA224()
- {
-- super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder());
+- super(new SHA224Digest(), new ECDSASigner(), new PlainDSAEncoder());
- }
- }
-
@@ -2482,7 +2555,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
- {
- public ecCVCDSA256()
- {
-- super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder());
+- super(new SHA256Digest(), new ECDSASigner(), new PlainDSAEncoder());
- }
- }
-
@@ -2491,7 +2564,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
- {
- public ecCVCDSA384()
- {
-- super(new SHA384Digest(), new ECDSASigner(), new CVCDSAEncoder());
+- super(new SHA384Digest(), new ECDSASigner(), new PlainDSAEncoder());
- }
- }
-
@@ -2500,7 +2573,16 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
- {
- public ecCVCDSA512()
- {
-- super(new SHA512Digest(), new ECDSASigner(), new CVCDSAEncoder());
+- super(new SHA512Digest(), new ECDSASigner(), new PlainDSAEncoder());
+- }
+- }
+-
+- static public class ecPlainDSARP160
+- extends SignatureSpi
+- {
+- public ecPlainDSARP160()
+- {
+- super(new RIPEMD160Digest(), new ECDSASigner(), new PlainDSAEncoder());
- }
- }
+ // BEGIN android-changed
@@ -2578,7 +2660,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ // {
+ // public ecCVCDSA()
+ // {
-+ // super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder());
++ // super(new SHA1Digest(), new ECDSASigner(), new PlainDSAEncoder());
+ // }
+ // }
+ //
@@ -2587,7 +2669,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ // {
+ // public ecCVCDSA224()
+ // {
-+ // super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder());
++ // super(new SHA224Digest(), new ECDSASigner(), new PlainDSAEncoder());
+ // }
+ // }
+ //
@@ -2596,7 +2678,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ // {
+ // public ecCVCDSA256()
+ // {
-+ // super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder());
++ // super(new SHA256Digest(), new ECDSASigner(), new PlainDSAEncoder());
+ // }
+ // }
+ //
@@ -2605,7 +2687,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ // {
+ // public ecCVCDSA384()
+ // {
-+ // super(new SHA384Digest(), new ECDSASigner(), new CVCDSAEncoder());
++ // super(new SHA384Digest(), new ECDSASigner(), new PlainDSAEncoder());
+ // }
+ // }
+ //
@@ -2614,23 +2696,158 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/e
+ // {
+ // public ecCVCDSA512()
+ // {
-+ // super(new SHA512Digest(), new ECDSASigner(), new CVCDSAEncoder());
++ // super(new SHA512Digest(), new ECDSASigner(), new PlainDSAEncoder());
++ // }
++ // }
++ //
++ // static public class ecPlainDSARP160
++ // extends SignatureSpi
++ // {
++ // public ecPlainDSARP160()
++ // {
++ // super(new RIPEMD160Digest(), new ECDSASigner(), new PlainDSAEncoder());
+ // }
+ // }
+ // END android-removed
private static class StdDSAEncoder
implements DSAEncoder
-@@ -355,4 +382,4 @@
- return sig;
+@@ -302,66 +329,68 @@
}
}
+
+- private static class PlainDSAEncoder
+- 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;
+- }
+- }
-}
\ No newline at end of file
++ // BEGIN android-removed
++ // private static class PlainDSAEncoder
++ // 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;
++ // }
++ // }
++ // END android-removed
+}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java 2014-07-28 19:51:54.000000000 +0000
@@ -26,7 +26,9 @@
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
@@ -2754,9 +2971,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/r
+ // }
+ // END android-removed
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java 2013-09-26 18:06:21.000000000 +0000
@@ -17,24 +17,31 @@
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
@@ -2979,9 +3196,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/r
+ // }
+ // END android-removed
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java 2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java 2012-09-17 23:04:47.000000000 +0000
@@ -18,8 +18,10 @@
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
@@ -3008,9 +3225,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/u
};
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java 2014-07-28 19:51:54.000000000 +0000
@@ -5,11 +5,15 @@
import java.security.PublicKey;
@@ -3029,7 +3246,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/u
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962NamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
-@@ -225,14 +229,16 @@
+@@ -226,14 +230,16 @@
{
oid = NISTNamedCurves.getOID(name);
}
@@ -3054,7 +3271,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/u
}
return oid;
-@@ -250,10 +256,12 @@
+@@ -255,10 +261,12 @@
{
params = NISTNamedCurves.getByOID(oid);
}
@@ -3071,7 +3288,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/u
}
return params;
-@@ -271,14 +279,16 @@
+@@ -276,14 +284,16 @@
{
name = NISTNamedCurves.getName(oid);
}
@@ -3096,9 +3313,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/u
}
return name;
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java 2013-02-21 00:01:31.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java 2013-02-21 00:01:31.000000000 +0000
@@ -36,7 +36,9 @@
import org.bouncycastle.asn1.pkcs.SignedData;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -3172,9 +3389,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/x
else
{
throw new CertificateEncodingException("unsupported encoding: " + encoding);
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java 2013-05-25 02:14:15.000000000 +0000
@@ -57,6 +57,9 @@
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.GeneralName;
@@ -3218,13 +3435,13 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/x
break;
case GeneralName.dNSName:
case GeneralName.rfc822Name:
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java 2014-07-28 19:51:54.000000000 +0000
@@ -14,12 +14,16 @@
+ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERNull;
- import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
@@ -3281,9 +3498,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/asymmetric/x
else
{
return digestAlgOID.getId();
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/digest/SHA256.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/digest/SHA256.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/digest/SHA256.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/digest/SHA256.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA256.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA256.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA256.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA256.java 2013-05-25 02:14:15.000000000 +0000
@@ -45,17 +45,19 @@
}
}
@@ -3330,9 +3547,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/digest/SHA25
addHMACAlgorithm(provider, "SHA256", PREFIX + "$HashMac", PREFIX + "$KeyGenerator");
addHMACAlias(provider, "SHA256", PKCSObjectIdentifiers.id_hmacWithSHA256);
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/digest/SHA384.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/digest/SHA384.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/digest/SHA384.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/digest/SHA384.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA384.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA384.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA384.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA384.java 2013-05-25 02:14:15.000000000 +0000
@@ -5,7 +5,9 @@
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.digests.SHA384Digest;
@@ -3380,9 +3597,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/digest/SHA38
addHMACAlgorithm(provider, "SHA384", PREFIX + "$HashMac", PREFIX + "$KeyGenerator");
addHMACAlias(provider, "SHA384", PKCSObjectIdentifiers.id_hmacWithSHA384);
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/digest/SHA512.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/digest/SHA512.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/digest/SHA512.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/digest/SHA512.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA512.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA512.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA512.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA512.java 2013-05-25 02:14:15.000000000 +0000
@@ -4,9 +4,13 @@
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.crypto.CipherKeyGenerator;
@@ -3627,9 +3844,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/digest/SHA51
}
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/BC.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/keystore/BC.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/BC.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/keystore/BC.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/BC.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/BC.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/BC.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/BC.java 2013-05-25 02:14:15.000000000 +0000
@@ -17,7 +17,9 @@
public void configure(ConfigurableProvider provider)
{
@@ -3641,9 +3858,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/BC.
provider.addAlgorithm("KeyStore.BouncyCastle", PREFIX + "BcKeyStoreSpi$BouncyCastleStore");
provider.addAlgorithm("Alg.Alias.KeyStore.UBER", "BouncyCastle");
provider.addAlgorithm("Alg.Alias.KeyStore.BOUNCYCASTLE", "BouncyCastle");
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/PKCS12.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/keystore/PKCS12.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/PKCS12.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/keystore/PKCS12.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/PKCS12.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/PKCS12.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/PKCS12.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/PKCS12.java 2013-05-25 02:14:15.000000000 +0000
@@ -17,14 +17,16 @@
public void configure(ConfigurableProvider provider)
{
@@ -3669,9 +3886,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/PKC
}
}
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java 2014-07-28 19:51:54.000000000 +0000
@@ -61,8 +61,10 @@
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.DERSequence;
@@ -3685,8 +3902,8 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/pkc
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.AuthenticatedSafe;
-@@ -86,7 +88,9 @@
- import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
+@@ -88,7 +90,9 @@
+ import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.jcajce.provider.config.PKCS12StoreParameter;
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
-import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
@@ -3696,7 +3913,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/pkc
import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
import org.bouncycastle.jce.interfaces.BCKeyStore;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
-@@ -736,13 +740,15 @@
+@@ -750,13 +754,15 @@
{
cipher.init(mode, key, new IvParameterSpec(ASN1OctetString.getInstance(encParams).getOctets()));
}
@@ -3719,7 +3936,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/pkc
return cipher;
}
-@@ -1659,32 +1665,34 @@
+@@ -1678,32 +1684,34 @@
}
}
@@ -3780,7 +3997,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/pkc
private static class IgnoresCaseHashtable
{
-@@ -1757,7 +1765,9 @@
+@@ -1776,7 +1784,9 @@
keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192));
keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256));
@@ -3791,9 +4008,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/keystore/pkc
KEY_SIZES = Collections.unmodifiableMap(keySizes);
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AES.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/AES.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AES.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/AES.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/AES.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/AES.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/AES.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/AES.java 2014-07-28 19:51:54.000000000 +0000
@@ -3,13 +3,17 @@
import java.io.IOException;
import java.lang.reflect.Constructor;
@@ -3815,16 +4032,18 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
import org.bouncycastle.asn1.cms.GCMParameters;
-@@ -19,25 +23,33 @@
+@@ -19,26 +23,34 @@
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.engines.AESWrapEngine;
-import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
+-import org.bouncycastle.crypto.engines.RFC5649WrapEngine;
-import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
-import org.bouncycastle.crypto.macs.CMac;
-import org.bouncycastle.crypto.macs.GMac;
+// BEGIN android-removed
+// import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
++// import org.bouncycastle.crypto.engines.RFC5649WrapEngine;
+// import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
+// import org.bouncycastle.crypto.macs.CMac;
+// import org.bouncycastle.crypto.macs.GMac;
@@ -3856,7 +4075,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
import org.bouncycastle.util.Integers;
public final class AES
-@@ -99,41 +111,43 @@
+@@ -100,41 +112,43 @@
}
}
@@ -3935,11 +4154,10 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
static public class Wrap
extends BaseWrapCipher
-@@ -143,15 +157,17 @@
- super(new AESWrapEngine());
+@@ -145,23 +159,25 @@
}
}
--
+
- public static class RFC3211Wrap
- extends BaseWrapCipher
- {
@@ -3948,7 +4166,15 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
- super(new RFC3211WrapEngine(new AESFastEngine()), 16);
- }
- }
-+
+-
+- public static class RFC5649Wrap
+- extends BaseWrapCipher
+- {
+- public RFC5649Wrap()
+- {
+- super(new RFC5649WrapEngine(new AESFastEngine()));
+- }
+- }
+ // BEGIN android-removed
+ // public static class RFC3211Wrap
+ // extends BaseWrapCipher
@@ -3958,11 +4184,20 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
+ // super(new RFC3211WrapEngine(new AESFastEngine()), 16);
+ // }
+ // }
++ //
++ // public static class RFC5649Wrap
++ // extends BaseWrapCipher
++ // {
++ // public RFC5649Wrap()
++ // {
++ // super(new RFC5649WrapEngine(new AESFastEngine()));
++ // }
++ // }
+ // END android-removed
-
/**
-@@ -180,32 +196,34 @@
+ * PBEWithAES-CBC
+@@ -189,32 +205,34 @@
}
}
@@ -4023,7 +4258,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
/**
* PBEWithSHA1And128BitAES-BC
-@@ -315,43 +333,45 @@
+@@ -324,43 +342,45 @@
}
}
@@ -4106,7 +4341,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
public static class AlgParams
extends IvAlgorithmParameters
-@@ -484,35 +504,41 @@
+@@ -493,37 +513,43 @@
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
@@ -4161,14 +4396,17 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_wrap, "AESWRAP");
provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes192_wrap, "AESWRAP");
provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_wrap, "AESWRAP");
+
- provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap");
+- provider.addAlgorithm("Cipher.AESRFC5649WRAP", PREFIX + "$RFC5649Wrap");
+ // BEGIN android-removed
+ // provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap");
++ // provider.addAlgorithm("Cipher.AESRFC5649WRAP", PREFIX + "$RFC5649Wrap");
+ // END android-removed
provider.addAlgorithm("Cipher.GCM", PREFIX + "$GCM");
provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
-@@ -520,27 +546,29 @@
+@@ -531,27 +557,29 @@
provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
provider.addAlgorithm("KeyGenerator.AES", PREFIX + "$KeyGen");
@@ -4219,7 +4457,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.getId(), "PBEWITHSHAAND128BITAES-CBC-BC");
provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.getId(), "PBEWITHSHAAND192BITAES-CBC-BC");
-@@ -619,8 +647,10 @@
+@@ -630,8 +658,10 @@
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.getId(), "PKCS12PBE");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.getId(), "PKCS12PBE");
@@ -4232,9 +4470,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AE
}
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ARC4.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/ARC4.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ARC4.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/ARC4.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/ARC4.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/ARC4.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/ARC4.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/ARC4.java 2013-05-25 02:14:15.000000000 +0000
@@ -29,7 +29,9 @@
{
public KeyGen()
@@ -4246,9 +4484,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/AR
}
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java 2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java 2012-09-17 23:04:47.000000000 +0000
@@ -64,7 +64,9 @@
{
@@ -4260,9 +4498,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/Bl
provider.addAlgorithm("KeyGenerator.BLOWFISH", PREFIX + "$KeyGen");
provider.addAlgorithm("Alg.Alias.KeyGenerator.1.3.6.1.4.1.3029.1.2", "BLOWFISH");
provider.addAlgorithm("AlgorithmParameters.BLOWFISH", PREFIX + "$AlgParams");
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/DES.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/DES.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/DES.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/DES.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/DES.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/DES.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/DES.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/DES.java 2013-05-25 02:14:15.000000000 +0000
@@ -19,12 +19,16 @@
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.KeyGenerationParameters;
@@ -4579,9 +4817,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/DE
provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, "PBEWITHMD5ANDDES");
provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, "PBEWITHSHA1ANDDES");
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/DESede.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/DESede.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/DESede.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/DESede.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/DESede.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/DESede.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/DESede.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/DESede.java 2013-05-25 02:14:15.000000000 +0000
@@ -1,30 +1,42 @@
package org.bouncycastle.jcajce.provider.symmetric;
@@ -4902,9 +5140,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/DE
provider.addAlgorithm("SecretKeyFactory.PBEWITHSHAAND3-KEYTRIPLEDES-CBC", PREFIX + "$PBEWithSHAAndDES3KeyFactory");
provider.addAlgorithm("SecretKeyFactory.PBEWITHSHAAND2-KEYTRIPLEDES-CBC", PREFIX + "$PBEWithSHAAndDES2KeyFactory");
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/RC2.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/RC2.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/RC2.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/RC2.java 2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/RC2.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/RC2.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/RC2.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/RC2.java 2013-05-25 02:14:15.000000000 +0000
@@ -12,24 +12,34 @@
import org.bouncycastle.asn1.ASN1Primitive;
@@ -5667,9 +5905,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/RC
provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC, "PBEWITHMD5ANDRC2");
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java 2013-12-12 00:35:05.000000000 +0000
@@ -6,29 +6,31 @@
abstract class SymmetricAlgorithmProvider
extends AlgorithmProvider
@@ -5726,9 +5964,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/Sy
+ // END android-removed
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/Twofish.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/Twofish.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/Twofish.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/Twofish.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/Twofish.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/Twofish.java 2013-12-12 00:35:05.000000000 +0000
@@ -1,18 +1,26 @@
package org.bouncycastle.jcajce.provider.symmetric;
@@ -5926,10 +6164,10 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/Tw
}
}
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java 2013-12-13 23:56:53.000000000 +0000
-@@ -19,8 +19,10 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java 2014-07-28 19:51:54.000000000 +0000
+@@ -20,8 +20,10 @@
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEParameterSpec;
@@ -5942,7 +6180,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
import org.bouncycastle.asn1.cms.GCMParameters;
import org.bouncycastle.crypto.BlockCipher;
-@@ -34,14 +36,20 @@
+@@ -35,14 +37,20 @@
import org.bouncycastle.crypto.modes.CCMBlockCipher;
import org.bouncycastle.crypto.modes.CFBBlockCipher;
import org.bouncycastle.crypto.modes.CTSBlockCipher;
@@ -5969,7 +6207,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
import org.bouncycastle.crypto.modes.SICBlockCipher;
import org.bouncycastle.crypto.paddings.BlockCipherPadding;
import org.bouncycastle.crypto.paddings.ISO10126d2Padding;
-@@ -54,11 +62,15 @@
+@@ -55,11 +63,15 @@
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.params.ParametersWithRandom;
@@ -5989,7 +6227,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Strings;
-@@ -73,11 +85,15 @@
+@@ -74,11 +86,15 @@
//
private Class[] availableSpecs =
{
@@ -6008,19 +6246,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
gcmSpecClass
};
-@@ -162,6 +178,11 @@
-
- protected byte[] engineGetIV()
- {
-+ // BEGIN android-added
-+ if (aeadParams != null) {
-+ return aeadParams.getNonce();
-+ }
-+ // END android-added
- return (ivParam != null) ? ivParam.getIV() : null;
- }
-
-@@ -278,48 +299,52 @@
+@@ -284,48 +300,52 @@
new CFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize()));
}
}
@@ -6109,7 +6335,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
else if (modeName.startsWith("CTS"))
{
ivLength = baseEngine.getBlockSize();
-@@ -330,24 +355,26 @@
+@@ -336,26 +356,28 @@
ivLength = 13; // CCM nonce 7..13 bytes
cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine));
}
@@ -6117,7 +6343,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
- {
- if (engineProvider != null)
- {
-- // Nonce restricted to max 120 bits over 128 bit block cipher since draft-irtf-cfrg-ocb-03
+- /*
+- * RFC 7253 4.2. Nonce is a string of no more than 120 bits
+- */
- ivLength = 15;
- cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get()));
- }
@@ -6136,7 +6364,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
+ // {
+ // if (engineProvider != null)
+ // {
-+ // // Nonce restricted to max 120 bits over 128 bit block cipher since draft-irtf-cfrg-ocb-03
++ // /*
++ // * RFC 7253 4.2. Nonce is a string of no more than 120 bits
++ // */
+ // ivLength = 15;
+ // cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get()));
+ // }
@@ -6154,7 +6384,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
else if (modeName.startsWith("GCM"))
{
ivLength = baseEngine.getBlockSize();
-@@ -470,18 +497,20 @@
+@@ -478,18 +500,20 @@
param = new ParametersWithIV(param, iv.getIV());
}
@@ -6187,7 +6417,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
}
else if (params instanceof PBEParameterSpec)
{
-@@ -513,12 +542,14 @@
+@@ -521,12 +545,14 @@
throw new InvalidAlgorithmParameterException("IV must be " + ivLength + " bytes long.");
}
@@ -6208,7 +6438,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
{
param = new ParametersWithIV(new KeyParameter(key.getEncoded()), p.getIV());
ivParam = (ParametersWithIV)param;
-@@ -534,63 +565,65 @@
+@@ -542,63 +568,65 @@
param = new KeyParameter(key.getEncoded());
}
}
@@ -6331,7 +6561,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
else if (gcmSpecClass != null && gcmSpecClass.isInstance(params))
{
if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher))
-@@ -603,11 +636,13 @@
+@@ -611,11 +639,13 @@
Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]);
Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]);
@@ -6350,7 +6580,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
{
param = aeadParams = new AEADParameters(new KeyParameter(key.getEncoded()), ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0]));
}
-@@ -867,7 +902,9 @@
+@@ -867,7 +897,9 @@
private boolean isAEADModeName(
String modeName)
{
@@ -6361,9 +6591,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
}
/*
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java 2013-12-12 00:35:05.000000000 +0000
@@ -16,8 +16,10 @@
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.params.KeyParameter;
@@ -6394,9 +6624,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
else if (params == null)
{
param = new KeyParameter(key.getEncoded());
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java 2014-07-28 19:51:54.000000000 +0000
@@ -14,8 +14,10 @@
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
@@ -6408,9 +6638,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
+// import javax.crypto.spec.RC5ParameterSpec;
+// END android-removed
- import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
-@@ -35,8 +37,10 @@
+ import org.bouncycastle.crypto.DataLengthException;
+@@ -33,8 +35,10 @@
//
private Class[] availableSpecs =
{
@@ -6423,9 +6653,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
IvParameterSpec.class,
PBEParameterSpec.class
};
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java 2013-01-31 02:26:40.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java 2014-07-28 19:51:54.000000000 +0000
@@ -22,8 +22,10 @@
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
@@ -6439,7 +6669,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-@@ -45,8 +47,10 @@
+@@ -46,8 +48,10 @@
{
IvParameterSpec.class,
PBEParameterSpec.class,
@@ -6452,7 +6682,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
};
protected int pbeType = PKCS12;
-@@ -258,6 +262,8 @@
+@@ -264,6 +268,8 @@
return null;
}
@@ -6461,7 +6691,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
protected int engineDoFinal(
byte[] input,
int inputOffset,
-@@ -268,6 +274,7 @@
+@@ -274,6 +280,7 @@
{
return 0;
}
@@ -6469,9 +6699,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
protected byte[] engineWrap(
Key key)
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java 2013-12-12 00:35:05.000000000 +0000
@@ -7,13 +7,18 @@
import org.bouncycastle.crypto.CipherParameters;
@@ -6658,9 +6888,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/symmetric/ut
default:
throw new IllegalStateException("unknown digest scheme for PBE encryption.");
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/util/DigestFactory.java bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/util/DigestFactory.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/util/DigestFactory.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jcajce/provider/util/DigestFactory.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/util/DigestFactory.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/util/DigestFactory.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/util/DigestFactory.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/util/DigestFactory.java 2013-09-26 18:06:21.000000000 +0000
@@ -10,12 +10,17 @@
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
@@ -6731,13 +6961,75 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jcajce/provider/util/DigestF
}
return null;
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java bcprov-jdk15on-150/org/bouncycastle/jce/PKCS10CertificationRequest.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/PKCS10CertificationRequest.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/util/JcaJceUtils.java bcprov-jdk15on-151/org/bouncycastle/jcajce/util/JcaJceUtils.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/util/JcaJceUtils.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jcajce/util/JcaJceUtils.java 2014-07-28 19:51:54.000000000 +0000
+@@ -6,11 +6,15 @@
+ import org.bouncycastle.asn1.ASN1Encodable;
+ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+ import org.bouncycastle.asn1.ASN1Primitive;
+-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
++// BEGIN android-removed
++// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
++// END android-removed
+ import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+ import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+-import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
++// BEGIN android-removed
++// import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
++// END android-removed
+
+ /**
+ * General JCA/JCE utility methods.
+@@ -100,22 +104,24 @@
+ {
+ return "SHA512";
+ }
+- else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID))
+- {
+- return "RIPEMD128";
+- }
+- else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID))
+- {
+- return "RIPEMD160";
+- }
+- else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID))
+- {
+- return "RIPEMD256";
+- }
+- else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID))
+- {
+- return "GOST3411";
+- }
++ // BEGIN android-removed
++ // else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID))
++ // {
++ // return "RIPEMD128";
++ // }
++ // else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID))
++ // {
++ // return "RIPEMD160";
++ // }
++ // else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID))
++ // {
++ // return "RIPEMD256";
++ // }
++ // else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID))
++ // {
++ // return "GOST3411";
++ // }
++ // END android-removed
+ else
+ {
+ return digestAlgOID.getId();
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java bcprov-jdk15on-151/org/bouncycastle/jce/PKCS10CertificationRequest.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/PKCS10CertificationRequest.java 2014-07-28 19:51:54.000000000 +0000
@@ -30,14 +30,18 @@
+ import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERNull;
- import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
@@ -6759,20 +7051,20 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/PKCS10CertificationReque
static
{
-- algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-- algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
+- algorithms.put("MD2WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"));
+- algorithms.put("MD2WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"));
+ // BEGIN android-removed
+ // Dropping MD2
-+ // algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-+ // algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
++ // algorithms.put("MD2WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"));
++ // algorithms.put("MD2WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"));
+ // END android-removed
- algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
- algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
- algorithms.put("RSAWITHMD5", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
+ algorithms.put("MD5WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"));
+ algorithms.put("MD5WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"));
+ algorithms.put("RSAWITHMD5", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"));
@@ -102,12 +109,14 @@
algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
- algorithms.put("RSAWITHSHA1", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
+ algorithms.put("RSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"));
- algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
- algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
- algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
@@ -6787,8 +7079,8 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/PKCS10CertificationReque
+ // algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
+ // algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
+ // END android-removed
- algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3"));
- algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3"));
+ algorithms.put("SHA1WITHDSA", new ASN1ObjectIdentifier("1.2.840.10040.4.3"));
+ algorithms.put("DSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.10040.4.3"));
algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224);
@@ -120,11 +129,13 @@
algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384);
@@ -6809,7 +7101,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/PKCS10CertificationReque
//
// reverse mappings
-@@ -134,11 +145,16 @@
+@@ -134,11 +145,15 @@
oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA");
oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA");
oids.put(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512WITHRSA");
@@ -6820,16 +7112,15 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/PKCS10CertificationReque
+ // oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, "GOST3411WITHECGOST3410");
+ // END android-removed
- oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
-- oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA");
+ oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
+- oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA");
+ // BEGIN android-removed
-+ // Dropping MD2
-+ // oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA");
++ // oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA");
+ // END android-removed
- oids.put(new DERObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA");
+ oids.put(new ASN1ObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA");
oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1WITHECDSA");
oids.put(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224WITHECDSA");
-@@ -172,8 +188,10 @@
+@@ -172,8 +187,10 @@
//
// RFC 4491
//
@@ -6842,7 +7133,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/PKCS10CertificationReque
//
// explicit params
//
-@@ -616,22 +634,24 @@
+@@ -616,22 +633,24 @@
{
return "SHA512";
}
@@ -6883,9 +7174,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/PKCS10CertificationReque
else
{
return digestAlgOID.getId();
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/BouncyCastleProvider.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/BouncyCastleProvider.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/BouncyCastleProvider.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/BouncyCastleProvider.java 2014-07-28 19:51:54.000000000 +0000
@@ -64,15 +64,22 @@
private static final String[] SYMMETRIC_MACS =
@@ -7045,9 +7336,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/BouncyCastlePro
}
private void loadAlgorithms(String packageName, String[] names)
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/CertBlacklist.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/CertBlacklist.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/CertBlacklist.java 1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/CertBlacklist.java 2013-12-10 21:31:49.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/CertBlacklist.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/CertBlacklist.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/CertBlacklist.java 1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/CertBlacklist.java 2013-12-10 21:31:49.000000000 +0000
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
@@ -7277,9 +7568,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/CertBlacklist.j
+ }
+
+}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java 2014-07-28 19:51:54.000000000 +0000
@@ -61,18 +61,24 @@
import org.bouncycastle.asn1.x509.PolicyInformation;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
@@ -7481,13 +7772,13 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/CertPathValidat
protected static void addAdditionalStoresFromCRLDistributionPoint(
CRLDistPoint crldp, ExtendedPKIXParameters pkixParams)
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/JCEECPrivateKey.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/JCEECPrivateKey.java 2013-12-12 00:35:05.000000000 +0000
-@@ -20,8 +20,10 @@
- import org.bouncycastle.asn1.DERInteger;
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEECPrivateKey.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEECPrivateKey.java 2014-07-28 19:51:54.000000000 +0000
+@@ -19,8 +19,10 @@
+ import org.bouncycastle.asn1.ASN1Sequence;
+ import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERNull;
- import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
-import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
+// BEGIN android-removed
@@ -7497,7 +7788,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPrivateKey
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.sec.ECPrivateKeyStructure;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-@@ -203,21 +205,23 @@
+@@ -202,21 +204,23 @@
ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
@@ -7536,7 +7827,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPrivateKey
{
EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
-@@ -331,11 +335,13 @@
+@@ -330,11 +334,13 @@
try
{
@@ -7555,9 +7846,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPrivateKey
{
info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.toASN1Primitive()), keyStructure.toASN1Primitive());
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/JCEECPublicKey.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/JCEECPublicKey.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEECPublicKey.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEECPublicKey.java 2014-07-28 19:51:54.000000000 +0000
@@ -18,9 +18,11 @@
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERNull;
@@ -7588,8 +7879,8 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPublicKey.
+// END android-removed
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.math.ec.ECCurve;
-
-@@ -46,7 +52,9 @@
+ import org.bouncycastle.math.ec.custom.sec.SecP256K1Point;
+@@ -48,7 +54,9 @@
private org.bouncycastle.math.ec.ECPoint q;
private ECParameterSpec ecSpec;
private boolean withCompression;
@@ -7600,7 +7891,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPublicKey.
public JCEECPublicKey(
String algorithm,
-@@ -56,7 +64,9 @@
+@@ -58,7 +66,9 @@
this.q = key.q;
this.ecSpec = key.ecSpec;
this.withCompression = key.withCompression;
@@ -7611,7 +7902,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPublicKey.
}
public JCEECPublicKey(
-@@ -179,54 +189,55 @@
+@@ -181,54 +191,55 @@
private void populateFromPubKeyInfo(SubjectPublicKeyInfo info)
{
@@ -7715,7 +8006,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPublicKey.
{
X962Parameters params = new X962Parameters((ASN1Primitive)info.getAlgorithmId().getParameters());
ECCurve curve;
-@@ -315,52 +326,54 @@
+@@ -317,52 +328,54 @@
ASN1Encodable params;
SubjectPublicKeyInfo info;
@@ -7816,10 +8107,10 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEECPublicKey.
{
if (ecSpec instanceof ECNamedCurveSpec)
{
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEStreamCipher.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/JCEStreamCipher.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEStreamCipher.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/JCEStreamCipher.java 2013-05-25 02:14:15.000000000 +0000
-@@ -23,8 +23,10 @@
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEStreamCipher.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEStreamCipher.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEStreamCipher.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEStreamCipher.java 2014-07-28 19:51:54.000000000 +0000
+@@ -23,19 +23,23 @@
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEParameterSpec;
@@ -7832,29 +8123,25 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEStreamCipher
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-@@ -33,12 +35,16 @@
+ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
- import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.engines.BlowfishEngine;
-import org.bouncycastle.crypto.engines.DESEngine;
-import org.bouncycastle.crypto.engines.DESedeEngine;
+-import org.bouncycastle.crypto.engines.SkipjackEngine;
+-import org.bouncycastle.crypto.engines.TwofishEngine;
+// BEGIN android-removed
+// import org.bouncycastle.crypto.engines.BlowfishEngine;
+// import org.bouncycastle.crypto.engines.DESEngine;
+// import org.bouncycastle.crypto.engines.DESedeEngine;
-+// END android-removed
- import org.bouncycastle.crypto.engines.RC4Engine;
--import org.bouncycastle.crypto.engines.SkipjackEngine;
--import org.bouncycastle.crypto.engines.TwofishEngine;
-+// BEGIN android-removed
+// import org.bouncycastle.crypto.engines.SkipjackEngine;
+// import org.bouncycastle.crypto.engines.TwofishEngine;
+// END android-removed
import org.bouncycastle.crypto.modes.CFBBlockCipher;
import org.bouncycastle.crypto.modes.OFBBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
-@@ -55,8 +61,10 @@
+@@ -52,8 +56,10 @@
//
private Class[] availableSpecs =
{
@@ -7867,7 +8154,7 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEStreamCipher
IvParameterSpec.class,
PBEParameterSpec.class
};
-@@ -491,123 +499,125 @@
+@@ -479,123 +485,125 @@
* The ciphers that inherit from us.
*/
@@ -8112,9 +8399,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/JCEStreamCipher
+ // }
+ // END android-removed
}
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/PKIXCRLUtil.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/PKIXCRLUtil.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/PKIXCRLUtil.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/PKIXCRLUtil.java 2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/PKIXCRLUtil.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/PKIXCRLUtil.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/PKIXCRLUtil.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/PKIXCRLUtil.java 2013-12-12 00:35:05.000000000 +0000
@@ -15,7 +15,9 @@
import org.bouncycastle.util.StoreException;
import org.bouncycastle.x509.ExtendedPKIXParameters;
@@ -8167,9 +8454,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/PKIXCRLUtil.jav
{
CertStore store = (CertStore)obj;
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java 2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java 2014-07-28 19:51:54.000000000 +0000
@@ -1,5 +1,8 @@
package org.bouncycastle.jce.provider;
@@ -8228,9 +8515,9 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/PKIXCertPathVal
// try
// {
//
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/X509CertificateObject.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/X509CertificateObject.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/X509CertificateObject.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/X509CertificateObject.java 2013-01-31 02:26:40.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/X509CertificateObject.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/X509CertificateObject.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/X509CertificateObject.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/X509CertificateObject.java 2013-01-31 02:26:40.000000000 +0000
@@ -57,6 +57,9 @@
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.GeneralName;
@@ -8274,13 +8561,13 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/X509Certificate
break;
case GeneralName.dNSName:
case GeneralName.rfc822Name:
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java bcprov-jdk15on-150/org/bouncycastle/jce/provider/X509SignatureUtil.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/jce/provider/X509SignatureUtil.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/X509SignatureUtil.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/X509SignatureUtil.java 2014-07-28 19:51:54.000000000 +0000
@@ -14,7 +14,9 @@
+ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERNull;
- import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
@@ -8292,21 +8579,21 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/X509SignatureUt
if (params != null && !derNull.equals(params))
{
-- if (sigAlgId.getObjectId().equals(PKCSObjectIdentifiers.id_RSASSA_PSS))
+- if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS))
- {
- RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params);
-
-- return getDigestAlgName(rsaParams.getHashAlgorithm().getObjectId()) + "withRSAandMGF1";
+- return getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "withRSAandMGF1";
- }
+ // BEGIN android-removed
-+ // if (sigAlgId.getObjectId().equals(PKCSObjectIdentifiers.id_RSASSA_PSS))
++ // if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS))
+ // {
+ // RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params);
-+ //
-+ // return getDigestAlgName(rsaParams.getHashAlgorithm().getObjectId()) + "withRSAandMGF1";
++ //
++ // return getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "withRSAandMGF1";
+ // }
+ // END android-removed
- if (sigAlgId.getObjectId().equals(X9ObjectIdentifiers.ecdsa_with_SHA2))
+ if (sigAlgId.getAlgorithm().equals(X9ObjectIdentifiers.ecdsa_with_SHA2))
{
ASN1Sequence ecDsaParams = ASN1Sequence.getInstance(params);
@@ -114,22 +118,24 @@
@@ -8350,13 +8637,13 @@ diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/jce/provider/X509SignatureUt
else
{
return digestAlgOID.getId();
-diff -Naur bcprov-jdk15on-150.orig/org/bouncycastle/x509/X509Util.java bcprov-jdk15on-150/org/bouncycastle/x509/X509Util.java
---- bcprov-jdk15on-150.orig/org/bouncycastle/x509/X509Util.java 2013-12-03 20:18:20.000000000 +0000
-+++ bcprov-jdk15on-150/org/bouncycastle/x509/X509Util.java 2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/x509/X509Util.java bcprov-jdk15on-151/org/bouncycastle/x509/X509Util.java
+--- bcprov-jdk15on-151.orig/org/bouncycastle/x509/X509Util.java 2014-07-26 04:17:24.000000000 +0000
++++ bcprov-jdk15on-151/org/bouncycastle/x509/X509Util.java 2014-07-28 19:51:54.000000000 +0000
@@ -25,12 +25,16 @@
import org.bouncycastle.asn1.ASN1Integer;
+ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERNull;
- import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;