summaryrefslogtreecommitdiff
path: root/bcprov/src/main/java
diff options
context:
space:
mode:
authorAdam Vartanian <flooey@google.com>2019-02-14 14:42:19 +0000
committerAdam Vartanian <flooey@google.com>2019-02-18 10:18:52 +0000
commit27254450f01adef5f4bb25a648d42eeacc14c438 (patch)
tree90eb8fa6c24a44780cc4c4be2d50555f955d29f4 /bcprov/src/main/java
parentbdfb209e7c1139588c82722a809c46667775a314 (diff)
parent1b335c5efbcf241b55345622fe9978047c3fdf9e (diff)
downloadbouncycastle-27254450f01adef5f4bb25a648d42eeacc14c438.tar.gz
Update Bouncy Castle to 1.61
Test: cts -m CtsLibcoreTestCases Test: cts -m CtsLibcoreWycheproofBCTestCases Change-Id: Ifcd182a8537439b945aedf80741bd51cbce37e49
Diffstat (limited to 'bcprov/src/main/java')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1BitString.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1External.java292
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java95
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java70
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1String.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java21
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/BEROctetString.java77
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/BEROutputStream.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/BERSequence.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/BERSet.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERExternal.java239
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERExternalParser.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralString.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java96
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERNull.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERSequence.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DLApplicationSpecific.java124
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DLExternal.java85
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DateUtil.java80
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/LimitedInputStream.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java71
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/gm/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java121
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/nsri/NSRIObjectIdentifiers.java78
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/nsri/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedData.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java336
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/Pfx.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java233
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java19
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/RDN.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/X500Name.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/DigestInfo.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/Extensions.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/OtherName.java92
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/PKIXNameConstraintValidator.java200
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java35
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificateStructure.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/DomainParameters.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java63
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java51
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java128
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/CryptoServicesPermission.java81
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/CryptoServicesRegistrar.java417
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/DSAExt.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/RawAgreement.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/NullDigest.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersGenerator.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java157
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java37
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java393
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables4kGCMMultiplier.java67
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java91
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/DHValidationParameters.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/ParametersWithRandom.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAEncoding.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/PlainDSAEncoding.java62
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/StandardDSAEncoding.java64
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNoCloseNotifyException.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java189
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java423
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/io/DigestUpdatingOutputStream.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/io/MacUpdatingOutputStream.java35
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/io/OutputStreamFactory.java46
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/io/SignatureUpdatingOutputStream.java56
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java71
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParameterGeneratorSpi.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPrivateKey.java57
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/DHUtil.java45
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java514
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyPairGeneratorSpi.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPrivateKey.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java56
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java21
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java86
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java45
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java402
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java228
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java199
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateCrtKey.java19
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java84
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/RSAUtil.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java58
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java21
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSABase.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSAEncoder.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java89
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java192
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfiguration.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java134
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java117
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java119
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseKeyGenerator.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java37
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java250
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/ClassUtil.java45
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/DHDomainParameterSpec.java129
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/netscape/NetscapeCertRequest.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java63
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration.java22
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPrivateKey.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java64
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java68
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java49
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java35
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java173
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java76
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECLookupTable.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java172
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java33
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java21
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java92
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/PreCompCallback.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ValidityPrecompInfo.java40
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java293
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1Curve.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1Curve.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192R1FieldElement.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1Curve.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1Curve.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224R1FieldElement.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1Curve.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Curve.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1FieldElement.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Curve.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1FieldElement.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1Curve.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP521R1FieldElement.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Interleave.java177
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java63
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Arrays.java129
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java88
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Fingerprint.java180
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/IPAddress.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Pack.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Properties.java126
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Strings.java119
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java60
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/encoders/UTF8.java156
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/pem/PemReader.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXParameters.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/extension/X509ExtensionUtil.java18
267 files changed, 9358 insertions, 2887 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java
index c67e42f3..770af15c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java
@@ -3,9 +3,10 @@ package org.bouncycastle.asn1;
import java.io.IOException;
import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.encoders.Hex;
/**
- * Base class for an application specific object
+ * Base class for an ASN.1 ApplicationSpecific object
*/
public abstract class ASN1ApplicationSpecific
extends ASN1Primitive
@@ -194,25 +195,19 @@ public abstract class ASN1ApplicationSpecific
//
if (tagNo == 0x1f)
{
- tagNo = 0;
-
int b = input[index++] & 0xff;
// X.690-0207 8.1.2.4.2
// "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
if ((b & 0x7f) == 0) // Note: -1 will pass
{
- throw new ASN1ParsingException("corrupted stream - invalid high tag number found");
+ throw new IOException("corrupted stream - invalid high tag number found");
}
- while ((b >= 0) && ((b & 0x80) != 0))
+ while ((b & 0x80) != 0)
{
- tagNo |= (b & 0x7f);
- tagNo <<= 7;
b = input[index++] & 0xff;
}
-
-// tagNo |= (b & 0x7f);
}
byte[] tmp = new byte[input.length - index + 1];
@@ -223,4 +218,29 @@ public abstract class ASN1ApplicationSpecific
return tmp;
}
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[");
+ if (isConstructed())
+ {
+ sb.append("CONSTRUCTED ");
+ }
+ sb.append("APPLICATION ");
+ sb.append(Integer.toString(getApplicationTag()));
+ sb.append("]");
+ // @todo content encoding somehow?
+ if (this.octets != null)
+ {
+ sb.append(" #");
+ sb.append(Hex.toHexString(this.octets));
+ }
+ else
+ {
+ sb.append(" #null");
+ }
+ sb.append(" ");
+ return sb.toString();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
index 8816b2b5..422bccf7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
@@ -3,7 +3,7 @@ package org.bouncycastle.asn1;
import java.io.IOException;
/**
- * Interface to parse ASN.1 application specific objects.
+ * Interface to parse ASN.1 ApplicationSpecific objects.
*/
public interface ASN1ApplicationSpecificParser
extends ASN1Encodable, InMemoryRepresentable
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1BitString.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1BitString.java
index 513d4e5b..e1aba657 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1BitString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1BitString.java
@@ -58,6 +58,7 @@ public abstract class ASN1BitString
return 0;
}
+
int bits = 1;
while (((val <<= 1) & 0xFF) != 0)
@@ -135,7 +136,7 @@ public abstract class ASN1BitString
{
StringBuffer buf = new StringBuffer("#");
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
try
{
@@ -216,7 +217,7 @@ public abstract class ASN1BitString
}
protected boolean asn1Equals(
- ASN1Primitive o)
+ ASN1Primitive o)
{
if (!(o instanceof ASN1BitString))
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java
index 0225e6e9..e968660f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Boolean.java
@@ -14,7 +14,6 @@ import org.bouncycastle.util.Arrays;
* <li> {@link ASN1Boolean#getInstance(boolean) ASN1Boolean.getInstance(boolean)}</li>
* <li> {@link ASN1Boolean#getInstance(int) ASN1Boolean.getInstance(int)}</li>
* </ul>
- * </p>
*/
public class ASN1Boolean
extends ASN1Primitive
@@ -28,7 +27,7 @@ public class ASN1Boolean
public static final ASN1Boolean TRUE = new ASN1Boolean(true);
/**
- * return a boolean from the passed in object.
+ * 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.
@@ -59,7 +58,7 @@ public class ASN1Boolean
}
/**
- * return an ASN1Boolean from the passed in boolean.
+ * Return an ASN1Boolean from the passed in boolean.
* @param value true or false depending on the ASN1Boolean wanted.
* @return an ASN1Boolean instance.
*/
@@ -70,7 +69,7 @@ public class ASN1Boolean
}
/**
- * return an ASN1Boolean from the passed in value.
+ * Return an ASN1Boolean from the passed in value.
* @param value non-zero (true) or zero (false) depending on the ASN1Boolean wanted.
* @return an ASN1Boolean instance.
*/
@@ -92,7 +91,7 @@ public class ASN1Boolean
// END Android-added: Unknown reason
/**
- * return a Boolean from a tagged object.
+ * 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
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java
index 3ca88905..4d92dd82 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Choice.java
@@ -8,7 +8,6 @@ package org.bouncycastle.asn1;
* 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>
@@ -16,11 +15,11 @@ package org.bouncycastle.asn1;
* The encoding of a choice value shall be the same as the encoding of a value of the chosen type.
* <blockquote>
* NOTE 1 &mdash; The encoding may be primitive or constructed depending on the chosen type.
- * <br />
+ * </blockquote>
+ * <blockquote>
* 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/ASN1EncodableVector.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java
index 2828541e..0971748a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1EncodableVector.java
@@ -4,7 +4,7 @@ import java.util.Enumeration;
import java.util.Vector;
/**
- * Mutable class for building ASN.1 constructed objects.
+ * Mutable class for building ASN.1 constructed objects such as SETs or SEQUENCEs.
*/
public class ASN1EncodableVector
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java
index ca192f31..aa89eb5d 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.math.BigInteger;
import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Properties;
/**
* Class representing the ASN.1 ENUMERATED type.
@@ -99,13 +100,9 @@ public class ASN1Enumerated
public ASN1Enumerated(
byte[] bytes)
{
- if (bytes.length > 1)
+ if (!Properties.isOverrideSet("org.bouncycastle.asn1.allow_unsafe_integer"))
{
- if (bytes[0] == 0 && (bytes[1] & 0x80) == 0)
- {
- throw new IllegalArgumentException("malformed enumerated");
- }
- if (bytes[0] == (byte)0xff && (bytes[1] & 0x80) != 0)
+ if (ASN1Integer.isMalformed(bytes))
{
throw new IllegalArgumentException("malformed enumerated");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1External.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1External.java
new file mode 100644
index 00000000..7db80fff
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1External.java
@@ -0,0 +1,292 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * Class representing the DER-type External
+ */
+public abstract class ASN1External
+ extends ASN1Primitive
+{
+ protected ASN1ObjectIdentifier directReference;
+ protected ASN1Integer indirectReference;
+ protected ASN1Primitive dataValueDescriptor;
+ protected int encoding;
+ protected ASN1Primitive externalContent;
+
+ /**
+ * Construct an EXTERNAL object, the input encoding vector must have exactly two elements on it.
+ * <p>
+ * Acceptable input formats are:
+ * <ul>
+ * <li> {@link ASN1ObjectIdentifier} + data {@link DERTaggedObject} (direct reference form)</li>
+ * <li> {@link ASN1Integer} + data {@link DERTaggedObject} (indirect reference form)</li>
+ * <li> Anything but {@link DERTaggedObject} + data {@link DERTaggedObject} (data value form)</li>
+ * </ul>
+ *
+ * @throws IllegalArgumentException if input size is wrong, or
+ */
+ public ASN1External(ASN1EncodableVector vector)
+ {
+ int offset = 0;
+
+ ASN1Primitive enc = getObjFromVector(vector, offset);
+ if (enc instanceof ASN1ObjectIdentifier)
+ {
+ directReference = (ASN1ObjectIdentifier)enc;
+ offset++;
+ enc = getObjFromVector(vector, offset);
+ }
+ if (enc instanceof ASN1Integer)
+ {
+ indirectReference = (ASN1Integer) enc;
+ offset++;
+ enc = getObjFromVector(vector, offset);
+ }
+ if (!(enc instanceof ASN1TaggedObject))
+ {
+ dataValueDescriptor = (ASN1Primitive) enc;
+ offset++;
+ enc = getObjFromVector(vector, offset);
+ }
+
+ if (vector.size() != offset + 1)
+ {
+ throw new IllegalArgumentException("input vector too large");
+ }
+
+ if (!(enc instanceof ASN1TaggedObject))
+ {
+ throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External");
+ }
+ ASN1TaggedObject obj = (ASN1TaggedObject)enc;
+ setEncoding(obj.getTagNo());
+ externalContent = obj.getObject();
+ }
+
+ private ASN1Primitive getObjFromVector(ASN1EncodableVector v, int index)
+ {
+ if (v.size() <= index)
+ {
+ throw new IllegalArgumentException("too few objects in input vector");
+ }
+
+ return v.get(index).toASN1Primitive();
+ }
+
+ /**
+ * Creates a new instance of External
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or <code>null</code> if not set.
+ * @param indirectReference The indirect reference or <code>null</code> if not set.
+ * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+ * @param externalData The external data in its encoded form.
+ */
+ public ASN1External(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData)
+ {
+ this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive());
+ }
+
+ /**
+ * Creates a new instance of External.
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or <code>null</code> if not set.
+ * @param indirectReference The indirect reference or <code>null</code> if not set.
+ * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+ * @param encoding The encoding to be used for the external data
+ * @param externalData The external data
+ */
+ public ASN1External(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData)
+ {
+ setDirectReference(directReference);
+ setIndirectReference(indirectReference);
+ setDataValueDescriptor(dataValueDescriptor);
+ setEncoding(encoding);
+ setExternalContent(externalData.toASN1Primitive());
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ if (this instanceof DERExternal)
+ {
+ return this;
+ }
+
+ return new DERExternal(directReference, indirectReference, dataValueDescriptor, encoding, externalContent);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ int ret = 0;
+ if (directReference != null)
+ {
+ ret = directReference.hashCode();
+ }
+ if (indirectReference != null)
+ {
+ ret ^= indirectReference.hashCode();
+ }
+ if (dataValueDescriptor != null)
+ {
+ ret ^= dataValueDescriptor.hashCode();
+ }
+ ret ^= externalContent.hashCode();
+ return ret;
+ }
+
+ boolean isConstructed()
+ {
+ return true;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return this.getEncoded().length;
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.asn1.ASN1Primitive#asn1Equals(org.bouncycastle.asn1.ASN1Primitive)
+ */
+ boolean asn1Equals(ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1External))
+ {
+ return false;
+ }
+ if (this == o)
+ {
+ return true;
+ }
+ ASN1External other = (ASN1External)o;
+ if (directReference != null)
+ {
+ if (other.directReference == null || !other.directReference.equals(directReference))
+ {
+ return false;
+ }
+ }
+ if (indirectReference != null)
+ {
+ if (other.indirectReference == null || !other.indirectReference.equals(indirectReference))
+ {
+ return false;
+ }
+ }
+ if (dataValueDescriptor != null)
+ {
+ if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor))
+ {
+ return false;
+ }
+ }
+ return externalContent.equals(other.externalContent);
+ }
+
+ /**
+ * Returns the data value descriptor
+ * @return The descriptor
+ */
+ public ASN1Primitive getDataValueDescriptor()
+ {
+ return dataValueDescriptor;
+ }
+
+ /**
+ * Returns the direct reference of the external element
+ * @return The reference
+ */
+ public ASN1ObjectIdentifier getDirectReference()
+ {
+ return directReference;
+ }
+
+ /**
+ * Returns the encoding of the content. Valid values are
+ * <ul>
+ * <li><code>0</code> single-ASN1-type</li>
+ * <li><code>1</code> OCTET STRING</li>
+ * <li><code>2</code> BIT STRING</li>
+ * </ul>
+ * @return The encoding
+ */
+ public int getEncoding()
+ {
+ return encoding;
+ }
+
+ /**
+ * Returns the content of this element
+ * @return The content
+ */
+ public ASN1Primitive getExternalContent()
+ {
+ return externalContent;
+ }
+
+ /**
+ * Returns the indirect reference of this element
+ * @return The reference
+ */
+ public ASN1Integer getIndirectReference()
+ {
+ return indirectReference;
+ }
+
+ /**
+ * Sets the data value descriptor
+ * @param dataValueDescriptor The descriptor
+ */
+ private void setDataValueDescriptor(ASN1Primitive dataValueDescriptor)
+ {
+ this.dataValueDescriptor = dataValueDescriptor;
+ }
+
+ /**
+ * Sets the direct reference of the external element
+ * @param directReferemce The reference
+ */
+ private void setDirectReference(ASN1ObjectIdentifier directReferemce)
+ {
+ this.directReference = directReferemce;
+ }
+
+ /**
+ * Sets the encoding of the content. Valid values are
+ * <ul>
+ * <li><code>0</code> single-ASN1-type</li>
+ * <li><code>1</code> OCTET STRING</li>
+ * <li><code>2</code> BIT STRING</li>
+ * </ul>
+ * @param encoding The encoding
+ */
+ private void setEncoding(int encoding)
+ {
+ if (encoding < 0 || encoding > 2)
+ {
+ throw new IllegalArgumentException("invalid encoding value: " + encoding);
+ }
+ this.encoding = encoding;
+ }
+
+ /**
+ * Sets the content of this element
+ * @param externalContent The content
+ */
+ private void setExternalContent(ASN1Primitive externalContent)
+ {
+ this.externalContent = externalContent;
+ }
+
+ /**
+ * Sets the indirect reference of this element
+ * @param indirectReference The reference
+ */
+ private void setIndirectReference(ASN1Integer indirectReference)
+ {
+ this.indirectReference = indirectReference;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
index 6040676a..ba8de8da 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
@@ -18,11 +18,35 @@ import org.bouncycastle.util.Strings;
* <p>
* The main difference between these and UTC time is a 4 digit year.
* </p>
+ * <p>
+ * One second resolution date+time on UTC timezone (Z)
+ * with 4 digit year (valid from 0001 to 9999).
+ * </p><p>
+ * Timestamp format is: yyyymmddHHMMSS'Z'
+ * </p><p>
+ * <h2>X.690</h2>
+ * This is what is called "restricted string",
+ * and it uses ASCII characters to encode digits and supplemental data.
+ *
+ * <h3>11: Restrictions on BER employed by both CER and DER</h3>
+ * <h4>11.7 GeneralizedTime </h4>
+ * <p>
+ * <b>11.7.1</b> The encoding shall terminate with a "Z",
+ * as described in the ITU-T Rec. X.680 | ISO/IEC 8824-1 clause on
+ * GeneralizedTime.
+ * </p><p>
+ * <b>11.7.2</b> The seconds element shall always be present.
+ * </p>
+ * <p>
+ * <b>11.7.3</b> The fractional-seconds elements, if present,
+ * shall omit all trailing zeros; if the elements correspond to 0,
+ * they shall be wholly omitted, and the decimal point element also
+ * shall be omitted.
*/
public class ASN1GeneralizedTime
extends ASN1Primitive
{
- private byte[] time;
+ protected byte[] time;
/**
* return a generalized time from the passed in object
@@ -112,7 +136,7 @@ public class ASN1GeneralizedTime
Date time)
{
// Android-changed: Use localized version
- // SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+ // SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'", DateUtil.EN_Locale);
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'", Locale.US);
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
@@ -169,7 +193,6 @@ public class ASN1GeneralizedTime
* </pre>
* To read in the time and get a date which is compatible with our local
* time zone.
- * </p>
* @return a String representation of the time.
*/
public String getTime()
@@ -264,12 +287,24 @@ public class ASN1GeneralizedTime
// dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'", Locale.US);
}
- else
+ else if (hasSeconds())
{
// Android-changed: Use localized version
// dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'", Locale.US);
}
+ else if (hasMinutes())
+ {
+ // Android-changed: Use localized version
+ // dateF = new SimpleDateFormat("yyyyMMddHHmm'Z'");
+ dateF = new SimpleDateFormat("yyyyMMddHHmm'Z'", Locale.US);
+ }
+ else
+ {
+ // Android-changed: Use localized version
+ // dateF = new SimpleDateFormat("yyyyMMddHH'Z'");
+ dateF = new SimpleDateFormat("yyyyMMddHH'Z'", Locale.US);
+ }
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
}
@@ -282,12 +317,24 @@ public class ASN1GeneralizedTime
// dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz", Locale.US);
}
- else
+ else if (hasSeconds())
{
// Android-changed: Use localized version
// dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
dateF = new SimpleDateFormat("yyyyMMddHHmmssz", Locale.US);
}
+ else if (hasMinutes())
+ {
+ // Android-changed: Use localized version
+ // dateF = new SimpleDateFormat("yyyyMMddHHmmz");
+ dateF = new SimpleDateFormat("yyyyMMddHHmmz", Locale.US);
+ }
+ else
+ {
+ // Android-changed: Use localized version
+ // dateF = new SimpleDateFormat("yyyyMMddHHz");
+ dateF = new SimpleDateFormat("yyyyMMddHHz", Locale.US);
+ }
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
}
@@ -299,12 +346,24 @@ public class ASN1GeneralizedTime
// dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS", Locale.US);
}
- else
+ else if (hasSeconds())
{
// Android-changed: Use localized version
// dateF = new SimpleDateFormat("yyyyMMddHHmmss");
dateF = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
}
+ else if (hasMinutes())
+ {
+ // Android-changed: Use localized version
+ // dateF = new SimpleDateFormat("yyyyMMddHHmm");
+ dateF = new SimpleDateFormat("yyyyMMddHHmm", Locale.US);
+ }
+ else
+ {
+ // Android-changed: Use localized version
+ // dateF = new SimpleDateFormat("yyyyMMddHH");
+ dateF = new SimpleDateFormat("yyyyMMddHH", Locale.US);
+ }
dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
}
@@ -340,10 +399,10 @@ public class ASN1GeneralizedTime
}
}
- return dateF.parse(d);
+ return DateUtil.epochAdjust(dateF.parse(d));
}
- private boolean hasFractionalSeconds()
+ protected boolean hasFractionalSeconds()
{
for (int i = 0; i != time.length; i++)
{
@@ -358,6 +417,21 @@ public class ASN1GeneralizedTime
return false;
}
+ protected boolean hasSeconds()
+ {
+ return isDigit(12) && isDigit(13);
+ }
+
+ protected boolean hasMinutes()
+ {
+ return isDigit(10) && isDigit(11);
+ }
+
+ private boolean isDigit(int pos)
+ {
+ return time.length > pos && time[pos] >= '0' && time[pos] <= '9';
+ }
+
boolean isConstructed()
{
return false;
@@ -377,6 +451,11 @@ public class ASN1GeneralizedTime
out.writeEncoded(BERTags.GENERALIZED_TIME, time);
}
+ ASN1Primitive toDERObject()
+ {
+ return new DERGeneralizedTime(time);
+ }
+
boolean asn1Equals(
ASN1Primitive o)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java
index 0c63a1a6..92d8cbb0 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1InputStream.java
@@ -9,7 +9,7 @@ import java.io.InputStream;
import org.bouncycastle.util.io.Streams;
/**
- * a general purpose ASN.1 decoder - note: this class differs from the
+ * A general purpose ASN.1 decoder - note: this class differs from the
* others in that it returns null after it has read the last object in
* the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
* returned.
@@ -143,7 +143,7 @@ public class ASN1InputStream
if ((tag & APPLICATION) != 0)
{
- return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ return new DLApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
}
if ((tag & TAGGED) != 0)
@@ -181,7 +181,7 @@ public class ASN1InputStream
case SET:
return DERFactory.createSet(buildDEREncodableVector(defIn));
case EXTERNAL:
- return new DERExternal(buildDEREncodableVector(defIn));
+ return new DLExternal(buildDEREncodableVector(defIn));
default:
throw new IOException("unknown tag " + tagNo + " encountered");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java
index ab6d2020..39ada8b5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.math.BigInteger;
import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Properties;
/**
* Class representing the ASN.1 INTEGER type.
@@ -14,11 +15,11 @@ public class ASN1Integer
private final byte[] bytes;
/**
- * return an integer from the passed in object
+ * 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.
+ * @throws IllegalArgumentException if the object cannot be converted.
*/
public static ASN1Integer getInstance(
Object obj)
@@ -44,14 +45,14 @@ public class ASN1Integer
}
/**
- * return an Integer from a tagged object.
+ * 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.
+ * @return an ASN1Integer instance.
* @throws IllegalArgumentException if the tagged object cannot
* be converted.
- * @return an ASN1Integer instance.
*/
public static ASN1Integer getInstance(
ASN1TaggedObject obj,
@@ -65,22 +66,54 @@ public class ASN1Integer
}
else
{
- return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets());
+ return new ASN1Integer(ASN1OctetString.getInstance(o).getOctets());
}
}
+ /**
+ * Construct an INTEGER from the passed in long value.
+ *
+ * @param value the long representing the value desired.
+ */
public ASN1Integer(
long value)
{
bytes = BigInteger.valueOf(value).toByteArray();
}
+ /**
+ * Construct an INTEGER from the passed in BigInteger value.
+ *
+ * @param value the BigInteger representing the value desired.
+ */
public ASN1Integer(
BigInteger value)
{
bytes = value.toByteArray();
}
+ /**
+ * Construct an INTEGER from the passed in byte array.
+ *
+ * <p>
+ * <b>NB: Strict Validation applied by default.</b>
+ * </p>
+ * <p>
+ * It has turned out that there are still a few applications that struggle with
+ * the ASN.1 BER encoding rules for an INTEGER as described in:
+ *
+ * https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ * Section 8.3.2.
+ * </p>
+ * <p>
+ * Users can set the 'org.bouncycastle.asn1.allow_unsafe_integer' to 'true'
+ * and a looser validation will be applied. Users must recognise that this is
+ * not ideal and may pave the way for an exploit based around a faulty encoding
+ * in the future.
+ * </p>
+ *
+ * @param bytes the byte array representing a 2's complement encoding of a BigInteger.
+ */
public ASN1Integer(
byte[] bytes)
{
@@ -89,18 +122,38 @@ public class ASN1Integer
ASN1Integer(byte[] bytes, boolean clone)
{
+ // Apply loose validation, see note in public constructor ANS1Integer(byte[])
+ if (!Properties.isOverrideSet("org.bouncycastle.asn1.allow_unsafe_integer"))
+ {
+ if (isMalformed(bytes))
+ {
+ throw new IllegalArgumentException("malformed integer");
+ }
+ }
+ this.bytes = (clone) ? Arrays.clone(bytes) : bytes;
+ }
+
+ /**
+ * Apply the correct validation for an INTEGER primitive following the BER rules.
+ *
+ * @param bytes The raw encoding of the integer.
+ * @return true if the (in)put fails this validation.
+ */
+ static boolean isMalformed(byte[] bytes)
+ {
if (bytes.length > 1)
{
if (bytes[0] == 0 && (bytes[1] & 0x80) == 0)
{
- throw new IllegalArgumentException("malformed integer");
+ return true;
}
if (bytes[0] == (byte)0xff && (bytes[1] & 0x80) != 0)
{
- throw new IllegalArgumentException("malformed integer");
+ return true;
}
}
- this.bytes = (clone) ? Arrays.clone(bytes) : bytes;
+
+ return false;
}
public BigInteger getValue()
@@ -111,6 +164,7 @@ public class ASN1Integer
/**
* 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()
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java
index f39d1206..7cf07657 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Null.java
@@ -1,3 +1,6 @@
+/***************************************************************/
+/****** DO NOT EDIT THIS CLASS bc-java SOURCE FILE ******/
+/***************************************************************/
package org.bouncycastle.asn1;
import java.io.IOException;
@@ -8,6 +11,11 @@ import java.io.IOException;
public abstract class ASN1Null
extends ASN1Primitive
{
+ ASN1Null()
+ {
+
+ }
+
/**
* Return an instance of ASN.1 NULL from the passed in object.
* <p>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
index bdfec4fd..b5288a2b 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
@@ -19,7 +19,7 @@ public class ASN1ObjectIdentifier
private byte[] body;
/**
- * return an OID from the passed in object
+ * Return an OID from the passed in object
*
* @param obj an ASN1ObjectIdentifier or an object that can be converted into one.
* @return an ASN1ObjectIdentifier instance, or null.
@@ -33,9 +33,14 @@ public class ASN1ObjectIdentifier
return (ASN1ObjectIdentifier)obj;
}
- if (obj instanceof ASN1Encodable && ((ASN1Encodable)obj).toASN1Primitive() instanceof ASN1ObjectIdentifier)
+ if (obj instanceof ASN1Encodable)
{
- return (ASN1ObjectIdentifier)((ASN1Encodable)obj).toASN1Primitive();
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1ObjectIdentifier)
+ {
+ return (ASN1ObjectIdentifier)primitive;
+ }
}
if (obj instanceof byte[])
@@ -55,7 +60,7 @@ public class ASN1ObjectIdentifier
}
/**
- * return an Object Identifier from a tagged object.
+ * 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
@@ -76,7 +81,7 @@ public class ASN1ObjectIdentifier
}
else
{
- return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets());
+ return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(o).getOctets());
}
}
@@ -219,7 +224,7 @@ public class ASN1ObjectIdentifier
}
/**
- * Return true if this oid is an extension of the passed in branch, stem.
+ * 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.
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java
index 07811d71..2df802bc 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java
@@ -16,7 +16,6 @@ import org.bouncycastle.util.encoders.Hex;
* 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>
@@ -38,20 +37,19 @@ import org.bouncycastle.util.encoders.Hex;
* <p>
* <b>8.7.3</b> The contents octets for the constructed encoding shall consist
* of zero, one, or more encodings.
+ * </p>
* <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.
+ * placed on the segment boundaries.</p>
* <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
@@ -59,15 +57,16 @@ import org.bouncycastle.util.encoders.Hex;
* 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.
+ * </p>
* <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.
- * <br />
+ * </blockquote>
+ * <blockquote>
* 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>
@@ -96,7 +95,6 @@ import org.bouncycastle.util.encoders.Hex;
* 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
@@ -249,6 +247,6 @@ public abstract class ASN1OctetString
public String toString()
{
- return "#"+ Strings.fromByteArray(Hex.encode(string));
+ return "#" + Strings.fromByteArray(Hex.encode(string));
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java
index db72d6ad..94b0b3d5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Primitive.java
@@ -79,11 +79,23 @@ public abstract class ASN1Primitive
public abstract int hashCode();
+ /**
+ * Return true if this objected is a CONSTRUCTED one, false otherwise.
+ * @return true if CONSTRUCTED bit set on object's tag, false otherwise.
+ */
abstract boolean isConstructed();
+ /**
+ * Return the length of the encoding this object will produce.
+ * @return the length of the object's encoding.
+ * @throws IOException if the encoding length cannot be calculated.
+ */
abstract int encodedLength() throws IOException;
abstract void encode(ASN1OutputStream out) throws IOException;
+ /**
+ * Equality (similarity) comparison for two ASN1Primitive objects.
+ */
abstract boolean asn1Equals(ASN1Primitive o);
} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java
index 0ca4d8f5..ea6f3d87 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Sequence.java
@@ -50,9 +50,11 @@ import org.bouncycastle.util.Arrays;
*
* <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>
+ * <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.
+ * </p>
*/
public abstract class ASN1Sequence
extends ASN1Primitive
@@ -103,7 +105,7 @@ public abstract class ASN1Sequence
}
/**
- * Return an ASN1 sequence from a tagged object. There is a special
+ * Return an ASN1 SEQUENCE from a tagged object. There is a special
* case here, if an object appears to have been explicitly tagged on
* reading but we were expecting it to be implicitly tagged in the
* normal course of events it indicates that we lost the surrounding
@@ -134,6 +136,8 @@ public abstract class ASN1Sequence
}
else
{
+ ASN1Primitive o = obj.getObject();
+
//
// constructed object which appears to be explicitly tagged
// when it should be implicit means we have to add the
@@ -143,18 +147,18 @@ public abstract class ASN1Sequence
{
if (obj instanceof BERTaggedObject)
{
- return new BERSequence(obj.getObject());
+ return new BERSequence(o);
}
else
{
- return new DLSequence(obj.getObject());
+ return new DLSequence(o);
}
}
else
{
- if (obj.getObject() instanceof ASN1Sequence)
+ if (o instanceof ASN1Sequence)
{
- return (ASN1Sequence)obj.getObject();
+ return (ASN1Sequence)o;
}
}
}
@@ -163,14 +167,14 @@ 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(
@@ -180,8 +184,8 @@ public abstract class ASN1Sequence
}
/**
- * Create a sequence containing a vector of objects.
- * @param v the vector of objects to be put in the SEQUENCE
+ * Create a SEQUENCE containing a vector of objects.
+ * @param v the vector of objects to be put in the SEQUENCE.
*/
protected ASN1Sequence(
ASN1EncodableVector v)
@@ -192,8 +196,9 @@ public abstract class ASN1Sequence
}
}
- /*
- * Create a sequence containing a vector of objects.
+ /**
+ * Create a SEQUENCE containing an array of objects.
+ * @param array the array of objects to be put in the SEQUENCE.
*/
protected ASN1Sequence(
ASN1Encodable[] array)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java
index 1f6234f5..9865533c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java
@@ -12,13 +12,12 @@ import org.bouncycastle.util.Arrays;
* <p>
* Note: This does not know which syntax the set is!
* (The difference: ordering of SET elements or not ordering.)
- * <p>
+ * </p><p>
* DER form is always definite form length fields, while
* BER support uses indefinite form.
- * <p>
+ * </p><p>
* The CER form support does not exist.
- * <p>
- * <hr>
+ * </p><p>
* <h2>X.690</h2>
* <h3>8: Basic encoding rules</h3>
* <h4>8.11 Encoding of a set value </h4>
@@ -29,7 +28,7 @@ import org.bouncycastle.util.Arrays;
* 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><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>.
@@ -38,13 +37,14 @@ import org.bouncycastle.util.Arrays;
* 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.1</b> The encoding of a set-of value shall be constructed.
+ * </p><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>
+ * </p><p>
* <b>8.12.3</b> The order of data values need not be preserved by
* the encoding and subsequent decoding.
*
@@ -175,6 +175,8 @@ public abstract class ASN1Set
}
else
{
+ ASN1Primitive o = obj.getObject();
+
//
// constructed object which appears to be explicitly tagged
// and it's really implicit means we have to add the
@@ -184,27 +186,27 @@ public abstract class ASN1Set
{
if (obj instanceof BERTaggedObject)
{
- return new BERSet(obj.getObject());
+ return new BERSet(o);
}
else
{
- return new DLSet(obj.getObject());
+ return new DLSet(o);
}
}
else
{
- if (obj.getObject() instanceof ASN1Set)
+ if (o instanceof ASN1Set)
{
- return (ASN1Set)obj.getObject();
+ return (ASN1Set)o;
}
//
// in this case the parser returns a sequence, convert it
// into a set.
//
- if (obj.getObject() instanceof ASN1Sequence)
+ if (o instanceof ASN1Sequence)
{
- ASN1Sequence s = (ASN1Sequence)obj.getObject();
+ ASN1Sequence s = (ASN1Sequence)o;
if (obj instanceof BERTaggedObject)
{
@@ -226,7 +228,7 @@ public abstract class ASN1Set
}
/**
- * create a sequence containing one object
+ * Create a SET containing one object
* @param obj object to be added to the SET.
*/
protected ASN1Set(
@@ -236,7 +238,7 @@ public abstract class ASN1Set
}
/**
- * create a sequence containing a vector of objects.
+ * Create a SET 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.
*/
@@ -255,8 +257,10 @@ public abstract class ASN1Set
}
}
- /*
- * create a sequence containing a vector of objects.
+ /**
+ * Create a SET containing an array of objects.
+ * @param array an array of objects to make up the SET.
+ * @param doSort true if should be sorted DER style, false otherwise.
*/
protected ASN1Set(
ASN1Encodable[] array,
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java
index a4bb370e..a1034292 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1StreamParser.java
@@ -172,7 +172,7 @@ public class ASN1StreamParser
if ((tag & BERTags.APPLICATION) != 0)
{
- return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ return new DLApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
}
if ((tag & BERTags.TAGGED) != 0)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1String.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1String.java
index 37544406..0c265bb0 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1String.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1String.java
@@ -1,7 +1,7 @@
package org.bouncycastle.asn1;
/**
- * General interface implemented by ASN.1 STRING objects.
+ * General interface implemented by ASN.1 STRING objects for extracting the content String.
*/
public interface ASN1String
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java
index 808f478e..66ac4aaa 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java
@@ -173,7 +173,7 @@ public abstract class ASN1TaggedObject
}
/**
- * return whatever was following the tag.
+ * Return whatever was following the tag.
* <p>
* Note: tagged objects are generally context dependent if you're
* trying to extract a tagged object you should be going via the
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
index a681dc94..660d9a28 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
@@ -2,11 +2,26 @@ package org.bouncycastle.asn1;
import java.io.IOException;
+/**
+ * Interface for the parsing of a generic tagged ASN.1 object.
+ */
public interface ASN1TaggedObjectParser
extends ASN1Encodable, InMemoryRepresentable
{
- public int getTagNo();
-
- public ASN1Encodable getObjectParser(int tag, boolean isExplicit)
+ /**
+ * Return the tag number associated with the underlying tagged object.
+ * @return the object's tag number.
+ */
+ int getTagNo();
+
+ /**
+ * Return a parser for the actual object tagged.
+ *
+ * @param tag the primitive tag value for the object tagged originally.
+ * @param isExplicit true if the tagging was done explicitly.
+ * @return a parser for the tagged object.
+ * @throws IOException if a parser cannot be constructed.
+ */
+ ASN1Encodable getObjectParser(int tag, boolean isExplicit)
throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java
index 446af77f..d2909370 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1UTCTime.java
@@ -17,7 +17,7 @@ import org.bouncycastle.util.Strings;
* 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>
+ * </p>
* <hr>
* <p><b>X.690</b></p>
* <p><b>11: Restrictions on BER employed by both CER and DER</b></p>
@@ -39,7 +39,7 @@ public class ASN1UTCTime
private byte[] time;
/**
- * return an UTC Time from the passed in object.
+ * 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.
@@ -69,7 +69,7 @@ public class ASN1UTCTime
}
/**
- * return an UTC Time from a tagged object.
+ * 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
@@ -119,14 +119,14 @@ public class ASN1UTCTime
}
/**
- * base constructor from a java.util.date object
+ * Base constructor from a java.util.date object
* @param time the Date to build the time from.
*/
public ASN1UTCTime(
Date time)
{
// Android-changed: Use localized version
- // SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
+ // SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'", DateUtil.EN_Locale);
SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'", Locale.US);
dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
@@ -163,7 +163,7 @@ public class ASN1UTCTime
}
/**
- * return the time as a date based on whatever a 2 digit year will return. For
+ * Return the time as a date based on whatever a 2 digit year will return. For
* standardised processing use getAdjustedDate().
*
* @return the resulting date
@@ -176,11 +176,11 @@ public class ASN1UTCTime
// SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz", Locale.US);
- return dateF.parse(getTime());
+ return DateUtil.epochAdjust(dateF.parse(getTime()));
}
/**
- * return the time as an adjusted date
+ * Return the time as an adjusted date
* in the range of 1950 - 2049.
*
* @return a date in the range of 1950 to 2049.
@@ -193,13 +193,13 @@ public class ASN1UTCTime
// SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz", Locale.US);
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
-
- return dateF.parse(getAdjustedTime());
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ return DateUtil.epochAdjust(dateF.parse(getAdjustedTime()));
}
/**
- * return the time - always in the form of
+ * 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",
@@ -258,7 +258,7 @@ public class ASN1UTCTime
}
/**
- * return a time string as an adjusted date with a 4 digit year. This goes
+ * Return a time string as an adjusted date with a 4 digit year. This goes
* in the range of 1950 - 2049.
*/
public String getAdjustedTime()
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java
index f8d6aa22..3608668d 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecific.java
@@ -4,7 +4,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
- * An indefinite-length encoding version of an application specific object.
+ * An indefinite-length encoding version of an ASN.1 ApplicationSpecific object.
*/
public class BERApplicationSpecific
extends ASN1ApplicationSpecific
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java
index e4904e05..c915415a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java
@@ -3,7 +3,7 @@ package org.bouncycastle.asn1;
import java.io.IOException;
/**
- * A parser for indefinite-length application specific objects.
+ * A parser for indefinite-length ASN.1 ApplicationSpecific objects.
*/
public class BERApplicationSpecificParser
implements ASN1ApplicationSpecificParser
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetString.java b/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetString.java
index bc1ed448..63349340 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetString.java
@@ -5,15 +5,30 @@ import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
+/**
+ * ASN.1 OctetStrings, with indefinite length rules, and <i>constructed form</i> support.
+ * <p>
+ * The Basic Encoding Rules (BER) format allows encoding using so called "<i>constructed form</i>",
+ * which DER and CER formats forbid allowing only "primitive form".
+ * </p><p>
+ * This class <b>always</b> produces the constructed form with underlying segments
+ * in an indefinite length array. If the input wasn't the same, then this output
+ * is not faithful reproduction.
+ * </p>
+ * <p>
+ * See {@link ASN1OctetString} for X.690 encoding rules of OCTET-STRING objects.
+ * </p>
+ */
public class BEROctetString
extends ASN1OctetString
{
- private static final int MAX_LENGTH = 1000;
+ private static final int DEFAULT_LENGTH = 1000;
- private ASN1OctetString[] octs;
+ private final int chunkSize;
+ private final ASN1OctetString[] octs;
/**
- * convert a vector of octet strings into a single byte string
+ * Convert a vector of octet strings into a single byte string
*/
static private byte[] toBytes(
ASN1OctetString[] octs)
@@ -42,29 +57,73 @@ public class BEROctetString
}
/**
+ * Create an OCTET-STRING object from a byte[]
* @param string the octets making up the octet string.
*/
public BEROctetString(
byte[] string)
{
- super(string);
+ this(string, DEFAULT_LENGTH);
}
+ /**
+ * Multiple {@link ASN1OctetString} data blocks are input,
+ * the result is <i>constructed form</i>.
+ *
+ * @param octs an array of OCTET STRING to construct the BER OCTET STRING from.
+ */
public BEROctetString(
ASN1OctetString[] octs)
{
- super(toBytes(octs));
+ this(octs, DEFAULT_LENGTH);
+ }
+
+ /**
+ * Create an OCTET-STRING object from a byte[]
+ * @param string the octets making up the octet string.
+ * @param chunkSize the number of octets stored in each DER encoded component OCTET STRING.
+ */
+ public BEROctetString(
+ byte[] string,
+ int chunkSize)
+ {
+ this(string, null, chunkSize);
+ }
+ /**
+ * Multiple {@link ASN1OctetString} data blocks are input,
+ * the result is <i>constructed form</i>.
+ *
+ * @param octs an array of OCTET STRING to construct the BER OCTET STRING from.
+ * @param chunkSize the number of octets stored in each DER encoded component OCTET STRING.
+ */
+ public BEROctetString(
+ ASN1OctetString[] octs,
+ int chunkSize)
+ {
+ this(toBytes(octs), octs, chunkSize);
+ }
+
+ private BEROctetString(byte[] string, ASN1OctetString[] octs, int chunkSize)
+ {
+ super(string);
this.octs = octs;
+ this.chunkSize = chunkSize;
}
+ /**
+ * Return a concatenated byte array of all the octets making up the constructed OCTET STRING
+ * @return the full OCTET STRING.
+ */
public byte[] getOctets()
{
return string;
}
/**
- * return the DER octets that make up this string.
+ * Return the OCTET STRINGs that make up this string.
+ *
+ * @return an Enumeration of the component OCTET STRINGs.
*/
public Enumeration getObjects()
{
@@ -92,17 +151,17 @@ public class BEROctetString
private Vector generateOcts()
{
Vector vec = new Vector();
- for (int i = 0; i < string.length; i += MAX_LENGTH)
+ for (int i = 0; i < string.length; i += chunkSize)
{
int end;
- if (i + MAX_LENGTH > string.length)
+ if (i + chunkSize > string.length)
{
end = string.length;
}
else
{
- end = i + MAX_LENGTH;
+ end = i + chunkSize;
}
byte[] nStr = new byte[end - i];
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BEROutputStream.java b/bcprov/src/main/java/org/bouncycastle/asn1/BEROutputStream.java
index f6459b2e..22a37ed4 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/BEROutputStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/BEROutputStream.java
@@ -4,7 +4,8 @@ import java.io.IOException;
import java.io.OutputStream;
/**
- * A class which writes indefinite and definite length objects,
+ * A class which writes indefinite and definite length objects. Objects which specify DER will be encoded accordingly, but DL or BER
+ * objects will be encoded as defined.
*/
public class BEROutputStream
extends DEROutputStream
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERSequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERSequence.java
index d4bfa061..3ecb1461 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/BERSequence.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERSequence.java
@@ -4,7 +4,12 @@ import java.io.IOException;
import java.util.Enumeration;
/**
- * Carrier class for an indefinite-length SEQUENCE.
+ * Indefinite length SEQUENCE of objects.
+ * <p>
+ * Length field has value 0x80, and the sequence ends with two bytes of: 0x00, 0x00.
+ * </p><p>
+ * For X.690 syntax rules, see {@link ASN1Sequence}.
+ * </p>
*/
public class BERSequence
extends ASN1Sequence
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERSet.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERSet.java
index 63a276bb..29ae7fd7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/BERSet.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERSet.java
@@ -4,7 +4,18 @@ import java.io.IOException;
import java.util.Enumeration;
/**
- * Carrier class for an indefinite-length SET.
+ * Indefinite length <code>SET</code> and <code>SET OF</code> constructs.
+ * <p>
+ * Note: This does not know which syntax the set is!
+ * </p><p>
+ * Length field has value 0x80, and the set ends with two bytes of: 0x00, 0x00.
+ * </p><p>
+ * For X.690 syntax rules, see {@link ASN1Set}.
+ * </p><p>
+ * In brief: Constructing this form does not sort the supplied elements,
+ * nor does the sorting happen before serialization. This is different
+ * from the way {@link DERSet} does things.
+ * </p>
*/
public class BERSet
extends ASN1Set
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java
index 98ab0d68..39b517e6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java
@@ -9,28 +9,28 @@ public interface BERTags
public static final int NULL = 0x05;
public static final int OBJECT_IDENTIFIER = 0x06;
public static final int EXTERNAL = 0x08;
- public static final int ENUMERATED = 0x0a;
- public static final int SEQUENCE = 0x10;
+ public static final int ENUMERATED = 0x0a; // decimal 10
+ public static final int SEQUENCE = 0x10; // decimal 16
public static final int SEQUENCE_OF = 0x10; // for completeness - used to model a SEQUENCE of the same type.
- public static final int SET = 0x11;
+ public static final int SET = 0x11; // decimal 17
public static final int SET_OF = 0x11; // for completeness - used to model a SET of the same type.
- public static final int NUMERIC_STRING = 0x12;
- public static final int PRINTABLE_STRING = 0x13;
- public static final int T61_STRING = 0x14;
- public static final int VIDEOTEX_STRING = 0x15;
- public static final int IA5_STRING = 0x16;
- public static final int UTC_TIME = 0x17;
- public static final int GENERALIZED_TIME = 0x18;
- public static final int GRAPHIC_STRING = 0x19;
- public static final int VISIBLE_STRING = 0x1a;
- public static final int GENERAL_STRING = 0x1b;
- public static final int UNIVERSAL_STRING = 0x1c;
- public static final int BMP_STRING = 0x1e;
- public static final int UTF8_STRING = 0x0c;
+ public static final int NUMERIC_STRING = 0x12; // decimal 18
+ public static final int PRINTABLE_STRING = 0x13; // decimal 19
+ public static final int T61_STRING = 0x14; // decimal 20
+ public static final int VIDEOTEX_STRING = 0x15; // decimal 21
+ public static final int IA5_STRING = 0x16; // decimal 22
+ public static final int UTC_TIME = 0x17; // decimal 23
+ public static final int GENERALIZED_TIME = 0x18; // decimal 24
+ public static final int GRAPHIC_STRING = 0x19; // decimal 25
+ public static final int VISIBLE_STRING = 0x1a; // decimal 26
+ public static final int GENERAL_STRING = 0x1b; // decimal 27
+ public static final int UNIVERSAL_STRING = 0x1c; // decimal 28
+ public static final int BMP_STRING = 0x1e; // decimal 30
+ public static final int UTF8_STRING = 0x0c; // decimal 12
- public static final int CONSTRUCTED = 0x20;
- public static final int APPLICATION = 0x40;
- public static final int TAGGED = 0x80;
+ public static final int CONSTRUCTED = 0x20; // decimal 32
+ public static final int APPLICATION = 0x40; // decimal 64
+ public static final int TAGGED = 0x80; // decimal 128
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java
index e689985c..c64802c9 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBMPString.java
@@ -5,7 +5,12 @@ import java.io.IOException;
import org.bouncycastle.util.Arrays;
/**
- * Carrier class for DER encoding BMPString object.
+ * DER BMPString object encodes BMP (<i>Basic Multilingual Plane</i>) subset
+ * (aka UCS-2) of UNICODE (ISO 10646) characters in codepoints 0 to 65535.
+ * <p>
+ * At ISO-10646:2011 the term "BMP" has been withdrawn, and replaced by
+ * term "UCS-2".
+ * </p>
*/
public class DERBMPString
extends ASN1Primitive
@@ -14,7 +19,7 @@ public class DERBMPString
private final char[] string;
/**
- * return a BMP String from the given object.
+ * Return a BMP String from the given object.
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -44,7 +49,7 @@ public class DERBMPString
}
/**
- * return a BMP String from a tagged object.
+ * Return a BMP String from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
@@ -70,7 +75,7 @@ public class DERBMPString
}
/**
- * basic constructor - byte encoded string.
+ * Basic constructor - byte encoded string.
* @param string the encoded BMP STRING to wrap.
*/
DERBMPString(
@@ -92,7 +97,7 @@ public class DERBMPString
}
/**
- * basic constructor
+ * Basic constructor
* @param string a String to wrap as a BMP STRING.
*/
public DERBMPString(
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java
index c789d7cd..8efcaf7a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java
@@ -3,7 +3,7 @@ package org.bouncycastle.asn1;
import java.io.IOException;
/**
- * A BIT STRING with DER encoding.
+ * A BIT STRING with DER encoding - the first byte contains the count of padding bits included in the byte array's last byte.
*/
public class DERBitString
extends ASN1BitString
@@ -124,7 +124,7 @@ public class DERBitString
}
void encode(
- ASN1OutputStream out)
+ ASN1OutputStream out)
throws IOException
{
byte[] string = derForm(data, padBits);
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERExternal.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERExternal.java
index f6c45d31..480a3942 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERExternal.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERExternal.java
@@ -7,61 +7,25 @@ import java.io.IOException;
* Class representing the DER-type External
*/
public class DERExternal
- extends ASN1Primitive
+ extends ASN1External
{
- private ASN1ObjectIdentifier directReference;
- private ASN1Integer indirectReference;
- private ASN1Primitive dataValueDescriptor;
- private int encoding;
- private ASN1Primitive externalContent;
-
+ /**
+ * Construct a DER EXTERNAL object, the input encoding vector must have exactly two elements on it.
+ * <p>
+ * Acceptable input formats are:
+ * <ul>
+ * <li> {@link ASN1ObjectIdentifier} + data {@link DERTaggedObject} (direct reference form)</li>
+ * <li> {@link ASN1Integer} + data {@link DERTaggedObject} (indirect reference form)</li>
+ * <li> Anything but {@link DERTaggedObject} + data {@link DERTaggedObject} (data value form)</li>
+ * </ul>
+ *
+ * @throws IllegalArgumentException if input size is wrong, or
+ */
public DERExternal(ASN1EncodableVector vector)
{
- int offset = 0;
-
- ASN1Primitive enc = getObjFromVector(vector, offset);
- if (enc instanceof ASN1ObjectIdentifier)
- {
- directReference = (ASN1ObjectIdentifier)enc;
- offset++;
- enc = getObjFromVector(vector, offset);
- }
- if (enc instanceof ASN1Integer)
- {
- indirectReference = (ASN1Integer) enc;
- offset++;
- enc = getObjFromVector(vector, offset);
- }
- if (!(enc instanceof ASN1TaggedObject))
- {
- dataValueDescriptor = (ASN1Primitive) enc;
- offset++;
- enc = getObjFromVector(vector, offset);
- }
-
- if (vector.size() != offset + 1)
- {
- throw new IllegalArgumentException("input vector too large");
- }
-
- if (!(enc instanceof ASN1TaggedObject))
- {
- throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External");
- }
- ASN1TaggedObject obj = (ASN1TaggedObject)enc;
- setEncoding(obj.getTagNo());
- externalContent = obj.getObject();
+ super(vector);
}
- private ASN1Primitive getObjFromVector(ASN1EncodableVector v, int index)
- {
- if (v.size() <= index)
- {
- throw new IllegalArgumentException("too few objects in input vector");
- }
-
- return v.get(index).toASN1Primitive();
- }
/**
* Creates a new instance of DERExternal
* See X.690 for more informations about the meaning of these parameters
@@ -86,38 +50,7 @@ public class DERExternal
*/
public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData)
{
- setDirectReference(directReference);
- setIndirectReference(indirectReference);
- setDataValueDescriptor(dataValueDescriptor);
- setEncoding(encoding);
- setExternalContent(externalData.toASN1Primitive());
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#hashCode()
- */
- public int hashCode()
- {
- int ret = 0;
- if (directReference != null)
- {
- ret = directReference.hashCode();
- }
- if (indirectReference != null)
- {
- ret ^= indirectReference.hashCode();
- }
- if (dataValueDescriptor != null)
- {
- ret ^= dataValueDescriptor.hashCode();
- }
- ret ^= externalContent.hashCode();
- return ret;
- }
-
- boolean isConstructed()
- {
- return true;
+ super(directReference, indirectReference, dataValueDescriptor, encoding, externalData);
}
int encodedLength()
@@ -149,146 +82,4 @@ public class DERExternal
baos.write(obj.getEncoded(ASN1Encoding.DER));
out.writeEncoded(BERTags.CONSTRUCTED, BERTags.EXTERNAL, baos.toByteArray());
}
-
- /* (non-Javadoc)
- * @see org.bouncycastle.asn1.ASN1Primitive#asn1Equals(org.bouncycastle.asn1.ASN1Primitive)
- */
- boolean asn1Equals(ASN1Primitive o)
- {
- if (!(o instanceof DERExternal))
- {
- return false;
- }
- if (this == o)
- {
- return true;
- }
- DERExternal other = (DERExternal)o;
- if (directReference != null)
- {
- if (other.directReference == null || !other.directReference.equals(directReference))
- {
- return false;
- }
- }
- if (indirectReference != null)
- {
- if (other.indirectReference == null || !other.indirectReference.equals(indirectReference))
- {
- return false;
- }
- }
- if (dataValueDescriptor != null)
- {
- if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor))
- {
- return false;
- }
- }
- return externalContent.equals(other.externalContent);
- }
-
- /**
- * Returns the data value descriptor
- * @return The descriptor
- */
- public ASN1Primitive getDataValueDescriptor()
- {
- return dataValueDescriptor;
- }
-
- /**
- * Returns the direct reference of the external element
- * @return The reference
- */
- public ASN1ObjectIdentifier getDirectReference()
- {
- return directReference;
- }
-
- /**
- * Returns the encoding of the content. Valid values are
- * <ul>
- * <li><code>0</code> single-ASN1-type</li>
- * <li><code>1</code> OCTET STRING</li>
- * <li><code>2</code> BIT STRING</li>
- * </ul>
- * @return The encoding
- */
- public int getEncoding()
- {
- return encoding;
- }
-
- /**
- * Returns the content of this element
- * @return The content
- */
- public ASN1Primitive getExternalContent()
- {
- return externalContent;
- }
-
- /**
- * Returns the indirect reference of this element
- * @return The reference
- */
- public ASN1Integer getIndirectReference()
- {
- return indirectReference;
- }
-
- /**
- * Sets the data value descriptor
- * @param dataValueDescriptor The descriptor
- */
- private void setDataValueDescriptor(ASN1Primitive dataValueDescriptor)
- {
- this.dataValueDescriptor = dataValueDescriptor;
- }
-
- /**
- * Sets the direct reference of the external element
- * @param directReferemce The reference
- */
- private void setDirectReference(ASN1ObjectIdentifier directReferemce)
- {
- this.directReference = directReferemce;
- }
-
- /**
- * Sets the encoding of the content. Valid values are
- * <ul>
- * <li><code>0</code> single-ASN1-type</li>
- * <li><code>1</code> OCTET STRING</li>
- * <li><code>2</code> BIT STRING</li>
- * </ul>
- * @param encoding The encoding
- */
- private void setEncoding(int encoding)
- {
- if (encoding < 0 || encoding > 2)
- {
- throw new IllegalArgumentException("invalid encoding value: " + encoding);
- }
- this.encoding = encoding;
- }
-
- /**
- * Sets the content of this element
- * @param externalContent The content
- */
- private void setExternalContent(ASN1Primitive externalContent)
- {
- this.externalContent = externalContent;
- }
-
- /**
- * Sets the indirect reference of this element
- * @param indirectReference The reference
- */
- private void setIndirectReference(ASN1Integer indirectReference)
- {
- this.indirectReference = indirectReference;
- }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERExternalParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERExternalParser.java
index 98d02e73..afdf510c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERExternalParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERExternalParser.java
@@ -37,7 +37,7 @@ public class DERExternalParser
{
try
{
- return new DERExternal(_parser.readVector());
+ return new DLExternal(_parser.readVector());
}
catch (IllegalArgumentException e)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralString.java
index 9addf700..52a580fa 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralString.java
@@ -6,7 +6,11 @@ import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;
/**
- * Carrier class for a DER encoding GeneralString
+ * ASN.1 GENERAL-STRING data type.
+ * <p>
+ * This is an 8-bit encoded ISO 646 (ASCII) character set
+ * with optional escapes to other character sets.
+ * </p>
*/
public class DERGeneralString
extends ASN1Primitive
@@ -15,7 +19,7 @@ public class DERGeneralString
private final byte[] string;
/**
- * return a GeneralString from the given object.
+ * Return a GeneralString from the given object.
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -46,7 +50,7 @@ public class DERGeneralString
}
/**
- * return a GeneralString from a tagged object.
+ * Return a GeneralString from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java
index adee74ec..1270e85c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERGeneralizedTime.java
@@ -1,17 +1,33 @@
package org.bouncycastle.asn1;
+import java.io.IOException;
import java.util.Date;
+import org.bouncycastle.util.Strings;
+
/**
* DER Generalized time object.
+ * <h3>11: Restrictions on BER employed by both CER and DER</h3>
+ * <h4>11.7 GeneralizedTime </h4>
+ * <p>
+ * <b>11.7.1</b> The encoding shall terminate with a "Z",
+ * as described in the ITU-T Rec. X.680 | ISO/IEC 8824-1 clause on
+ * GeneralizedTime.
+ * </p><p>
+ * <b>11.7.2</b> The seconds element shall always be present.
+ * </p>
+ * <p>
+ * <b>11.7.3</b> The fractional-seconds elements, if present,
+ * shall omit all trailing zeros; if the elements correspond to 0,
+ * they shall be wholly omitted, and the decimal point element also
+ * shall be omitted.
*/
public class DERGeneralizedTime
extends ASN1GeneralizedTime
{
-
- DERGeneralizedTime(byte[] bytes)
+ public DERGeneralizedTime(byte[] time)
{
- super(bytes);
+ super(time);
}
public DERGeneralizedTime(Date time)
@@ -24,5 +40,77 @@ public class DERGeneralizedTime
super(time);
}
- // TODO: create proper DER encoding.
+ private byte[] getDERTime()
+ {
+ if (time[time.length - 1] == 'Z')
+ {
+ if (!hasMinutes())
+ {
+ byte[] derTime = new byte[time.length + 4];
+
+ System.arraycopy(time, 0, derTime, 0, time.length - 1);
+ System.arraycopy(Strings.toByteArray("0000Z"), 0, derTime, time.length - 1, 5);
+
+ return derTime;
+ }
+ else if (!hasSeconds())
+ {
+ byte[] derTime = new byte[time.length + 2];
+
+ System.arraycopy(time, 0, derTime, 0, time.length - 1);
+ System.arraycopy(Strings.toByteArray("00Z"), 0, derTime, time.length - 1, 3);
+
+ return derTime;
+ }
+ else if (hasFractionalSeconds())
+ {
+ int ind = time.length - 2;
+ while (ind > 0 && time[ind] == '0')
+ {
+ ind--;
+ }
+
+ if (time[ind] == '.')
+ {
+ byte[] derTime = new byte[ind + 1];
+
+ System.arraycopy(time, 0, derTime, 0, ind);
+ derTime[ind] = (byte)'Z';
+
+ return derTime;
+ }
+ else
+ {
+ byte[] derTime = new byte[ind + 2];
+
+ System.arraycopy(time, 0, derTime, 0, ind + 1);
+ derTime[ind + 1] = (byte)'Z';
+
+ return derTime;
+ }
+ }
+ else
+ {
+ return time;
+ }
+ }
+ else
+ {
+ return time; // TODO: is there a better way?
+ }
+ }
+
+ int encodedLength()
+ {
+ int length = getDERTime().length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.GENERALIZED_TIME, getDERTime());
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java
index 0336e6b7..d2f7a8d1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERIA5String.java
@@ -6,7 +6,10 @@ import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;
/**
- * DER IA5String object - this is an ascii string.
+ * DER IA5String object - this is a ISO 646 (ASCII) string encoding code points 0 to 127.
+ * <p>
+ * Explicit character set escape sequences are not allowed.
+ * </p>
*/
public class DERIA5String
extends ASN1Primitive
@@ -15,7 +18,7 @@ public class DERIA5String
private final byte[] string;
/**
- * return a IA5 string from the passed in object
+ * Return an 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.
@@ -45,7 +48,7 @@ public class DERIA5String
}
/**
- * return an IA5 String from a tagged object.
+ * Return an IA5 String from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
@@ -71,7 +74,7 @@ public class DERIA5String
}
/**
- * basic constructor - with bytes.
+ * Basic constructor - with bytes.
* @param string the byte encoding of the characters making up the string.
*/
DERIA5String(
@@ -81,7 +84,7 @@ public class DERIA5String
}
/**
- * basic constructor - without validation.
+ * Basic constructor - without validation.
* @param string the base string to use..
*/
public DERIA5String(
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERNull.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERNull.java
index 3a86b1d6..1981fef7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERNull.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERNull.java
@@ -3,7 +3,9 @@ package org.bouncycastle.asn1;
import java.io.IOException;
/**
- * A NULL object.
+ * An ASN.1 DER NULL object.
+ * <p>
+ * Preferably use the constant: DERNull.INSTANCE.
*/
public class DERNull
extends ASN1Null
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java
index ed287e56..1f82be17 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERNumericString.java
@@ -7,6 +7,13 @@ import org.bouncycastle.util.Strings;
/**
* DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
+ * ASN.1 NUMERIC-STRING object.
+ * <p>
+ * This is an ASCII string of characters {0,1,2,3,4,5,6,7,8,9} + space.
+ * <p>
+ * See X.680 section 37.2.
+ * <p>
+ * Explicit character set escape sequences are not allowed.
*/
public class DERNumericString
extends ASN1Primitive
@@ -15,7 +22,7 @@ public class DERNumericString
private final byte[] string;
/**
- * return a Numeric string from the passed in object
+ * 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.
@@ -45,7 +52,7 @@ public class DERNumericString
}
/**
- * return an Numeric String from a tagged object.
+ * Return an Numeric String from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
@@ -71,7 +78,7 @@ public class DERNumericString
}
/**
- * basic constructor - with bytes.
+ * Basic constructor - with bytes.
*/
DERNumericString(
byte[] string)
@@ -80,7 +87,7 @@ public class DERNumericString
}
/**
- * basic constructor - without validation..
+ * Basic constructor - without validation..
*/
public DERNumericString(
String string)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java
index 58be862d..1c9c1598 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DEROctetStringParser.java
@@ -4,7 +4,7 @@ import java.io.IOException;
import java.io.InputStream;
/**
- * Parse for DER encoded OCTET STRINGS
+ * Parser for DER encoded OCTET STRINGS
*/
public class DEROctetStringParser
implements ASN1OctetStringParser
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java
index 805ad30e..a234eea4 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERPrintableString.java
@@ -7,6 +7,29 @@ import org.bouncycastle.util.Strings;
/**
* DER PrintableString object.
+ * <p>
+ * X.680 section 37.4 defines PrintableString character codes as ASCII subset of following characters:
+ * </p>
+ * <ul>
+ * <li>Latin capital letters: 'A' .. 'Z'</li>
+ * <li>Latin small letters: 'a' .. 'z'</li>
+ * <li>Digits: '0'..'9'</li>
+ * <li>Space</li>
+ * <li>Apostrophe: '\''</li>
+ * <li>Left parenthesis: '('</li>
+ * <li>Right parenthesis: ')'</li>
+ * <li>Plus sign: '+'</li>
+ * <li>Comma: ','</li>
+ * <li>Hyphen-minus: '-'</li>
+ * <li>Full stop: '.'</li>
+ * <li>Solidus: '/'</li>
+ * <li>Colon: ':'</li>
+ * <li>Equals sign: '='</li>
+ * <li>Question mark: '?'</li>
+ * </ul>
+ * <p>
+ * Explicit character set escape sequences are not allowed.
+ * </p>
*/
public class DERPrintableString
extends ASN1Primitive
@@ -15,7 +38,7 @@ public class DERPrintableString
private final byte[] string;
/**
- * return a printable string from the passed in object.
+ * 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.
@@ -45,7 +68,7 @@ public class DERPrintableString
}
/**
- * return a Printable String from a tagged object.
+ * Return a Printable String from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
@@ -71,7 +94,7 @@ public class DERPrintableString
}
/**
- * basic constructor - byte encoded string.
+ * Basic constructor - byte encoded string.
*/
DERPrintableString(
byte[] string)
@@ -80,7 +103,7 @@ public class DERPrintableString
}
/**
- * basic constructor - this does not validate the string
+ * Basic constructor - this does not validate the string
*/
public DERPrintableString(
String string)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERSequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERSequence.java
index b631064d..8efbbab5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERSequence.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERSequence.java
@@ -3,20 +3,26 @@ package org.bouncycastle.asn1;
import java.io.IOException;
import java.util.Enumeration;
+/**
+ * Definite length SEQUENCE, encoding tells explicit number of bytes
+ * that the content of this sequence occupies.
+ * <p>
+ * For X.690 syntax rules, see {@link ASN1Sequence}.
+ */
public class DERSequence
extends ASN1Sequence
{
private int bodyLength = -1;
/**
- * create an empty sequence
+ * Create an empty sequence
*/
public DERSequence()
{
}
/**
- * create a sequence containing one object
+ * Create a sequence containing one object
* @param obj the object to go in the sequence.
*/
public DERSequence(
@@ -26,7 +32,7 @@ public class DERSequence
}
/**
- * create a sequence containing a vector of objects.
+ * Create a sequence containing a vector of objects.
* @param v the vector of objects to make up the sequence.
*/
public DERSequence(
@@ -36,7 +42,7 @@ public class DERSequence
}
/**
- * create a sequence containing an array of objects.
+ * Create a sequence containing an array of objects.
* @param array the array of objects to make up the sequence.
*/
public DERSequence(
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java
index 1a72a0b1..99d10d8e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java
@@ -5,6 +5,13 @@ import java.util.Enumeration;
/**
* A DER encoded SET object
+ * <p>
+ * For X.690 syntax rules, see {@link ASN1Set}.
+ * </p><p>
+ * For short: Constructing this form does sort the supplied elements,
+ * and the sorting happens also before serialization (if necesssary).
+ * This is different from the way {@link BERSet},{@link DLSet} does things.
+ * </p>
*/
public class DERSet
extends ASN1Set
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java
index c5c29137..289bfc8c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java
@@ -16,7 +16,7 @@ public class DERT61String
private byte[] string;
/**
- * return a T61 string from the passed in object.
+ * 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.
@@ -46,7 +46,7 @@ public class DERT61String
}
/**
- * return an T61 String from a tagged object.
+ * Return an T61 String from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
@@ -72,7 +72,7 @@ public class DERT61String
}
/**
- * basic constructor - string encoded as a sequence of bytes.
+ * Basic constructor - string encoded as a sequence of bytes.
*
* @param string the byte encoding of the string to be wrapped.
*/
@@ -83,7 +83,7 @@ public class DERT61String
}
/**
- * basic constructor - with string 8 bit assumed.
+ * Basic constructor - with string 8 bit assumed.
*
* @param string the string to be wrapped.
*/
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java
index 6b70faab..487f86d9 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java
@@ -6,7 +6,8 @@ import java.io.IOException;
import org.bouncycastle.util.Arrays;
/**
- * DER UniversalString object.
+ * DER UniversalString object - encodes UNICODE (ISO 10646) characters using 32-bit format. In Java we
+ * have no way of representing this directly so we rely on byte arrays to carry these.
*/
public class DERUniversalString
extends ASN1Primitive
@@ -16,7 +17,7 @@ public class DERUniversalString
private final byte[] string;
/**
- * return a Universal String from the passed in object.
+ * 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.
@@ -46,7 +47,7 @@ public class DERUniversalString
}
/**
- * return a Universal String from a tagged object.
+ * Return a Universal String from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
@@ -72,7 +73,7 @@ public class DERUniversalString
}
/**
- * basic constructor - byte encoded string.
+ * Basic constructor - byte encoded string.
*
* @param string the byte encoding of the string to be carried in the UniversalString object,
*/
@@ -94,7 +95,7 @@ public class DERUniversalString
}
catch (IOException e)
{
- throw new ASN1ParsingException("internal error encoding BitString");
+ throw new ASN1ParsingException("internal error encoding UniversalString");
}
byte[] string = bOut.toByteArray();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLApplicationSpecific.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLApplicationSpecific.java
new file mode 100644
index 00000000..8369492a
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLApplicationSpecific.java
@@ -0,0 +1,124 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * A DER encoding version of an application specific object.
+ */
+public class DLApplicationSpecific
+ extends ASN1ApplicationSpecific
+{
+ DLApplicationSpecific(
+ boolean isConstructed,
+ int tag,
+ byte[] octets)
+ {
+ super(isConstructed, tag, octets);
+ }
+
+ /**
+ * Create an application specific object from the passed in data. This will assume
+ * the data does not represent a constructed object.
+ *
+ * @param tag the tag number for this object.
+ * @param octets the encoding of the object's body.
+ */
+ public DLApplicationSpecific(
+ int tag,
+ byte[] octets)
+ {
+ this(false, tag, octets);
+ }
+
+ /**
+ * Create an application specific object with a tagging of explicit/constructed.
+ *
+ * @param tag the tag number for this object.
+ * @param object the object to be contained.
+ */
+ public DLApplicationSpecific(
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ this(true, tag, object);
+ }
+
+ /**
+ * Create an application specific object with the tagging style given by the value of constructed.
+ *
+ * @param constructed true if the object is constructed.
+ * @param tag the tag number for this object.
+ * @param object the object to be contained.
+ */
+ public DLApplicationSpecific(
+ boolean constructed,
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ super(constructed || object.toASN1Primitive().isConstructed(), tag, getEncoding(constructed, object));
+ }
+
+ private static byte[] getEncoding(boolean explicit, ASN1Encodable object)
+ throws IOException
+ {
+ byte[] data = object.toASN1Primitive().getEncoded(ASN1Encoding.DL);
+
+ if (explicit)
+ {
+ return data;
+ }
+ else
+ {
+ int lenBytes = getLengthOfHeader(data);
+ byte[] tmp = new byte[data.length - lenBytes];
+ System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
+ return tmp;
+ }
+ }
+
+ /**
+ * Create an application specific object which is marked as constructed
+ *
+ * @param tagNo the tag number for this object.
+ * @param vec the objects making up the application specific object.
+ */
+ public DLApplicationSpecific(int tagNo, ASN1EncodableVector vec)
+ {
+ super(true, tagNo, getEncodedVector(vec));
+ }
+
+ private static byte[] getEncodedVector(ASN1EncodableVector vec)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != vec.size(); i++)
+ {
+ try
+ {
+ bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DL));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("malformed object: " + e, e);
+ }
+ }
+ return bOut.toByteArray();
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream)
+ */
+ void encode(ASN1OutputStream out) throws IOException
+ {
+ int classBits = BERTags.APPLICATION;
+ if (isConstructed)
+ {
+ classBits |= BERTags.CONSTRUCTED;
+ }
+
+ out.writeEncoded(classBits, tag, octets);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java
index f6cb49bd..a5d9cbb6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java
@@ -124,7 +124,7 @@ public class DLBitString
}
void encode(
- ASN1OutputStream out)
+ ASN1OutputStream out)
throws IOException
{
byte[] string = data;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLExternal.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLExternal.java
new file mode 100644
index 00000000..e3df2506
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLExternal.java
@@ -0,0 +1,85 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Class representing the Definite-Length-type External
+ */
+public class DLExternal
+ extends ASN1External
+{
+ /**
+ * Construct a Definite-Length EXTERNAL object, the input encoding vector must have exactly two elements on it.
+ * <p>
+ * Acceptable input formats are:
+ * <ul>
+ * <li> {@link ASN1ObjectIdentifier} + data {@link DERTaggedObject} (direct reference form)</li>
+ * <li> {@link ASN1Integer} + data {@link DERTaggedObject} (indirect reference form)</li>
+ * <li> Anything but {@link DERTaggedObject} + data {@link DERTaggedObject} (data value form)</li>
+ * </ul>
+ *
+ * @throws IllegalArgumentException if input size is wrong, or
+ */
+ public DLExternal(ASN1EncodableVector vector)
+ {
+ super(vector);
+ }
+
+ /**
+ * Creates a new instance of DERExternal
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or <code>null</code> if not set.
+ * @param indirectReference The indirect reference or <code>null</code> if not set.
+ * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+ * @param externalData The external data in its encoded form.
+ */
+ public DLExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData)
+ {
+ this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive());
+ }
+
+ /**
+ * Creates a new instance of Definite-Length External.
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or <code>null</code> if not set.
+ * @param indirectReference The indirect reference or <code>null</code> if not set.
+ * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+ * @param encoding The encoding to be used for the external data
+ * @param externalData The external data
+ */
+ public DLExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData)
+ {
+ super(directReference, indirectReference, dataValueDescriptor, encoding, externalData);
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return this.getEncoded().length;
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream)
+ */
+ void encode(ASN1OutputStream out)
+ throws IOException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ if (directReference != null)
+ {
+ baos.write(directReference.getEncoded(ASN1Encoding.DL));
+ }
+ if (indirectReference != null)
+ {
+ baos.write(indirectReference.getEncoded(ASN1Encoding.DL));
+ }
+ if (dataValueDescriptor != null)
+ {
+ baos.write(dataValueDescriptor.getEncoded(ASN1Encoding.DL));
+ }
+ DERTaggedObject obj = new DERTaggedObject(true, encoding, externalContent);
+ baos.write(obj.getEncoded(ASN1Encoding.DL));
+ out.writeEncoded(BERTags.CONSTRUCTED, BERTags.EXTERNAL, baos.toByteArray());
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DateUtil.java b/bcprov/src/main/java/org/bouncycastle/asn1/DateUtil.java
new file mode 100644
index 00000000..83d8bb2d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DateUtil.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.asn1;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+class DateUtil
+{
+ private static Long ZERO = longValueOf(0);
+
+ private static final Map localeCache = new HashMap();
+
+ static Locale EN_Locale = forEN();
+
+ private static Locale forEN()
+ {
+ if ("en".equalsIgnoreCase(Locale.getDefault().getLanguage()))
+ {
+ return Locale.getDefault();
+ }
+
+ Locale[] locales = Locale.getAvailableLocales();
+ for (int i = 0; i != locales.length; i++)
+ {
+ if ("en".equalsIgnoreCase(locales[i].getLanguage()))
+ {
+ return locales[i];
+ }
+ }
+
+ return Locale.getDefault();
+ }
+
+ static Date epochAdjust(Date date)
+ throws ParseException
+ {
+ Locale locale = Locale.getDefault();
+ if (locale == null)
+ {
+ return date;
+ }
+
+ synchronized (localeCache)
+ {
+ Long adj = (Long)localeCache.get(locale);
+
+ if (adj == null)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ long v = dateF.parse("19700101000000GMT+00:00").getTime();
+
+ if (v == 0)
+ {
+ adj = ZERO;
+ }
+ else
+ {
+ adj = longValueOf(v);
+ }
+
+ localeCache.put(locale, adj);
+ }
+
+ if (adj != ZERO)
+ {
+ return new Date(date.getTime() - adj.longValue());
+ }
+
+ return date;
+ }
+ }
+
+ private static Long longValueOf(long v)
+ {
+ return Long.valueOf(v);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java b/bcprov/src/main/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java
index 37851748..d7b51ded 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java
@@ -6,6 +6,9 @@ import java.io.InputStream;
import org.bouncycastle.util.io.Streams;
+/**
+ * Parse data stream of expected ASN.1 data expecting definite-length encoding..
+ */
class DefiniteLengthInputStream
extends LimitedInputStream
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/LimitedInputStream.java b/bcprov/src/main/java/org/bouncycastle/asn1/LimitedInputStream.java
index d94b0bd8..ab8470f8 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/LimitedInputStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/LimitedInputStream.java
@@ -2,6 +2,9 @@ package org.bouncycastle.asn1;
import java.io.InputStream;
+/**
+ * Internal use stream that allows reading of a limited number of bytes from a wrapped stream.
+ */
abstract class LimitedInputStream
extends InputStream
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
index f43f9fb7..dae0dacc 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
@@ -83,6 +83,77 @@ public interface BCObjectIdentifiers
public static final ASN1ObjectIdentifier sphincs256_with_SHA3_512 = sphincs256.branch("3");
/**
+ * XMSS
+ */
+ public static final ASN1ObjectIdentifier xmss = bc_sig.branch("2");
+ public static final ASN1ObjectIdentifier xmss_SHA256ph = xmss.branch("1");
+ public static final ASN1ObjectIdentifier xmss_SHA512ph = xmss.branch("2");
+ public static final ASN1ObjectIdentifier xmss_SHAKE128ph = xmss.branch("3");
+ public static final ASN1ObjectIdentifier xmss_SHAKE256ph = xmss.branch("4");
+ public static final ASN1ObjectIdentifier xmss_SHA256 = xmss.branch("5");
+ public static final ASN1ObjectIdentifier xmss_SHA512 = xmss.branch("6");
+ public static final ASN1ObjectIdentifier xmss_SHAKE128 = xmss.branch("7");
+ public static final ASN1ObjectIdentifier xmss_SHAKE256 = xmss.branch("8");
+
+ /**
+ * XMSS^MT
+ */
+ public static final ASN1ObjectIdentifier xmss_mt = bc_sig.branch("3");
+ public static final ASN1ObjectIdentifier xmss_mt_SHA256ph = xmss_mt.branch("1");
+ public static final ASN1ObjectIdentifier xmss_mt_SHA512ph = xmss_mt.branch("2");
+ public static final ASN1ObjectIdentifier xmss_mt_SHAKE128ph = xmss_mt.branch("3");
+ public static final ASN1ObjectIdentifier xmss_mt_SHAKE256ph = xmss_mt.branch("4");
+ public static final ASN1ObjectIdentifier xmss_mt_SHA256 = xmss_mt.branch("5");
+ public static final ASN1ObjectIdentifier xmss_mt_SHA512 = xmss_mt.branch("6");
+ public static final ASN1ObjectIdentifier xmss_mt_SHAKE128 = xmss_mt.branch("7");
+ public static final ASN1ObjectIdentifier xmss_mt_SHAKE256 = xmss_mt.branch("8");
+
+ // old OIDs.
+ /**
+ * @deprecated use xmss_SHA256ph
+ */
+ public static final ASN1ObjectIdentifier xmss_with_SHA256 = xmss_SHA256ph;
+ /**
+ * @deprecated use xmss_SHA512ph
+ */
+ public static final ASN1ObjectIdentifier xmss_with_SHA512 = xmss_SHA512ph;
+ /**
+ * @deprecated use xmss_SHAKE128ph
+ */
+ public static final ASN1ObjectIdentifier xmss_with_SHAKE128 = xmss_SHAKE128ph;
+ /**
+ * @deprecated use xmss_SHAKE256ph
+ */
+ public static final ASN1ObjectIdentifier xmss_with_SHAKE256 = xmss_SHAKE256ph;
+
+ /**
+ * @deprecated use xmss_mt_SHA256ph
+ */
+ public static final ASN1ObjectIdentifier xmss_mt_with_SHA256 = xmss_mt_SHA256ph;
+ /**
+ * @deprecated use xmss_mt_SHA512ph
+ */
+ public static final ASN1ObjectIdentifier xmss_mt_with_SHA512 = xmss_mt_SHA512ph;
+ /**
+ * @deprecated use xmss_mt_SHAKE128ph
+ */
+ public static final ASN1ObjectIdentifier xmss_mt_with_SHAKE128 = xmss_mt_SHAKE128;
+ /**
+ * @deprecated use xmss_mt_SHAKE256ph
+ */
+ public static final ASN1ObjectIdentifier xmss_mt_with_SHAKE256 = xmss_mt_SHAKE256;
+
+ /**
+ * qTESLA
+ */
+ public static final ASN1ObjectIdentifier qTESLA = bc_sig.branch("4");
+ public static final ASN1ObjectIdentifier qTESLA_I = qTESLA.branch("1");
+ public static final ASN1ObjectIdentifier qTESLA_III_size = qTESLA.branch("2");
+ public static final ASN1ObjectIdentifier qTESLA_III_speed = qTESLA.branch("3");
+ public static final ASN1ObjectIdentifier qTESLA_p_I = qTESLA.branch("4");
+ public static final ASN1ObjectIdentifier qTESLA_p_III = qTESLA.branch("5");
+
+ /**
* key_exchange(3) algorithms
*
public static final ASN1ObjectIdentifier bc_exch = bc.branch("3");
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
index e21c8a7b..4ffe5ea5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
@@ -4,6 +4,7 @@ import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DLSet;
/**
@@ -63,6 +64,13 @@ public class Attributes
return null;
}
+ public static Attributes getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Set.getInstance(obj, explicit));
+ }
+
public Attribute[] getAttributes()
{
Attribute[] rv = new Attribute[attributes.size()];
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
index 71c85fbe..d452ef8a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
@@ -3,6 +3,7 @@ package org.bouncycastle.asn1.cms;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
/**
* <a href="http://tools.ietf.org/html/rfc5652">RFC 5652</a> CMS attribute OID constants.
* and <a href="http://tools.ietf.org/html/rfc6211">RFC 6211</a> Algorithm Identifier Protection Attribute.
@@ -20,16 +21,16 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
public interface CMSAttributes
{
/** PKCS#9: 1.2.840.113549.1.9.3 */
- public static final ASN1ObjectIdentifier contentType = PKCSObjectIdentifiers.pkcs_9_at_contentType;
+ ASN1ObjectIdentifier contentType = PKCSObjectIdentifiers.pkcs_9_at_contentType;
/** PKCS#9: 1.2.840.113549.1.9.4 */
- public static final ASN1ObjectIdentifier messageDigest = PKCSObjectIdentifiers.pkcs_9_at_messageDigest;
+ ASN1ObjectIdentifier messageDigest = PKCSObjectIdentifiers.pkcs_9_at_messageDigest;
/** PKCS#9: 1.2.840.113549.1.9.5 */
- public static final ASN1ObjectIdentifier signingTime = PKCSObjectIdentifiers.pkcs_9_at_signingTime;
+ ASN1ObjectIdentifier signingTime = PKCSObjectIdentifiers.pkcs_9_at_signingTime;
/** PKCS#9: 1.2.840.113549.1.9.6 */
- public static final ASN1ObjectIdentifier counterSignature = PKCSObjectIdentifiers.pkcs_9_at_counterSignature;
+ ASN1ObjectIdentifier counterSignature = PKCSObjectIdentifiers.pkcs_9_at_counterSignature;
/** PKCS#9: 1.2.840.113549.1.9.16.6.2.4 - See <a href="http://tools.ietf.org/html/rfc2634">RFC 2634</a> */
- public static final ASN1ObjectIdentifier contentHint = PKCSObjectIdentifiers.id_aa_contentHint;
+ ASN1ObjectIdentifier contentHint = PKCSObjectIdentifiers.id_aa_contentHint;
- public static final ASN1ObjectIdentifier cmsAlgorithmProtect = PKCSObjectIdentifiers.id_aa_cmsAlgorithmProtect;
+ ASN1ObjectIdentifier cmsAlgorithmProtect = PKCSObjectIdentifiers.id_aa_cmsAlgorithmProtect;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/gm/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/gm/package.html
new file mode 100644
index 00000000..54a633d6
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/gm/package.html
@@ -0,0 +1,5 @@
+<html>
+<body bgcolor="#ffffff">
+Support classes for Chinese Standard (GM) standard curves and algorithms.
+</body>
+</html>
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 284751eb..0f0b10d5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
@@ -8,64 +8,98 @@ public interface MiscObjectIdentifiers
// Netscape
// iso/itu(2) joint-assign(16) us(840) uscompany(1) netscape(113730) cert-extensions(1) }
//
- /** Netscape cert extensions OID base: 2.16.840.1.113730.1 */
- static final ASN1ObjectIdentifier netscape = new ASN1ObjectIdentifier("2.16.840.1.113730.1");
- /** Netscape cert CertType OID: 2.16.840.1.113730.1.1 */
- static final ASN1ObjectIdentifier netscapeCertType = netscape.branch("1");
- /** Netscape cert BaseURL OID: 2.16.840.1.113730.1.2 */
- static final ASN1ObjectIdentifier netscapeBaseURL = netscape.branch("2");
- /** Netscape cert RevocationURL OID: 2.16.840.1.113730.1.3 */
- static final ASN1ObjectIdentifier netscapeRevocationURL = netscape.branch("3");
- /** Netscape cert CARevocationURL OID: 2.16.840.1.113730.1.4 */
- static final ASN1ObjectIdentifier netscapeCARevocationURL = netscape.branch("4");
- /** Netscape cert RenewalURL OID: 2.16.840.1.113730.1.7 */
- static final ASN1ObjectIdentifier netscapeRenewalURL = netscape.branch("7");
- /** Netscape cert CApolicyURL OID: 2.16.840.1.113730.1.8 */
- static final ASN1ObjectIdentifier netscapeCApolicyURL = netscape.branch("8");
- /** Netscape cert SSLServerName OID: 2.16.840.1.113730.1.12 */
- static final ASN1ObjectIdentifier netscapeSSLServerName = netscape.branch("12");
- /** Netscape cert CertComment OID: 2.16.840.1.113730.1.13 */
- static final ASN1ObjectIdentifier netscapeCertComment = netscape.branch("13");
-
+ /**
+ * Netscape cert extensions OID base: 2.16.840.1.113730.1
+ */
+ ASN1ObjectIdentifier netscape = new ASN1ObjectIdentifier("2.16.840.1.113730.1");
+ /**
+ * Netscape cert CertType OID: 2.16.840.1.113730.1.1
+ */
+ ASN1ObjectIdentifier netscapeCertType = netscape.branch("1");
+ /**
+ * Netscape cert BaseURL OID: 2.16.840.1.113730.1.2
+ */
+ ASN1ObjectIdentifier netscapeBaseURL = netscape.branch("2");
+ /**
+ * Netscape cert RevocationURL OID: 2.16.840.1.113730.1.3
+ */
+ ASN1ObjectIdentifier netscapeRevocationURL = netscape.branch("3");
+ /**
+ * Netscape cert CARevocationURL OID: 2.16.840.1.113730.1.4
+ */
+ ASN1ObjectIdentifier netscapeCARevocationURL = netscape.branch("4");
+ /**
+ * Netscape cert RenewalURL OID: 2.16.840.1.113730.1.7
+ */
+ ASN1ObjectIdentifier netscapeRenewalURL = netscape.branch("7");
+ /**
+ * Netscape cert CApolicyURL OID: 2.16.840.1.113730.1.8
+ */
+ ASN1ObjectIdentifier netscapeCApolicyURL = netscape.branch("8");
+ /**
+ * Netscape cert SSLServerName OID: 2.16.840.1.113730.1.12
+ */
+ ASN1ObjectIdentifier netscapeSSLServerName = netscape.branch("12");
+ /**
+ * Netscape cert CertComment OID: 2.16.840.1.113730.1.13
+ */
+ ASN1ObjectIdentifier netscapeCertComment = netscape.branch("13");
+
//
// Verisign
// iso/itu(2) joint-assign(16) us(840) uscompany(1) verisign(113733) cert-extensions(1) }
//
- /** Verisign OID base: 2.16.840.1.113733.1 */
- static final ASN1ObjectIdentifier verisign = new ASN1ObjectIdentifier("2.16.840.1.113733.1");
+ /**
+ * Verisign OID base: 2.16.840.1.113733.1
+ */
+ ASN1ObjectIdentifier verisign = new ASN1ObjectIdentifier("2.16.840.1.113733.1");
- /** 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 CZAG (Country,Zip,Age,Gender) Extension OID: 2.16.840.1.113733.1.6.3
+ */
+ ASN1ObjectIdentifier verisignCzagExtension = verisign.branch("6.3");
- static final ASN1ObjectIdentifier verisignPrivate_6_9 = verisign.branch("6.9");
- static final ASN1ObjectIdentifier verisignOnSiteJurisdictionHash = verisign.branch("6.11");
- static final ASN1ObjectIdentifier verisignBitString_6_13 = verisign.branch("6.13");
+ ASN1ObjectIdentifier verisignPrivate_6_9 = verisign.branch("6.9");
+ ASN1ObjectIdentifier verisignOnSiteJurisdictionHash = verisign.branch("6.11");
+ ASN1ObjectIdentifier verisignBitString_6_13 = verisign.branch("6.13");
- /** 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");
+ /**
+ * Verisign D&amp;B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15
+ */
+ ASN1ObjectIdentifier verisignDnbDunsNumber = verisign.branch("6.15");
- static final ASN1ObjectIdentifier verisignIssStrongCrypto = verisign.branch("8.1");
+ ASN1ObjectIdentifier verisignIssStrongCrypto = verisign.branch("8.1");
//
// Novell
// iso/itu(2) country(16) us(840) organization(1) novell(113719)
//
- /** Novell OID base: 2.16.840.1.113719 */
- static final ASN1ObjectIdentifier novell = new ASN1ObjectIdentifier("2.16.840.1.113719");
- /** Novell SecurityAttribs OID: 2.16.840.1.113719.1.9.4.1 */
- static final ASN1ObjectIdentifier novellSecurityAttribs = novell.branch("1.9.4.1");
+ /**
+ * Novell OID base: 2.16.840.1.113719
+ */
+ ASN1ObjectIdentifier novell = new ASN1ObjectIdentifier("2.16.840.1.113719");
+ /**
+ * Novell SecurityAttribs OID: 2.16.840.1.113719.1.9.4.1
+ */
+ ASN1ObjectIdentifier novellSecurityAttribs = novell.branch("1.9.4.1");
//
// Entrust
// iso(1) member-body(16) us(840) nortelnetworks(113533) entrust(7)
//
- /** NortelNetworks Entrust OID base: 1.2.840.113533.7 */
- static final ASN1ObjectIdentifier entrust = new ASN1ObjectIdentifier("1.2.840.113533.7");
- /** NortelNetworks Entrust VersionExtension OID: 1.2.840.113533.7.65.0 */
- static final ASN1ObjectIdentifier entrustVersionExtension = entrust.branch("65.0");
+ /**
+ * NortelNetworks Entrust OID base: 1.2.840.113533.7
+ */
+ ASN1ObjectIdentifier entrust = new ASN1ObjectIdentifier("1.2.840.113533.7");
+ /**
+ * NortelNetworks Entrust VersionExtension OID: 1.2.840.113533.7.65.0
+ */
+ ASN1ObjectIdentifier entrustVersionExtension = entrust.branch("65.0");
- /** cast5CBC OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) nt(113533) nsn(7) algorithms(66) 10} SEE RFC 2984 */
- ASN1ObjectIdentifier cast5CBC = entrust.branch("66.10");
+ /**
+ * cast5CBC OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) nt(113533) nsn(7) algorithms(66) 10} SEE RFC 2984
+ */
+ ASN1ObjectIdentifier cast5CBC = entrust.branch("66.10");
//
// Ascom
@@ -92,4 +126,13 @@ public interface MiscObjectIdentifiers
ASN1ObjectIdentifier id_blake2b256 = blake2.branch("1.8");
ASN1ObjectIdentifier id_blake2b384 = blake2.branch("1.12");
ASN1ObjectIdentifier id_blake2b512 = blake2.branch("1.16");
+
+ ASN1ObjectIdentifier id_blake2s128 = blake2.branch("2.4");
+ ASN1ObjectIdentifier id_blake2s160 = blake2.branch("2.5");
+ ASN1ObjectIdentifier id_blake2s224 = blake2.branch("2.7");
+ ASN1ObjectIdentifier id_blake2s256 = blake2.branch("2.8");
+
+ //
+ // Scrypt
+ ASN1ObjectIdentifier id_scrypt = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.4.11");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nsri/NSRIObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/nsri/NSRIObjectIdentifiers.java
index 4ef8148a..c687f3c5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/nsri/NSRIObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/nsri/NSRIObjectIdentifiers.java
@@ -4,55 +4,55 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
public interface NSRIObjectIdentifiers
{
- static final ASN1ObjectIdentifier nsri = new ASN1ObjectIdentifier("1.2.410.200046");
+ ASN1ObjectIdentifier nsri = new ASN1ObjectIdentifier("1.2.410.200046");
- static final ASN1ObjectIdentifier id_algorithm = nsri.branch("1");
+ ASN1ObjectIdentifier id_algorithm = nsri.branch("1");
- static final ASN1ObjectIdentifier id_sea = id_algorithm.branch("1");
- static final ASN1ObjectIdentifier id_pad = id_algorithm.branch("2");
+ ASN1ObjectIdentifier id_sea = id_algorithm.branch("1");
+ ASN1ObjectIdentifier id_pad = id_algorithm.branch("2");
- static final ASN1ObjectIdentifier id_pad_null = id_algorithm.branch("0");
- static final ASN1ObjectIdentifier id_pad_1 = id_algorithm.branch("1");
+ ASN1ObjectIdentifier id_pad_null = id_algorithm.branch("0");
+ ASN1ObjectIdentifier id_pad_1 = id_algorithm.branch("1");
- static final ASN1ObjectIdentifier id_aria128_ecb = id_sea.branch("1");
- static final ASN1ObjectIdentifier id_aria128_cbc = id_sea.branch("2");
- static final ASN1ObjectIdentifier id_aria128_cfb = id_sea.branch("3");
- static final ASN1ObjectIdentifier id_aria128_ofb = id_sea.branch("4");
- static final ASN1ObjectIdentifier id_aria128_ctr = id_sea.branch("5");
+ ASN1ObjectIdentifier id_aria128_ecb = id_sea.branch("1");
+ ASN1ObjectIdentifier id_aria128_cbc = id_sea.branch("2");
+ ASN1ObjectIdentifier id_aria128_cfb = id_sea.branch("3");
+ ASN1ObjectIdentifier id_aria128_ofb = id_sea.branch("4");
+ ASN1ObjectIdentifier id_aria128_ctr = id_sea.branch("5");
- static final ASN1ObjectIdentifier id_aria192_ecb = id_sea.branch("6");
- static final ASN1ObjectIdentifier id_aria192_cbc = id_sea.branch("7");
- static final ASN1ObjectIdentifier id_aria192_cfb = id_sea.branch("8");
- static final ASN1ObjectIdentifier id_aria192_ofb = id_sea.branch("9");
- static final ASN1ObjectIdentifier id_aria192_ctr = id_sea.branch("10");
+ ASN1ObjectIdentifier id_aria192_ecb = id_sea.branch("6");
+ ASN1ObjectIdentifier id_aria192_cbc = id_sea.branch("7");
+ ASN1ObjectIdentifier id_aria192_cfb = id_sea.branch("8");
+ ASN1ObjectIdentifier id_aria192_ofb = id_sea.branch("9");
+ ASN1ObjectIdentifier id_aria192_ctr = id_sea.branch("10");
- static final ASN1ObjectIdentifier id_aria256_ecb = id_sea.branch("11");
- static final ASN1ObjectIdentifier id_aria256_cbc = id_sea.branch("12");
- static final ASN1ObjectIdentifier id_aria256_cfb = id_sea.branch("13");
- static final ASN1ObjectIdentifier id_aria256_ofb = id_sea.branch("14");
- static final ASN1ObjectIdentifier id_aria256_ctr = id_sea.branch("15");
+ ASN1ObjectIdentifier id_aria256_ecb = id_sea.branch("11");
+ ASN1ObjectIdentifier id_aria256_cbc = id_sea.branch("12");
+ ASN1ObjectIdentifier id_aria256_cfb = id_sea.branch("13");
+ ASN1ObjectIdentifier id_aria256_ofb = id_sea.branch("14");
+ ASN1ObjectIdentifier id_aria256_ctr = id_sea.branch("15");
- static final ASN1ObjectIdentifier id_aria128_cmac = id_sea.branch("21");
- static final ASN1ObjectIdentifier id_aria192_cmac = id_sea.branch("22");
- static final ASN1ObjectIdentifier id_aria256_cmac = id_sea.branch("23");
+ ASN1ObjectIdentifier id_aria128_cmac = id_sea.branch("21");
+ ASN1ObjectIdentifier id_aria192_cmac = id_sea.branch("22");
+ ASN1ObjectIdentifier id_aria256_cmac = id_sea.branch("23");
- static final ASN1ObjectIdentifier id_aria128_ocb2 = id_sea.branch("31");
- static final ASN1ObjectIdentifier id_aria192_ocb2 = id_sea.branch("32");
- static final ASN1ObjectIdentifier id_aria256_ocb2 = id_sea.branch("33");
+ ASN1ObjectIdentifier id_aria128_ocb2 = id_sea.branch("31");
+ ASN1ObjectIdentifier id_aria192_ocb2 = id_sea.branch("32");
+ ASN1ObjectIdentifier id_aria256_ocb2 = id_sea.branch("33");
- static final ASN1ObjectIdentifier id_aria128_gcm = id_sea.branch("34");
- static final ASN1ObjectIdentifier id_aria192_gcm = id_sea.branch("35");
- static final ASN1ObjectIdentifier id_aria256_gcm = id_sea.branch("36");
+ ASN1ObjectIdentifier id_aria128_gcm = id_sea.branch("34");
+ ASN1ObjectIdentifier id_aria192_gcm = id_sea.branch("35");
+ ASN1ObjectIdentifier id_aria256_gcm = id_sea.branch("36");
- static final ASN1ObjectIdentifier id_aria128_ccm = id_sea.branch("37");
- static final ASN1ObjectIdentifier id_aria192_ccm = id_sea.branch("38");
- static final ASN1ObjectIdentifier id_aria256_ccm = id_sea.branch("39");
+ ASN1ObjectIdentifier id_aria128_ccm = id_sea.branch("37");
+ ASN1ObjectIdentifier id_aria192_ccm = id_sea.branch("38");
+ ASN1ObjectIdentifier id_aria256_ccm = id_sea.branch("39");
- static final ASN1ObjectIdentifier id_aria128_kw = id_sea.branch("40");
- static final ASN1ObjectIdentifier id_aria192_kw = id_sea.branch("41");
- static final ASN1ObjectIdentifier id_aria256_kw = id_sea.branch("42");
+ ASN1ObjectIdentifier id_aria128_kw = id_sea.branch("40");
+ ASN1ObjectIdentifier id_aria192_kw = id_sea.branch("41");
+ ASN1ObjectIdentifier id_aria256_kw = id_sea.branch("42");
- static final ASN1ObjectIdentifier id_aria128_kwp = id_sea.branch("43");
- static final ASN1ObjectIdentifier id_aria192_kwp = id_sea.branch("44");
- static final ASN1ObjectIdentifier id_aria256_kwp = id_sea.branch("45");
+ ASN1ObjectIdentifier id_aria128_kwp = id_sea.branch("43");
+ ASN1ObjectIdentifier id_aria192_kwp = id_sea.branch("44");
+ ASN1ObjectIdentifier id_aria256_kwp = id_sea.branch("45");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nsri/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/nsri/package.html
new file mode 100644
index 00000000..bd43ca00
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/nsri/package.html
@@ -0,0 +1,5 @@
+<html>
+<body bgcolor="#ffffff">
+Support classes algorithms from the Korean National Security Research Institute.
+</body>
+</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java b/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java
index 0b1db325..e471149a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java
@@ -13,7 +13,7 @@ public class CertStatus
implements ASN1Choice
{
private int tagNo;
- private ASN1Encodable value;
+ private ASN1Encodable value;
/**
* create a CertStatus object with a tag of zero.
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
index ea4779bb..b7cae332 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
@@ -45,12 +45,21 @@ public class AuthenticatedSafe
public AuthenticatedSafe(
ContentInfo[] info)
{
- this.info = info;
+ this.info = copy(info);
}
public ContentInfo[] getContentInfo()
{
- return info;
+ return copy(info);
+ }
+
+ private ContentInfo[] copy(ContentInfo[] infos)
+ {
+ ContentInfo[] tmp = new ContentInfo[infos.length];
+
+ System.arraycopy(infos, 0, tmp, 0, tmp.length);
+
+ return tmp;
}
public ASN1Primitive toASN1Primitive()
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedData.java
index e0f5efdf..7a250eaa 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptedData.java
@@ -35,8 +35,6 @@ public class EncryptedData
extends ASN1Object
{
ASN1Sequence data;
- ASN1ObjectIdentifier bagId;
- ASN1Primitive bagValue;
public static EncryptedData getInstance(
Object obj)
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 848f4fcf..eeaa48d9 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
@@ -13,6 +13,12 @@ public class EncryptionScheme
private AlgorithmIdentifier algId;
public EncryptionScheme(
+ ASN1ObjectIdentifier objectId)
+ {
+ this.algId = new AlgorithmIdentifier(objectId);
+ }
+
+ public EncryptionScheme(
ASN1ObjectIdentifier objectId,
ASN1Encodable parameters)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java
index 63fa2e4e..593373f5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java
@@ -42,11 +42,11 @@ public class MacData
{
this.digInfo = DigestInfo.getInstance(seq.getObjectAt(0));
- this.salt = Arrays.clone(((ASN1OctetString)seq.getObjectAt(1)).getOctets());
+ this.salt = Arrays.clone(ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets());
if (seq.size() == 3)
{
- this.iterationCount = ((ASN1Integer)seq.getObjectAt(2)).getValue();
+ this.iterationCount = ASN1Integer.getInstance(seq.getObjectAt(2)).getValue();
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
index 48d03209..d245b9bb 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
@@ -10,39 +10,39 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
public interface PKCSObjectIdentifiers
{
/** PKCS#1: 1.2.840.113549.1.1 */
- static final ASN1ObjectIdentifier pkcs_1 = new ASN1ObjectIdentifier("1.2.840.113549.1.1");
+ ASN1ObjectIdentifier pkcs_1 = new ASN1ObjectIdentifier("1.2.840.113549.1.1");
/** PKCS#1: 1.2.840.113549.1.1.1 */
- static final ASN1ObjectIdentifier rsaEncryption = pkcs_1.branch("1");
+ ASN1ObjectIdentifier rsaEncryption = pkcs_1.branch("1");
// BEGIN Android-removed: MD2 and MD4 are unsupported
/*
/** PKCS#1: 1.2.840.113549.1.1.2 *
- static final ASN1ObjectIdentifier md2WithRSAEncryption = pkcs_1.branch("2");
+ ASN1ObjectIdentifier md2WithRSAEncryption = pkcs_1.branch("2");
/** PKCS#1: 1.2.840.113549.1.1.3 *
- static final ASN1ObjectIdentifier md4WithRSAEncryption = pkcs_1.branch("3");
+ ASN1ObjectIdentifier md4WithRSAEncryption = pkcs_1.branch("3");
*/
// END Android-removed: MD2 and MD4 are unsupported
/** PKCS#1: 1.2.840.113549.1.1.4 */
- static final ASN1ObjectIdentifier md5WithRSAEncryption = pkcs_1.branch("4");
+ ASN1ObjectIdentifier md5WithRSAEncryption = pkcs_1.branch("4");
/** PKCS#1: 1.2.840.113549.1.1.5 */
- static final ASN1ObjectIdentifier sha1WithRSAEncryption = pkcs_1.branch("5");
+ ASN1ObjectIdentifier sha1WithRSAEncryption = pkcs_1.branch("5");
/** PKCS#1: 1.2.840.113549.1.1.6 */
- static final ASN1ObjectIdentifier srsaOAEPEncryptionSET = pkcs_1.branch("6");
+ ASN1ObjectIdentifier srsaOAEPEncryptionSET = pkcs_1.branch("6");
/** PKCS#1: 1.2.840.113549.1.1.7 */
- static final ASN1ObjectIdentifier id_RSAES_OAEP = pkcs_1.branch("7");
+ ASN1ObjectIdentifier id_RSAES_OAEP = pkcs_1.branch("7");
/** PKCS#1: 1.2.840.113549.1.1.8 */
- static final ASN1ObjectIdentifier id_mgf1 = pkcs_1.branch("8");
+ ASN1ObjectIdentifier id_mgf1 = pkcs_1.branch("8");
/** PKCS#1: 1.2.840.113549.1.1.9 */
- static final ASN1ObjectIdentifier id_pSpecified = pkcs_1.branch("9");
+ ASN1ObjectIdentifier id_pSpecified = pkcs_1.branch("9");
/** PKCS#1: 1.2.840.113549.1.1.10 */
- static final ASN1ObjectIdentifier id_RSASSA_PSS = pkcs_1.branch("10");
+ ASN1ObjectIdentifier id_RSASSA_PSS = pkcs_1.branch("10");
/** PKCS#1: 1.2.840.113549.1.1.11 */
- static final ASN1ObjectIdentifier sha256WithRSAEncryption = pkcs_1.branch("11");
+ ASN1ObjectIdentifier sha256WithRSAEncryption = pkcs_1.branch("11");
/** PKCS#1: 1.2.840.113549.1.1.12 */
- static final ASN1ObjectIdentifier sha384WithRSAEncryption = pkcs_1.branch("12");
+ ASN1ObjectIdentifier sha384WithRSAEncryption = pkcs_1.branch("12");
/** PKCS#1: 1.2.840.113549.1.1.13 */
- static final ASN1ObjectIdentifier sha512WithRSAEncryption = pkcs_1.branch("13");
+ ASN1ObjectIdentifier sha512WithRSAEncryption = pkcs_1.branch("13");
/** PKCS#1: 1.2.840.113549.1.1.14 */
- static final ASN1ObjectIdentifier sha224WithRSAEncryption = pkcs_1.branch("14");
+ ASN1ObjectIdentifier sha224WithRSAEncryption = pkcs_1.branch("14");
/** PKCS#1: 1.2.840.113549.1.1.15 */
ASN1ObjectIdentifier sha512_224WithRSAEncryption = pkcs_1.branch("15");
/** PKCS#1: 1.2.840.113549.1.1.16 */
@@ -53,60 +53,60 @@ public interface PKCSObjectIdentifiers
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
//
/** PKCS#3: 1.2.840.113549.1.3 */
- static final ASN1ObjectIdentifier pkcs_3 = new ASN1ObjectIdentifier("1.2.840.113549.1.3");
+ ASN1ObjectIdentifier pkcs_3 = new ASN1ObjectIdentifier("1.2.840.113549.1.3");
/** PKCS#3: 1.2.840.113549.1.3.1 */
- static final ASN1ObjectIdentifier dhKeyAgreement = pkcs_3.branch("1");
+ ASN1ObjectIdentifier dhKeyAgreement = pkcs_3.branch("1");
//
// pkcs-5 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 }
//
/** PKCS#5: 1.2.840.113549.1.5 */
- static final ASN1ObjectIdentifier pkcs_5 = new ASN1ObjectIdentifier("1.2.840.113549.1.5");
+ ASN1ObjectIdentifier pkcs_5 = new ASN1ObjectIdentifier("1.2.840.113549.1.5");
/** PKCS#5: 1.2.840.113549.1.5.1 */
- static final ASN1ObjectIdentifier pbeWithMD2AndDES_CBC = pkcs_5.branch("1");
+ ASN1ObjectIdentifier pbeWithMD2AndDES_CBC = pkcs_5.branch("1");
/** PKCS#5: 1.2.840.113549.1.5.4 */
- static final ASN1ObjectIdentifier pbeWithMD2AndRC2_CBC = pkcs_5.branch("4");
+ ASN1ObjectIdentifier pbeWithMD2AndRC2_CBC = pkcs_5.branch("4");
/** PKCS#5: 1.2.840.113549.1.5.3 */
- static final ASN1ObjectIdentifier pbeWithMD5AndDES_CBC = pkcs_5.branch("3");
+ ASN1ObjectIdentifier pbeWithMD5AndDES_CBC = pkcs_5.branch("3");
/** PKCS#5: 1.2.840.113549.1.5.6 */
- static final ASN1ObjectIdentifier pbeWithMD5AndRC2_CBC = pkcs_5.branch("6");
+ ASN1ObjectIdentifier pbeWithMD5AndRC2_CBC = pkcs_5.branch("6");
/** PKCS#5: 1.2.840.113549.1.5.10 */
- static final ASN1ObjectIdentifier pbeWithSHA1AndDES_CBC = pkcs_5.branch("10");
+ ASN1ObjectIdentifier pbeWithSHA1AndDES_CBC = pkcs_5.branch("10");
/** PKCS#5: 1.2.840.113549.1.5.11 */
- static final ASN1ObjectIdentifier pbeWithSHA1AndRC2_CBC = pkcs_5.branch("11");
+ ASN1ObjectIdentifier pbeWithSHA1AndRC2_CBC = pkcs_5.branch("11");
/** PKCS#5: 1.2.840.113549.1.5.13 */
- static final ASN1ObjectIdentifier id_PBES2 = pkcs_5.branch("13");
+ ASN1ObjectIdentifier id_PBES2 = pkcs_5.branch("13");
/** PKCS#5: 1.2.840.113549.1.5.12 */
- static final ASN1ObjectIdentifier id_PBKDF2 = pkcs_5.branch("12");
+ ASN1ObjectIdentifier id_PBKDF2 = pkcs_5.branch("12");
//
// encryptionAlgorithm OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) 3 }
//
/** 1.2.840.113549.3 */
- static final ASN1ObjectIdentifier encryptionAlgorithm = new ASN1ObjectIdentifier("1.2.840.113549.3");
+ ASN1ObjectIdentifier encryptionAlgorithm = new ASN1ObjectIdentifier("1.2.840.113549.3");
/** 1.2.840.113549.3.7 */
- static final ASN1ObjectIdentifier des_EDE3_CBC = encryptionAlgorithm.branch("7");
+ ASN1ObjectIdentifier des_EDE3_CBC = encryptionAlgorithm.branch("7");
/** 1.2.840.113549.3.2 */
- static final ASN1ObjectIdentifier RC2_CBC = encryptionAlgorithm.branch("2");
+ ASN1ObjectIdentifier RC2_CBC = encryptionAlgorithm.branch("2");
/** 1.2.840.113549.3.4 */
- static final ASN1ObjectIdentifier rc4 = encryptionAlgorithm.branch("4");
+ ASN1ObjectIdentifier rc4 = encryptionAlgorithm.branch("4");
//
// object identifiers for digests
//
/** 1.2.840.113549.2 */
- static final ASN1ObjectIdentifier digestAlgorithm = new ASN1ObjectIdentifier("1.2.840.113549.2");
+ ASN1ObjectIdentifier digestAlgorithm = new ASN1ObjectIdentifier("1.2.840.113549.2");
//
// md2 OBJECT IDENTIFIER ::=
// {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2}
//
// BEGIN android-removed
// /** 1.2.840.113549.2.2 */
- // static final ASN1ObjectIdentifier md2 = digestAlgorithm.branch("2");
+ // ASN1ObjectIdentifier md2 = digestAlgorithm.branch("2");
// END android-removed
//
@@ -115,7 +115,7 @@ public interface PKCSObjectIdentifiers
//
// BEGIN android-removed
// /** 1.2.840.113549.2.4 */
- // static final ASN1ObjectIdentifier md4 = digestAlgorithm.branch("4");
+ // ASN1ObjectIdentifier md4 = digestAlgorithm.branch("4");
// END android-removed
//
@@ -123,93 +123,93 @@ public interface PKCSObjectIdentifiers
// {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
//
/** 1.2.840.113549.2.5 */
- static final ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5");
+ ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5");
/** 1.2.840.113549.2.7 */
- static final ASN1ObjectIdentifier id_hmacWithSHA1 = digestAlgorithm.branch("7").intern();
+ ASN1ObjectIdentifier id_hmacWithSHA1 = digestAlgorithm.branch("7").intern();
/** 1.2.840.113549.2.8 */
- static final ASN1ObjectIdentifier id_hmacWithSHA224 = digestAlgorithm.branch("8").intern();
+ ASN1ObjectIdentifier id_hmacWithSHA224 = digestAlgorithm.branch("8").intern();
/** 1.2.840.113549.2.9 */
- static final ASN1ObjectIdentifier id_hmacWithSHA256 = digestAlgorithm.branch("9").intern();
+ ASN1ObjectIdentifier id_hmacWithSHA256 = digestAlgorithm.branch("9").intern();
/** 1.2.840.113549.2.10 */
- static final ASN1ObjectIdentifier id_hmacWithSHA384 = digestAlgorithm.branch("10").intern();
+ ASN1ObjectIdentifier id_hmacWithSHA384 = digestAlgorithm.branch("10").intern();
/** 1.2.840.113549.2.11 */
- static final ASN1ObjectIdentifier id_hmacWithSHA512 = digestAlgorithm.branch("11").intern();
+ ASN1ObjectIdentifier id_hmacWithSHA512 = digestAlgorithm.branch("11").intern();
//
// pkcs-7 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
//
/** pkcs#7: 1.2.840.113549.1.7 */
- static final ASN1ObjectIdentifier pkcs_7 = new ASN1ObjectIdentifier("1.2.840.113549.1.7").intern();
+ ASN1ObjectIdentifier pkcs_7 = new ASN1ObjectIdentifier("1.2.840.113549.1.7").intern();
/** PKCS#7: 1.2.840.113549.1.7.1 */
- static final ASN1ObjectIdentifier data = new ASN1ObjectIdentifier("1.2.840.113549.1.7.1").intern();
+ ASN1ObjectIdentifier data = new ASN1ObjectIdentifier("1.2.840.113549.1.7.1").intern();
/** PKCS#7: 1.2.840.113549.1.7.2 */
- static final ASN1ObjectIdentifier signedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.2").intern();
+ ASN1ObjectIdentifier signedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.2").intern();
/** PKCS#7: 1.2.840.113549.1.7.3 */
- static final ASN1ObjectIdentifier envelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.3").intern();
+ ASN1ObjectIdentifier envelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.3").intern();
/** PKCS#7: 1.2.840.113549.1.7.4 */
- static final ASN1ObjectIdentifier signedAndEnvelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.4").intern();
+ ASN1ObjectIdentifier signedAndEnvelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.4").intern();
/** PKCS#7: 1.2.840.113549.1.7.5 */
- static final ASN1ObjectIdentifier digestedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.5").intern();
+ ASN1ObjectIdentifier digestedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.5").intern();
/** PKCS#7: 1.2.840.113549.1.7.76 */
- static final ASN1ObjectIdentifier encryptedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.6").intern();
+ ASN1ObjectIdentifier encryptedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.6").intern();
//
// pkcs-9 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
//
/** PKCS#9: 1.2.840.113549.1.9 */
- static final ASN1ObjectIdentifier pkcs_9 = new ASN1ObjectIdentifier("1.2.840.113549.1.9");
+ ASN1ObjectIdentifier pkcs_9 = new ASN1ObjectIdentifier("1.2.840.113549.1.9");
/** PKCS#9: 1.2.840.113549.1.9.1 */
- static final ASN1ObjectIdentifier pkcs_9_at_emailAddress = pkcs_9.branch("1").intern();
+ ASN1ObjectIdentifier pkcs_9_at_emailAddress = pkcs_9.branch("1").intern();
/** PKCS#9: 1.2.840.113549.1.9.2 */
- static final ASN1ObjectIdentifier pkcs_9_at_unstructuredName = pkcs_9.branch("2").intern();
+ ASN1ObjectIdentifier pkcs_9_at_unstructuredName = pkcs_9.branch("2").intern();
/** PKCS#9: 1.2.840.113549.1.9.3 */
- static final ASN1ObjectIdentifier pkcs_9_at_contentType = pkcs_9.branch("3").intern();
+ ASN1ObjectIdentifier pkcs_9_at_contentType = pkcs_9.branch("3").intern();
/** PKCS#9: 1.2.840.113549.1.9.4 */
- static final ASN1ObjectIdentifier pkcs_9_at_messageDigest = pkcs_9.branch("4").intern();
+ ASN1ObjectIdentifier pkcs_9_at_messageDigest = pkcs_9.branch("4").intern();
/** PKCS#9: 1.2.840.113549.1.9.5 */
- static final ASN1ObjectIdentifier pkcs_9_at_signingTime = pkcs_9.branch("5").intern();
+ ASN1ObjectIdentifier pkcs_9_at_signingTime = pkcs_9.branch("5").intern();
/** PKCS#9: 1.2.840.113549.1.9.6 */
- static final ASN1ObjectIdentifier pkcs_9_at_counterSignature = pkcs_9.branch("6").intern();
+ ASN1ObjectIdentifier pkcs_9_at_counterSignature = pkcs_9.branch("6").intern();
/** PKCS#9: 1.2.840.113549.1.9.7 */
- static final ASN1ObjectIdentifier pkcs_9_at_challengePassword = pkcs_9.branch("7").intern();
+ ASN1ObjectIdentifier pkcs_9_at_challengePassword = pkcs_9.branch("7").intern();
/** PKCS#9: 1.2.840.113549.1.9.8 */
- static final ASN1ObjectIdentifier pkcs_9_at_unstructuredAddress = pkcs_9.branch("8").intern();
+ ASN1ObjectIdentifier pkcs_9_at_unstructuredAddress = pkcs_9.branch("8").intern();
/** PKCS#9: 1.2.840.113549.1.9.9 */
- static final ASN1ObjectIdentifier pkcs_9_at_extendedCertificateAttributes = pkcs_9.branch("9").intern();
+ ASN1ObjectIdentifier pkcs_9_at_extendedCertificateAttributes = pkcs_9.branch("9").intern();
/** PKCS#9: 1.2.840.113549.1.9.13 */
- static final ASN1ObjectIdentifier pkcs_9_at_signingDescription = pkcs_9.branch("13").intern();
+ ASN1ObjectIdentifier pkcs_9_at_signingDescription = pkcs_9.branch("13").intern();
/** PKCS#9: 1.2.840.113549.1.9.14 */
- static final ASN1ObjectIdentifier pkcs_9_at_extensionRequest = pkcs_9.branch("14").intern();
+ ASN1ObjectIdentifier pkcs_9_at_extensionRequest = pkcs_9.branch("14").intern();
/** PKCS#9: 1.2.840.113549.1.9.15 */
- static final ASN1ObjectIdentifier pkcs_9_at_smimeCapabilities = pkcs_9.branch("15").intern();
+ ASN1ObjectIdentifier pkcs_9_at_smimeCapabilities = pkcs_9.branch("15").intern();
/** PKCS#9: 1.2.840.113549.1.9.16 */
- static final ASN1ObjectIdentifier id_smime = pkcs_9.branch("16").intern();
+ ASN1ObjectIdentifier id_smime = pkcs_9.branch("16").intern();
/** PKCS#9: 1.2.840.113549.1.9.20 */
- static final ASN1ObjectIdentifier pkcs_9_at_friendlyName = pkcs_9.branch("20").intern();
+ ASN1ObjectIdentifier pkcs_9_at_friendlyName = pkcs_9.branch("20").intern();
/** PKCS#9: 1.2.840.113549.1.9.21 */
- static final ASN1ObjectIdentifier pkcs_9_at_localKeyId = pkcs_9.branch("21").intern();
+ ASN1ObjectIdentifier pkcs_9_at_localKeyId = pkcs_9.branch("21").intern();
/** PKCS#9: 1.2.840.113549.1.9.22.1
* @deprecated use x509Certificate instead */
- static final ASN1ObjectIdentifier x509certType = pkcs_9.branch("22.1");
+ ASN1ObjectIdentifier x509certType = pkcs_9.branch("22.1");
/** PKCS#9: 1.2.840.113549.1.9.22 */
- static final ASN1ObjectIdentifier certTypes = pkcs_9.branch("22");
+ ASN1ObjectIdentifier certTypes = pkcs_9.branch("22");
/** PKCS#9: 1.2.840.113549.1.9.22.1 */
- static final ASN1ObjectIdentifier x509Certificate = certTypes.branch("1").intern();
+ ASN1ObjectIdentifier x509Certificate = certTypes.branch("1").intern();
/** PKCS#9: 1.2.840.113549.1.9.22.2 */
- static final ASN1ObjectIdentifier sdsiCertificate = certTypes.branch("2").intern();
+ ASN1ObjectIdentifier sdsiCertificate = certTypes.branch("2").intern();
/** PKCS#9: 1.2.840.113549.1.9.23 */
- static final ASN1ObjectIdentifier crlTypes = pkcs_9.branch("23");
+ ASN1ObjectIdentifier crlTypes = pkcs_9.branch("23");
/** PKCS#9: 1.2.840.113549.1.9.23.1 */
- static final ASN1ObjectIdentifier x509Crl = crlTypes.branch("1").intern();
+ ASN1ObjectIdentifier x509Crl = crlTypes.branch("1").intern();
/** RFC 6211 - id-aa-cmsAlgorithmProtect OBJECT IDENTIFIER ::= {
iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
@@ -220,38 +220,38 @@ public interface PKCSObjectIdentifiers
// SMIME capability sub oids.
//
/** PKCS#9: 1.2.840.113549.1.9.15.1 -- smime capability */
- static final ASN1ObjectIdentifier preferSignedData = pkcs_9.branch("15.1");
+ ASN1ObjectIdentifier preferSignedData = pkcs_9.branch("15.1");
/** PKCS#9: 1.2.840.113549.1.9.15.2 -- smime capability */
- static final ASN1ObjectIdentifier canNotDecryptAny = pkcs_9.branch("15.2");
+ ASN1ObjectIdentifier canNotDecryptAny = pkcs_9.branch("15.2");
/** PKCS#9: 1.2.840.113549.1.9.15.3 -- smime capability */
- static final ASN1ObjectIdentifier sMIMECapabilitiesVersions = pkcs_9.branch("15.3");
+ ASN1ObjectIdentifier sMIMECapabilitiesVersions = pkcs_9.branch("15.3");
//
// id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1)}
//
/** PKCS#9: 1.2.840.113549.1.9.16.1 -- smime ct */
- static final ASN1ObjectIdentifier id_ct = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.1");
+ ASN1ObjectIdentifier id_ct = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.1");
/** PKCS#9: 1.2.840.113549.1.9.16.1.2 -- smime ct authData */
- static final ASN1ObjectIdentifier id_ct_authData = id_ct.branch("2");
+ ASN1ObjectIdentifier id_ct_authData = id_ct.branch("2");
/** PKCS#9: 1.2.840.113549.1.9.16.1.4 -- smime ct TSTInfo*/
- static final ASN1ObjectIdentifier id_ct_TSTInfo = id_ct.branch("4");
+ ASN1ObjectIdentifier id_ct_TSTInfo = id_ct.branch("4");
/** PKCS#9: 1.2.840.113549.1.9.16.1.9 -- smime ct compressedData */
- static final ASN1ObjectIdentifier id_ct_compressedData = id_ct.branch("9");
+ ASN1ObjectIdentifier id_ct_compressedData = id_ct.branch("9");
/** PKCS#9: 1.2.840.113549.1.9.16.1.23 -- smime ct authEnvelopedData */
- static final ASN1ObjectIdentifier id_ct_authEnvelopedData = id_ct.branch("23");
+ ASN1ObjectIdentifier id_ct_authEnvelopedData = id_ct.branch("23");
/** PKCS#9: 1.2.840.113549.1.9.16.1.31 -- smime ct timestampedData*/
- static final ASN1ObjectIdentifier id_ct_timestampedData = id_ct.branch("31");
+ ASN1ObjectIdentifier id_ct_timestampedData = id_ct.branch("31");
/** S/MIME: Algorithm Identifiers ; 1.2.840.113549.1.9.16.3 */
- static final ASN1ObjectIdentifier id_alg = id_smime.branch("3");
+ ASN1ObjectIdentifier id_alg = id_smime.branch("3");
/** PKCS#9: 1.2.840.113549.1.9.16.3.9 */
- static final ASN1ObjectIdentifier id_alg_PWRI_KEK = id_alg.branch("9");
+ ASN1ObjectIdentifier id_alg_PWRI_KEK = id_alg.branch("9");
/**
* <pre>
- * -- RSA-KEM Key Transport Algorithm
+ * -- RSA-KEM Key Transport Algorithm RFC 5990
*
* id-rsa-kem OID ::= {
* iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
@@ -259,114 +259,114 @@ public interface PKCSObjectIdentifiers
* }
* </pre>
*/
- static final ASN1ObjectIdentifier id_rsa_KEM = id_alg.branch("14");
+ ASN1ObjectIdentifier id_rsa_KEM = id_alg.branch("14");
//
// id-cti OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) cti(6)}
//
/** PKCS#9: 1.2.840.113549.1.9.16.6 -- smime cti */
- static final ASN1ObjectIdentifier id_cti = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.6");
+ ASN1ObjectIdentifier id_cti = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.6");
/** PKCS#9: 1.2.840.113549.1.9.16.6.1 -- smime cti proofOfOrigin */
- static final ASN1ObjectIdentifier id_cti_ets_proofOfOrigin = id_cti.branch("1");
+ ASN1ObjectIdentifier id_cti_ets_proofOfOrigin = id_cti.branch("1");
/** PKCS#9: 1.2.840.113549.1.9.16.6.2 -- smime cti proofOfReceipt*/
- static final ASN1ObjectIdentifier id_cti_ets_proofOfReceipt = id_cti.branch("2");
+ ASN1ObjectIdentifier id_cti_ets_proofOfReceipt = id_cti.branch("2");
/** PKCS#9: 1.2.840.113549.1.9.16.6.3 -- smime cti proofOfDelivery */
- static final ASN1ObjectIdentifier id_cti_ets_proofOfDelivery = id_cti.branch("3");
+ ASN1ObjectIdentifier id_cti_ets_proofOfDelivery = id_cti.branch("3");
/** PKCS#9: 1.2.840.113549.1.9.16.6.4 -- smime cti proofOfSender */
- static final ASN1ObjectIdentifier id_cti_ets_proofOfSender = id_cti.branch("4");
+ ASN1ObjectIdentifier id_cti_ets_proofOfSender = id_cti.branch("4");
/** PKCS#9: 1.2.840.113549.1.9.16.6.5 -- smime cti proofOfApproval */
- static final ASN1ObjectIdentifier id_cti_ets_proofOfApproval = id_cti.branch("5");
+ ASN1ObjectIdentifier id_cti_ets_proofOfApproval = id_cti.branch("5");
/** PKCS#9: 1.2.840.113549.1.9.16.6.6 -- smime cti proofOfCreation */
- static final ASN1ObjectIdentifier id_cti_ets_proofOfCreation = id_cti.branch("6");
+ ASN1ObjectIdentifier id_cti_ets_proofOfCreation = id_cti.branch("6");
//
// id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
//
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2 - smime attributes */
- static final ASN1ObjectIdentifier id_aa = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.2");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2 - smime attributes */
+ ASN1ObjectIdentifier id_aa = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.2");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.1 -- smime attribute receiptRequest */
- static final ASN1ObjectIdentifier id_aa_receiptRequest = id_aa.branch("1");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.1 -- smime attribute receiptRequest */
+ ASN1ObjectIdentifier id_aa_receiptRequest = id_aa.branch("1");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.4 - See <a href="http://tools.ietf.org/html/rfc2634">RFC 2634</a> */
- static final ASN1ObjectIdentifier id_aa_contentHint = id_aa.branch("4"); // See RFC 2634
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.5 */
- static final ASN1ObjectIdentifier id_aa_msgSigDigest = id_aa.branch("5");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.10 */
- static final ASN1ObjectIdentifier id_aa_contentReference = id_aa.branch("10");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.4 - See <a href="http://tools.ietf.org/html/rfc2634">RFC 2634</a> */
+ ASN1ObjectIdentifier id_aa_contentHint = id_aa.branch("4"); // See RFC 2634
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.5 */
+ ASN1ObjectIdentifier id_aa_msgSigDigest = id_aa.branch("5");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.10 */
+ ASN1ObjectIdentifier id_aa_contentReference = id_aa.branch("10");
/*
* id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
*
*/
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.11 */
- static final ASN1ObjectIdentifier id_aa_encrypKeyPref = id_aa.branch("11");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.12 */
- static final ASN1ObjectIdentifier id_aa_signingCertificate = id_aa.branch("12");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.47 */
- static final ASN1ObjectIdentifier id_aa_signingCertificateV2 = id_aa.branch("47");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.11 */
+ ASN1ObjectIdentifier id_aa_encrypKeyPref = id_aa.branch("11");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.12 */
+ ASN1ObjectIdentifier id_aa_signingCertificate = id_aa.branch("12");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.47 */
+ ASN1ObjectIdentifier id_aa_signingCertificateV2 = id_aa.branch("47");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.7 - See <a href="http://tools.ietf.org/html/rfc2634">RFC 2634</a> */
- static final ASN1ObjectIdentifier id_aa_contentIdentifier = id_aa.branch("7"); // See RFC 2634
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.7 - See <a href="http://tools.ietf.org/html/rfc2634">RFC 2634</a> */
+ ASN1ObjectIdentifier id_aa_contentIdentifier = id_aa.branch("7"); // See RFC 2634
/*
* RFC 3126
*/
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.14 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_signatureTimeStampToken = id_aa.branch("14");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.14 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_signatureTimeStampToken = id_aa.branch("14");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.15 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_sigPolicyId = id_aa.branch("15");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.16 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_commitmentType = id_aa.branch("16");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.17 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_signerLocation = id_aa.branch("17");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.18 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_signerAttr = id_aa.branch("18");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.15 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_sigPolicyId = id_aa.branch("15");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.16 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_commitmentType = id_aa.branch("16");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.17 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_signerLocation = id_aa.branch("17");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.18 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_signerAttr = id_aa.branch("18");
/** PKCS#9: 1.2.840.113549.1.9.16.6.2.19 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_otherSigCert = id_aa.branch("19");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.20 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_contentTimestamp = id_aa.branch("20");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.21 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_certificateRefs = id_aa.branch("21");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.22 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_revocationRefs = id_aa.branch("22");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.23 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_certValues = id_aa.branch("23");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.24 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_revocationValues = id_aa.branch("24");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.25 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_escTimeStamp = id_aa.branch("25");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.26 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_certCRLTimestamp = id_aa.branch("26");
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.27 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
- static final ASN1ObjectIdentifier id_aa_ets_archiveTimestamp = id_aa.branch("27");
-
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.37 - <a href="https://tools.ietf.org/html/rfc4108#section-2.2.5">RFC 4108</a> */
- static final ASN1ObjectIdentifier id_aa_decryptKeyID = id_aa.branch("37");
-
- /** PKCS#9: 1.2.840.113549.1.9.16.6.2.38 - <a href="https://tools.ietf.org/html/rfc4108#section-2.2.6">RFC 4108</a> */
- static final ASN1ObjectIdentifier id_aa_implCryptoAlgs = id_aa.branch("38");
+ ASN1ObjectIdentifier id_aa_ets_otherSigCert = id_aa.branch("19");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.20 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_contentTimestamp = id_aa.branch("20");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.21 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_certificateRefs = id_aa.branch("21");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.22 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_revocationRefs = id_aa.branch("22");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.23 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_certValues = id_aa.branch("23");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.24 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_revocationValues = id_aa.branch("24");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.25 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_escTimeStamp = id_aa.branch("25");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.26 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_certCRLTimestamp = id_aa.branch("26");
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.27 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */
+ ASN1ObjectIdentifier id_aa_ets_archiveTimestamp = id_aa.branch("27");
+
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.37 - <a href="https://tools.ietf.org/html/rfc4108#section-2.2.5">RFC 4108</a> */
+ ASN1ObjectIdentifier id_aa_decryptKeyID = id_aa.branch("37");
+
+ /** PKCS#9: 1.2.840.113549.1.9.16.2.38 - <a href="https://tools.ietf.org/html/rfc4108#section-2.2.6">RFC 4108</a> */
+ ASN1ObjectIdentifier id_aa_implCryptoAlgs = id_aa.branch("38");
/** PKCS#9: 1.2.840.113549.1.9.16.2.54 <a href="https://tools.ietf.org/html/rfc7030">RFC7030</a>*/
- static final ASN1ObjectIdentifier id_aa_asymmDecryptKeyID = id_aa.branch("54");
+ ASN1ObjectIdentifier id_aa_asymmDecryptKeyID = id_aa.branch("54");
/** PKCS#9: 1.2.840.113549.1.9.16.2.43 <a href="https://tools.ietf.org/html/rfc7030">RFC7030</a>*/
- static final ASN1ObjectIdentifier id_aa_implCompressAlgs = id_aa.branch("43");
+ ASN1ObjectIdentifier id_aa_implCompressAlgs = id_aa.branch("43");
/** PKCS#9: 1.2.840.113549.1.9.16.2.40 <a href="https://tools.ietf.org/html/rfc7030">RFC7030</a>*/
- static final ASN1ObjectIdentifier id_aa_communityIdentifiers = id_aa.branch("40");
+ ASN1ObjectIdentifier id_aa_communityIdentifiers = id_aa.branch("40");
/** @deprecated use id_aa_ets_sigPolicyId instead */
- static final ASN1ObjectIdentifier id_aa_sigPolicyId = id_aa_ets_sigPolicyId;
+ ASN1ObjectIdentifier id_aa_sigPolicyId = id_aa_ets_sigPolicyId;
/** @deprecated use id_aa_ets_commitmentType instead */
- static final ASN1ObjectIdentifier id_aa_commitmentType = id_aa_ets_commitmentType;
+ ASN1ObjectIdentifier id_aa_commitmentType = id_aa_ets_commitmentType;
/** @deprecated use id_aa_ets_signerLocation instead */
- static final ASN1ObjectIdentifier id_aa_signerLocation = id_aa_ets_signerLocation;
+ ASN1ObjectIdentifier id_aa_signerLocation = id_aa_ets_signerLocation;
/** @deprecated use id_aa_ets_otherSigCert instead */
- static final ASN1ObjectIdentifier id_aa_otherSigCert = id_aa_ets_otherSigCert;
+ ASN1ObjectIdentifier id_aa_otherSigCert = id_aa_ets_otherSigCert;
/**
* id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
@@ -376,61 +376,61 @@ public interface PKCSObjectIdentifiers
final String id_spq = "1.2.840.113549.1.9.16.5";
/** SMIME SPQ URI: 1.2.840.113549.1.9.16.5.1 */
- static final ASN1ObjectIdentifier id_spq_ets_uri = new ASN1ObjectIdentifier(id_spq + ".1");
+ ASN1ObjectIdentifier id_spq_ets_uri = new ASN1ObjectIdentifier(id_spq + ".1");
/** SMIME SPQ UNOTICE: 1.2.840.113549.1.9.16.5.2 */
- static final ASN1ObjectIdentifier id_spq_ets_unotice = new ASN1ObjectIdentifier(id_spq + ".2");
+ ASN1ObjectIdentifier id_spq_ets_unotice = new ASN1ObjectIdentifier(id_spq + ".2");
//
// pkcs-12 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 }
//
/** PKCS#12: 1.2.840.113549.1.12 */
- static final ASN1ObjectIdentifier pkcs_12 = new ASN1ObjectIdentifier("1.2.840.113549.1.12");
+ ASN1ObjectIdentifier pkcs_12 = new ASN1ObjectIdentifier("1.2.840.113549.1.12");
/** PKCS#12: 1.2.840.113549.1.12.10.1 */
- static final ASN1ObjectIdentifier bagtypes = pkcs_12.branch("10.1");
+ ASN1ObjectIdentifier bagtypes = pkcs_12.branch("10.1");
/** PKCS#12: 1.2.840.113549.1.12.10.1.1 */
- static final ASN1ObjectIdentifier keyBag = bagtypes.branch("1");
+ ASN1ObjectIdentifier keyBag = bagtypes.branch("1");
/** PKCS#12: 1.2.840.113549.1.12.10.1.2 */
- static final ASN1ObjectIdentifier pkcs8ShroudedKeyBag = bagtypes.branch("2");
+ ASN1ObjectIdentifier pkcs8ShroudedKeyBag = bagtypes.branch("2");
/** PKCS#12: 1.2.840.113549.1.12.10.1.3 */
- static final ASN1ObjectIdentifier certBag = bagtypes.branch("3");
+ ASN1ObjectIdentifier certBag = bagtypes.branch("3");
/** PKCS#12: 1.2.840.113549.1.12.10.1.4 */
- static final ASN1ObjectIdentifier crlBag = bagtypes.branch("4");
+ ASN1ObjectIdentifier crlBag = bagtypes.branch("4");
/** PKCS#12: 1.2.840.113549.1.12.10.1.5 */
- static final ASN1ObjectIdentifier secretBag = bagtypes.branch("5");
+ ASN1ObjectIdentifier secretBag = bagtypes.branch("5");
/** PKCS#12: 1.2.840.113549.1.12.10.1.6 */
- static final ASN1ObjectIdentifier safeContentsBag = bagtypes.branch("6");
+ ASN1ObjectIdentifier safeContentsBag = bagtypes.branch("6");
/** PKCS#12: 1.2.840.113549.1.12.1 */
- static final ASN1ObjectIdentifier pkcs_12PbeIds = pkcs_12.branch("1");
+ ASN1ObjectIdentifier pkcs_12PbeIds = pkcs_12.branch("1");
/** PKCS#12: 1.2.840.113549.1.12.1.1 */
- static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC4 = pkcs_12PbeIds.branch("1");
+ ASN1ObjectIdentifier pbeWithSHAAnd128BitRC4 = pkcs_12PbeIds.branch("1");
/** PKCS#12: 1.2.840.113549.1.12.1.2 */
- static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC4 = pkcs_12PbeIds.branch("2");
+ ASN1ObjectIdentifier pbeWithSHAAnd40BitRC4 = pkcs_12PbeIds.branch("2");
/** PKCS#12: 1.2.840.113549.1.12.1.3 */
- static final ASN1ObjectIdentifier pbeWithSHAAnd3_KeyTripleDES_CBC = pkcs_12PbeIds.branch("3");
+ ASN1ObjectIdentifier pbeWithSHAAnd3_KeyTripleDES_CBC = pkcs_12PbeIds.branch("3");
/** PKCS#12: 1.2.840.113549.1.12.1.4 */
- static final ASN1ObjectIdentifier pbeWithSHAAnd2_KeyTripleDES_CBC = pkcs_12PbeIds.branch("4");
+ ASN1ObjectIdentifier pbeWithSHAAnd2_KeyTripleDES_CBC = pkcs_12PbeIds.branch("4");
/** PKCS#12: 1.2.840.113549.1.12.1.5 */
- static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC2_CBC = pkcs_12PbeIds.branch("5");
+ ASN1ObjectIdentifier pbeWithSHAAnd128BitRC2_CBC = pkcs_12PbeIds.branch("5");
/** PKCS#12: 1.2.840.113549.1.12.1.6 */
- static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
+ ASN1ObjectIdentifier pbeWithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
/**
* PKCS#12: 1.2.840.113549.1.12.1.6
* @deprecated use pbeWithSHAAnd40BitRC2_CBC
*/
- static final ASN1ObjectIdentifier pbewithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
+ ASN1ObjectIdentifier pbewithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
/** PKCS#9: 1.2.840.113549.1.9.16.3.6 */
- static final ASN1ObjectIdentifier id_alg_CMS3DESwrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.6");
+ ASN1ObjectIdentifier id_alg_CMS3DESwrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.6");
/** PKCS#9: 1.2.840.113549.1.9.16.3.7 */
- static final ASN1ObjectIdentifier id_alg_CMSRC2wrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7");
+ ASN1ObjectIdentifier id_alg_CMSRC2wrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7");
/** PKCS#9: 1.2.840.113549.1.9.16.3.5 */
- static final ASN1ObjectIdentifier id_alg_ESDH = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.5");
+ ASN1ObjectIdentifier id_alg_ESDH = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.5");
/** PKCS#9: 1.2.840.113549.1.9.16.3.10 */
- static final ASN1ObjectIdentifier id_alg_SSDH = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.10");
+ ASN1ObjectIdentifier id_alg_SSDH = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.10");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/Pfx.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/Pfx.java
index 7885a795..ce7e0758 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/Pfx.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/Pfx.java
@@ -22,7 +22,7 @@ public class Pfx
private Pfx(
ASN1Sequence seq)
{
- BigInteger version = ((ASN1Integer)seq.getObjectAt(0)).getValue();
+ BigInteger version = ASN1Integer.getInstance(seq.getObjectAt(0)).getValue();
if (version.intValue() != 3)
{
throw new IllegalArgumentException("wrong version for PFX PDU");
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 7f02e709..85700b6a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
@@ -4,9 +4,9 @@ import java.io.IOException;
import java.math.BigInteger;
import java.util.Enumeration;
+import org.bouncycastle.asn1.ASN1BitString;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
@@ -14,27 +14,65 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
+import org.bouncycastle.util.BigIntegers;
+
+/**
+ * RFC 5958
+ *
+ * <pre>
+ * [IMPLICIT TAGS]
+ *
+ * OneAsymmetricKey ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes [0] Attributes OPTIONAL,
+ * ...,
+ * [[2: publicKey [1] PublicKey OPTIONAL ]],
+ * ...
+ * }
+ *
+ * PrivateKeyInfo ::= OneAsymmetricKey
+ *
+ * Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2)
+ *
+ * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ * { PUBLIC-KEY,
+ * { PrivateKeyAlgorithms } }
+ *
+ * PrivateKey ::= OCTET STRING
+ * -- Content varies based on type of key. The
+ * -- algorithm identifier dictates the format of
+ * -- the key.
+ *
+ * PublicKey ::= BIT STRING
+ * -- Content varies based on type of key. The
+ * -- algorithm identifier dictates the format of
+ * -- the key.
+ *
+ * Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } }
+ * </pre>
+ */
public class PrivateKeyInfo
extends ASN1Object
{
- private ASN1OctetString privKey;
- private AlgorithmIdentifier algId;
- private ASN1Set attributes;
+ private ASN1Integer version;
+ private AlgorithmIdentifier privateKeyAlgorithm;
+ private ASN1OctetString privateKey;
+ private ASN1Set attributes;
+ private ASN1BitString publicKey;
- public static PrivateKeyInfo getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
+ public static PrivateKeyInfo getInstance(ASN1TaggedObject obj, boolean explicit)
{
return getInstance(ASN1Sequence.getInstance(obj, explicit));
}
- public static PrivateKeyInfo getInstance(
- Object obj)
+ public static PrivateKeyInfo getInstance(Object obj)
{
if (obj instanceof PrivateKeyInfo)
{
@@ -47,118 +85,165 @@ public class PrivateKeyInfo
return null;
}
-
+
+ private static int getVersionValue(ASN1Integer version)
+ {
+ BigInteger bigValue = version.getValue();
+ if (bigValue.compareTo(BigIntegers.ZERO) < 0 || bigValue.compareTo(BigIntegers.ONE) > 0)
+ {
+ throw new IllegalArgumentException("invalid version for private key info");
+ }
+ return bigValue.intValue();
+ }
+
public PrivateKeyInfo(
- AlgorithmIdentifier algId,
- ASN1Encodable privateKey)
+ AlgorithmIdentifier privateKeyAlgorithm,
+ ASN1Encodable privateKey)
throws IOException
{
- this(algId, privateKey, null);
+ this(privateKeyAlgorithm, privateKey, null, null);
}
public PrivateKeyInfo(
- AlgorithmIdentifier algId,
- ASN1Encodable privateKey,
- ASN1Set attributes)
+ AlgorithmIdentifier privateKeyAlgorithm,
+ ASN1Encodable privateKey,
+ ASN1Set attributes)
throws IOException
{
- this.privKey = new DEROctetString(privateKey.toASN1Primitive().getEncoded(ASN1Encoding.DER));
- this.algId = algId;
- this.attributes = attributes;
+ this(privateKeyAlgorithm, privateKey, attributes, null);
}
- /**
- * @deprecated use PrivateKeyInfo.getInstance()
- * @param seq
- */
public PrivateKeyInfo(
- ASN1Sequence seq)
+ AlgorithmIdentifier privateKeyAlgorithm,
+ ASN1Encodable privateKey,
+ ASN1Set attributes,
+ byte[] publicKey)
+ throws IOException
+ {
+ this.version = new ASN1Integer(publicKey != null ? BigIntegers.ONE : BigIntegers.ZERO);
+ this.privateKeyAlgorithm = privateKeyAlgorithm;
+ this.privateKey = new DEROctetString(privateKey);
+ this.attributes = attributes;
+ this.publicKey = publicKey == null ? null : new DERBitString(publicKey);
+ }
+
+ private PrivateKeyInfo(ASN1Sequence seq)
{
Enumeration e = seq.getObjects();
- BigInteger version = ((ASN1Integer)e.nextElement()).getValue();
- if (version.intValue() != 0)
- {
- throw new IllegalArgumentException("wrong version for private key info");
- }
+ this.version = ASN1Integer.getInstance(e.nextElement());
+
+ int versionValue = getVersionValue(version);
- algId = AlgorithmIdentifier.getInstance(e.nextElement());
- privKey = ASN1OctetString.getInstance(e.nextElement());
-
- if (e.hasMoreElements())
+ this.privateKeyAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+ this.privateKey = ASN1OctetString.getInstance(e.nextElement());
+
+ int lastTag = -1;
+ while (e.hasMoreElements())
{
- attributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
+ ASN1TaggedObject tagged = (ASN1TaggedObject)e.nextElement();
+
+ int tag = tagged.getTagNo();
+ if (tag <= lastTag)
+ {
+ throw new IllegalArgumentException("invalid optional field in private key info");
+ }
+
+ lastTag = tag;
+
+ switch (tag)
+ {
+ case 0:
+ {
+ this.attributes = ASN1Set.getInstance(tagged, false);
+ break;
+ }
+ case 1:
+ {
+ if (versionValue < 1)
+ {
+ throw new IllegalArgumentException("'publicKey' requires version v2(1) or later");
+ }
+
+ this.publicKey = DERBitString.getInstance(tagged, false);
+ break;
+ }
+ default:
+ {
+ throw new IllegalArgumentException("unknown optional field in private key info");
+ }
+ }
}
}
- public AlgorithmIdentifier getPrivateKeyAlgorithm()
+ public ASN1Set getAttributes()
{
- return algId;
+ return attributes;
}
- /**
- * @deprecated use getPrivateKeyAlgorithm()
- */
- public AlgorithmIdentifier getAlgorithmId()
+
+ public AlgorithmIdentifier getPrivateKeyAlgorithm()
{
- return algId;
+ return privateKeyAlgorithm;
}
public ASN1Encodable parsePrivateKey()
throws IOException
{
- return ASN1Primitive.fromByteArray(privKey.getOctets());
+ return ASN1Primitive.fromByteArray(privateKey.getOctets());
}
/**
- * @deprecated use parsePrivateKey()
+ * Return true if a public key is present, false otherwise.
+ *
+ * @return true if public included, otherwise false.
*/
- public ASN1Primitive getPrivateKey()
+ public boolean hasPublicKey()
{
- try
- {
- return parsePrivateKey().toASN1Primitive();
- }
- catch (IOException e)
- {
- throw new IllegalStateException("unable to parse private key");
- }
+ return publicKey != null;
}
-
- public ASN1Set getAttributes()
+
+ /**
+ * for when the public key is an encoded object - if the bitstring
+ * can't be decoded this routine throws an IOException.
+ *
+ * @return the public key as an ASN.1 primitive.
+ * @throws IOException - if the bit string doesn't represent a DER
+ * encoded object.
+ */
+ public ASN1Encodable parsePublicKey()
+ throws IOException
{
- return attributes;
+ return publicKey == null ? null : ASN1Primitive.fromByteArray(publicKey.getOctets());
}
/**
- * write out an RSA private key with its associated information
- * as described in PKCS8.
- * <pre>
- * PrivateKeyInfo ::= SEQUENCE {
- * version Version,
- * privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
- * privateKey PrivateKey,
- * attributes [0] IMPLICIT Attributes OPTIONAL
- * }
- * Version ::= INTEGER {v1(0)} (v1,...)
+ * for when the public key is raw bits.
*
- * PrivateKey ::= OCTET STRING
- *
- * Attributes ::= SET OF Attribute
- * </pre>
+ * @return the public key as the raw bit string...
*/
+ public ASN1BitString getPublicKeyData()
+ {
+ return publicKey;
+ }
+
public ASN1Primitive toASN1Primitive()
{
ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(new ASN1Integer(0));
- v.add(algId);
- v.add(privKey);
+ v.add(version);
+ v.add(privateKeyAlgorithm);
+ v.add(privateKey);
if (attributes != null)
{
v.add(new DERTaggedObject(false, 0, attributes));
}
-
+
+ if (publicKey != null)
+ {
+ v.add(new DERTaggedObject(false, 1, publicKey));
+ }
+
return new DERSequence(v);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
index 1ddc17d0..bb215bee 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
@@ -9,6 +9,8 @@ import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
* ellipticCurve OBJECT IDENTIFIER ::= {
* iso(1) identified-organization(3) certicom(132) curve(0)
* }
+ * secg-scheme OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) schemes(1) }
* </pre>
*/
public interface SECObjectIdentifiers
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 59c961f2..f251702e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java
@@ -7,6 +7,7 @@ import org.bouncycastle.asn1.ASN1ApplicationSpecific;
import org.bouncycastle.asn1.ASN1Boolean;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Enumerated;
+import org.bouncycastle.asn1.ASN1External;
import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -25,16 +26,17 @@ import org.bouncycastle.asn1.BERTags;
import org.bouncycastle.asn1.DERApplicationSpecific;
import org.bouncycastle.asn1.DERBMPString;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERExternal;
import org.bouncycastle.asn1.DERGraphicString;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DERPrintableString;
import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.DERT61String;
import org.bouncycastle.asn1.DERUTF8String;
import org.bouncycastle.asn1.DERVideotexString;
import org.bouncycastle.asn1.DERVisibleString;
+import org.bouncycastle.asn1.DLApplicationSpecific;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;
@@ -147,11 +149,14 @@ public class ASN1Dump
{
buf.append("BER Set");
}
- else
+ else if (obj instanceof DERSet)
{
buf.append("DER Set");
}
-
+ else
+ {
+ buf.append("Set");
+ }
buf.append(nl);
while (e.hasMoreElements())
@@ -268,14 +273,18 @@ public class ASN1Dump
{
buf.append(outputApplicationSpecific("DER", indent, verbose, obj, nl));
}
+ else if (obj instanceof DLApplicationSpecific)
+ {
+ buf.append(outputApplicationSpecific("", indent, verbose, obj, nl));
+ }
else if (obj instanceof ASN1Enumerated)
{
ASN1Enumerated en = (ASN1Enumerated) obj;
buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl);
}
- else if (obj instanceof DERExternal)
+ else if (obj instanceof ASN1External)
{
- DERExternal ext = (DERExternal) obj;
+ ASN1External ext = (ASN1External) obj;
buf.append(indent + "External " + nl);
String tab = indent + TAB;
if (ext.getDirectReference() != null)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/RDN.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/RDN.java
index 6a1b318f..c84bd0e2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/RDN.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/RDN.java
@@ -108,7 +108,7 @@ public class RDN
* <pre>
* RelativeDistinguishedName ::=
* SET OF AttributeTypeAndValue
- *
+
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500Name.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500Name.java
index 67c5cd1c..bcdfa334 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500Name.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/X500Name.java
@@ -130,7 +130,7 @@ public class X500Name
X500NameStyle style,
RDN[] rDNs)
{
- this.rdns = rDNs;
+ this.rdns = copy(rDNs);
this.style = style;
}
@@ -247,6 +247,15 @@ public class X500Name
return tmp;
}
+ private RDN[] copy(RDN[] rdns)
+ {
+ RDN[] tmp = new RDN[rdns.length];
+
+ System.arraycopy(rdns, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
public ASN1Primitive toASN1Primitive()
{
return new DERSequence(rdns);
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 2ef24d36..8d2129ae 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
@@ -150,6 +150,12 @@ public class BCStyle
*/
public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
+
+ /**
+ * id-at-organizationIdentifier
+ */
+ public static final ASN1ObjectIdentifier ORGANIZATION_IDENTIFIER = X509ObjectIdentifiers.id_at_organizationIdentifier;
+
/**
* Email address (RSA PKCS#9 extension) - IA5String.
* <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
@@ -222,6 +228,7 @@ public class BCStyle
DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
DefaultSymbols.put(NAME, "Name");
+ DefaultSymbols.put(ORGANIZATION_IDENTIFIER, "organizationIdentifier");
DefaultLookUp.put("c", C);
DefaultLookUp.put("o", O);
@@ -257,6 +264,7 @@ public class BCStyle
DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
DefaultLookUp.put("name", NAME);
+ DefaultLookUp.put("organizationidentifier", ORGANIZATION_IDENTIFIER);
}
/**
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 54eaa329..b55d9a9b 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
@@ -21,7 +21,7 @@ public class AlgorithmIdentifier
{
return getInstance(ASN1Sequence.getInstance(obj, explicit));
}
-
+
public static AlgorithmIdentifier getInstance(
Object obj)
{
@@ -59,7 +59,7 @@ public class AlgorithmIdentifier
throw new IllegalArgumentException("Bad sequence size: "
+ seq.size());
}
-
+
algorithm = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
if (seq.size() == 2)
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 dcde3034..df4ad65f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
@@ -17,6 +17,7 @@ import org.bouncycastle.crypto.Digest;
// Android-changed: Use Android digests
// import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.AndroidDigestFactory;
+import org.bouncycastle.util.encoders.Hex;
/**
* The AuthorityKeyIdentifier object.
@@ -230,6 +231,6 @@ public class AuthorityKeyIdentifier
public String toString()
{
- return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
+ return ("AuthorityKeyIdentifier: KeyID(" + ((keyidentifier != null) ? Hex.toHexString(this.keyidentifier.getOctets()) : "null") + ")");
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java
index dd3422f6..14bc2e23 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CRLDistPoint.java
@@ -20,6 +20,11 @@ public class CRLDistPoint
return getInstance(ASN1Sequence.getInstance(obj, explicit));
}
+ public static CRLDistPoint fromExtensions(Extensions extensions)
+ {
+ return CRLDistPoint.getInstance(extensions.getExtensionParsedValue(Extension.cRLDistributionPoints));
+ }
+
public static CRLDistPoint getInstance(
Object obj)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/DigestInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/DigestInfo.java
index fd17f1b5..4b040a72 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/DigestInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/DigestInfo.java
@@ -10,6 +10,7 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.util.Arrays;
/**
* The DigestInfo object.
@@ -51,7 +52,7 @@ public class DigestInfo
AlgorithmIdentifier algId,
byte[] digest)
{
- this.digest = digest;
+ this.digest = Arrays.clone(digest);
this.algId = algId;
}
@@ -71,7 +72,7 @@ public class DigestInfo
public byte[] getDigest()
{
- return digest;
+ return Arrays.clone(digest);
}
public ASN1Primitive toASN1Primitive()
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extensions.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extensions.java
index 6508f938..30a16f3c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extensions.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extensions.java
@@ -56,6 +56,11 @@ public class Extensions
{
Extension ext = Extension.getInstance(e.nextElement());
+ if (extensions.containsKey(ext.getExtnId()))
+ {
+ throw new IllegalArgumentException("repeated extension found: " + ext.getExtnId());
+ }
+
extensions.put(ext.getExtnId(), ext);
ordering.addElement(ext.getExtnId());
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java
index 405f6e4e..52e0c36b 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/GeneralNames.java
@@ -56,7 +56,7 @@ public class GeneralNames
public GeneralNames(
GeneralName[] names)
{
- this.names = names;
+ this.names = copy(names);
}
private GeneralNames(
@@ -72,9 +72,14 @@ public class GeneralNames
public GeneralName[] getNames()
{
- GeneralName[] tmp = new GeneralName[names.length];
+ return copy(names);
+ }
+
+ private GeneralName[] copy(GeneralName[] nms)
+ {
+ GeneralName[] tmp = new GeneralName[nms.length];
- System.arraycopy(names, 0, tmp, 0, names.length);
+ System.arraycopy(nms, 0, tmp, 0, tmp.length);
return tmp;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/OtherName.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/OtherName.java
new file mode 100644
index 00000000..eb652f7f
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/OtherName.java
@@ -0,0 +1,92 @@
+package org.bouncycastle.asn1.x509;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Object;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * The OtherName object.
+ * <pre>
+ * OtherName ::= SEQUENCE {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ * </pre>
+ */
+public class OtherName
+ extends ASN1Object
+{
+ private final ASN1ObjectIdentifier typeID;
+ private final ASN1Encodable value;
+
+ /**
+ * OtherName factory method.
+ * @param obj the object used to construct an instance of <code>
+ * OtherName</code>. It must be an instance of <code>OtherName
+ * </code> or <code>ASN1Sequence</code>.
+ * @return the instance of <code>OtherName</code> built from the
+ * supplied object.
+ * @throws java.lang.IllegalArgumentException if the object passed
+ * to the factory is not an instance of <code>OtherName</code> or something that
+ * can be converted into an appropriate <code>ASN1Sequence</code>.
+ */
+ public static OtherName getInstance(
+ Object obj)
+ {
+
+ if (obj instanceof OtherName)
+ {
+ return (OtherName)obj;
+ }
+ else if (obj != null)
+ {
+ return new OtherName(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Base constructor.
+ * @param typeID the type of the other name.
+ * @param value the ANY object that represents the value.
+ */
+ public OtherName(
+ ASN1ObjectIdentifier typeID,
+ ASN1Encodable value)
+ {
+ this.typeID = typeID;
+ this.value = value;
+ }
+
+ private OtherName(ASN1Sequence seq)
+ {
+ this.typeID = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ this.value = ASN1TaggedObject.getInstance(seq.getObjectAt(1)).getObject(); // explicitly tagged
+ }
+
+ public ASN1ObjectIdentifier getTypeID()
+ {
+ return typeID;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return value;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(typeID);
+ v.add(new DERTaggedObject(true, 0, value));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PKIXNameConstraintValidator.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PKIXNameConstraintValidator.java
index 0f15dae1..d360609e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PKIXNameConstraintValidator.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PKIXNameConstraintValidator.java
@@ -1,5 +1,6 @@
package org.bouncycastle.asn1.x509;
+import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -15,6 +16,7 @@ import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Integers;
import org.bouncycastle.util.Strings;
+import org.bouncycastle.util.encoders.Hex;
public class PKIXNameConstraintValidator
implements NameConstraintValidator
@@ -29,6 +31,8 @@ public class PKIXNameConstraintValidator
private Set excludedSubtreesIP = new HashSet();
+ private Set excludedSubtreesOtherName = new HashSet();
+
private Set permittedSubtreesDN;
private Set permittedSubtreesDNS;
@@ -39,6 +43,8 @@ public class PKIXNameConstraintValidator
private Set permittedSubtreesIP;
+ private Set permittedSubtreesOtherName;
+
public PKIXNameConstraintValidator()
{
}
@@ -54,6 +60,9 @@ public class PKIXNameConstraintValidator
{
switch (name.getTagNo())
{
+ case GeneralName.otherName:
+ checkPermittedOtherName(permittedSubtreesOtherName, OtherName.getInstance(name.getName()));
+ break;
case GeneralName.rfc822Name:
checkPermittedEmail(permittedSubtreesEmail,
extractNameAsString(name));
@@ -73,6 +82,9 @@ public class PKIXNameConstraintValidator
byte[] ip = ASN1OctetString.getInstance(name.getName()).getOctets();
checkPermittedIP(permittedSubtreesIP, ip);
+ break;
+ default:
+ throw new IllegalStateException("Unknown tag encountered: " + name.getTagNo());
}
}
@@ -88,6 +100,9 @@ public class PKIXNameConstraintValidator
{
switch (name.getTagNo())
{
+ case GeneralName.otherName:
+ checkExcludedOtherName(excludedSubtreesOtherName, OtherName.getInstance(name.getName()));
+ break;
case GeneralName.rfc822Name:
checkExcludedEmail(excludedSubtreesEmail, extractNameAsString(name));
break;
@@ -106,6 +121,9 @@ public class PKIXNameConstraintValidator
byte[] ip = ASN1OctetString.getInstance(name.getName()).getOctets();
checkExcludedIP(excludedSubtreesIP, ip);
+ break;
+ default:
+ throw new IllegalStateException("Unknown tag encountered: " + name.getTagNo());
}
}
@@ -141,8 +159,13 @@ public class PKIXNameConstraintValidator
Map.Entry entry = (Map.Entry)it.next();
// go through all subtree groups
- switch (((Integer)entry.getKey()).intValue())
+ int nameType = ((Integer)entry.getKey()).intValue();
+ switch (nameType)
{
+ case GeneralName.otherName:
+ permittedSubtreesOtherName = intersectOtherName(permittedSubtreesOtherName,
+ (Set)entry.getValue());
+ break;
case GeneralName.rfc822Name:
permittedSubtreesEmail = intersectEmail(permittedSubtreesEmail,
(Set)entry.getValue());
@@ -162,6 +185,9 @@ public class PKIXNameConstraintValidator
case GeneralName.iPAddress:
permittedSubtreesIP = intersectIP(permittedSubtreesIP,
(Set)entry.getValue());
+ break;
+ default:
+ throw new IllegalStateException("Unknown tag encountered: " + nameType);
}
}
}
@@ -170,6 +196,9 @@ public class PKIXNameConstraintValidator
{
switch (nameType)
{
+ case GeneralName.otherName:
+ permittedSubtreesOtherName = new HashSet();
+ break;
case GeneralName.rfc822Name:
permittedSubtreesEmail = new HashSet();
break;
@@ -184,6 +213,9 @@ public class PKIXNameConstraintValidator
break;
case GeneralName.iPAddress:
permittedSubtreesIP = new HashSet();
+ break;
+ default:
+ throw new IllegalStateException("Unknown tag encountered: " + nameType);
}
}
@@ -198,6 +230,10 @@ public class PKIXNameConstraintValidator
switch (base.getTagNo())
{
+ case GeneralName.otherName:
+ excludedSubtreesOtherName = unionOtherName(excludedSubtreesOtherName,
+ OtherName.getInstance(base.getName()));
+ break;
case GeneralName.rfc822Name:
excludedSubtreesEmail = unionEmail(excludedSubtreesEmail,
extractNameAsString(base));
@@ -218,6 +254,8 @@ public class PKIXNameConstraintValidator
excludedSubtreesIP = unionIP(excludedSubtreesIP, ASN1OctetString
.getInstance(base.getName()).getOctets());
break;
+ default:
+ throw new IllegalStateException("Unknown tag encountered: " + base.getTagNo());
}
}
@@ -228,11 +266,13 @@ public class PKIXNameConstraintValidator
+ hashCollection(excludedSubtreesEmail)
+ hashCollection(excludedSubtreesIP)
+ hashCollection(excludedSubtreesURI)
+ + hashCollection(excludedSubtreesOtherName)
+ hashCollection(permittedSubtreesDN)
+ hashCollection(permittedSubtreesDNS)
+ hashCollection(permittedSubtreesEmail)
+ hashCollection(permittedSubtreesIP)
- + hashCollection(permittedSubtreesURI);
+ + hashCollection(permittedSubtreesURI)
+ + hashCollection(permittedSubtreesOtherName);
}
public boolean equals(Object o)
@@ -247,11 +287,13 @@ public class PKIXNameConstraintValidator
&& collectionsAreEqual(constraintValidator.excludedSubtreesEmail, excludedSubtreesEmail)
&& collectionsAreEqual(constraintValidator.excludedSubtreesIP, excludedSubtreesIP)
&& collectionsAreEqual(constraintValidator.excludedSubtreesURI, excludedSubtreesURI)
+ && collectionsAreEqual(constraintValidator.excludedSubtreesOtherName, excludedSubtreesOtherName)
&& collectionsAreEqual(constraintValidator.permittedSubtreesDN, permittedSubtreesDN)
&& collectionsAreEqual(constraintValidator.permittedSubtreesDNS, permittedSubtreesDNS)
&& collectionsAreEqual(constraintValidator.permittedSubtreesEmail, permittedSubtreesEmail)
&& collectionsAreEqual(constraintValidator.permittedSubtreesIP, permittedSubtreesIP)
- && collectionsAreEqual(constraintValidator.permittedSubtreesURI, permittedSubtreesURI);
+ && collectionsAreEqual(constraintValidator.permittedSubtreesURI, permittedSubtreesURI)
+ && collectionsAreEqual(constraintValidator.permittedSubtreesOtherName, permittedSubtreesOtherName);
}
public String toString()
@@ -283,6 +325,11 @@ public class PKIXNameConstraintValidator
temp += "IP:\n";
temp += stringifyIPCollection(permittedSubtreesIP) + "\n";
}
+ if (permittedSubtreesOtherName != null)
+ {
+ temp += "OtherName:\n";
+ temp += stringifyOtherNameCollection(permittedSubtreesOtherName) + "\n";
+ }
temp += "excluded:\n";
if (!excludedSubtreesDN.isEmpty())
{
@@ -309,6 +356,11 @@ public class PKIXNameConstraintValidator
temp += "IP:\n";
temp += stringifyIPCollection(excludedSubtreesIP) + "\n";
}
+ if (!excludedSubtreesOtherName.isEmpty())
+ {
+ temp += "OtherName:\n";
+ temp += stringifyOtherNameCollection(excludedSubtreesOtherName) + "\n";
+ }
return temp;
}
@@ -474,6 +526,25 @@ public class PKIXNameConstraintValidator
}
}
+ private Set intersectOtherName(Set permitted, Set otherNames)
+ {
+ Set intersect = new HashSet(permitted);
+
+ intersect.retainAll(otherNames);
+
+ return intersect;
+ }
+
+
+ private Set unionOtherName(Set permitted, OtherName otherName)
+ {
+ Set union = new HashSet(permitted);
+
+ union.add(otherName);
+
+ return union;
+ }
+
private Set intersectEmail(Set permitted, Set emails)
{
Set intersect = new HashSet();
@@ -774,6 +845,52 @@ public class PKIXNameConstraintValidator
"Subject email address is not from a permitted subtree.");
}
+ private void checkPermittedOtherName(Set permitted, OtherName name)
+ throws NameConstraintValidatorException
+ {
+ if (permitted == null)
+ {
+ return;
+ }
+
+ Iterator it = permitted.iterator();
+
+ while (it.hasNext())
+ {
+ OtherName str = ((OtherName)it.next());
+
+ if (otherNameIsConstrained(name, str))
+ {
+ return;
+ }
+ }
+
+ throw new NameConstraintValidatorException(
+ "Subject OtherName is not from a permitted subtree.");
+ }
+
+ private void checkExcludedOtherName(Set excluded, OtherName name)
+ throws NameConstraintValidatorException
+ {
+ if (excluded.isEmpty())
+ {
+ return;
+ }
+
+ Iterator it = excluded.iterator();
+
+ while (it.hasNext())
+ {
+ OtherName str = OtherName.getInstance(it.next());
+
+ if (otherNameIsConstrained(name, str))
+ {
+ throw new NameConstraintValidatorException(
+ "OtherName is from an excluded subtree.");
+ }
+ }
+ }
+
private void checkExcludedEmail(Set excluded, String email)
throws NameConstraintValidatorException
{
@@ -899,6 +1016,16 @@ public class PKIXNameConstraintValidator
return Arrays.areEqual(permittedSubnetAddress, ipSubnetAddress);
}
+ private boolean otherNameIsConstrained(OtherName name, OtherName constraint)
+ {
+ if (constraint.equals(name))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
private boolean emailIsConstrained(String email, String constraint)
{
String sub = email.substring(email.indexOf('@') + 1);
@@ -1887,34 +2014,73 @@ public class PKIXNameConstraintValidator
*/
private String stringifyIP(byte[] ip)
{
- String temp = "";
+ StringBuilder temp = new StringBuilder();
for (int i = 0; i < ip.length / 2; i++)
{
- temp += Integer.toString(ip[i] & 0x00FF) + ".";
+ if (temp.length() > 0)
+ {
+ temp.append(".");
+ }
+ temp.append(Integer.toString(ip[i] & 0x00FF));
}
- temp = temp.substring(0, temp.length() - 1);
- temp += "/";
+
+ temp.append("/");
+ boolean first = true;
for (int i = ip.length / 2; i < ip.length; i++)
{
- temp += Integer.toString(ip[i] & 0x00FF) + ".";
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ temp.append(".");
+ }
+ temp.append(Integer.toString(ip[i] & 0x00FF));
}
- temp = temp.substring(0, temp.length() - 1);
- return temp;
+
+ return temp.toString();
}
private String stringifyIPCollection(Set ips)
{
- String temp = "";
- temp += "[";
+ StringBuilder temp = new StringBuilder();
+ temp.append("[");
for (Iterator it = ips.iterator(); it.hasNext(); )
{
- temp += stringifyIP((byte[])it.next()) + ",";
+ if (temp.length() > 1)
+ {
+ temp.append(",");
+ }
+ temp.append(stringifyIP((byte[])it.next()));
}
- if (temp.length() > 1)
+ temp.append("]");
+ return temp.toString();
+ }
+
+ private String stringifyOtherNameCollection(Set otherNames)
+ {
+ StringBuilder temp = new StringBuilder();
+ temp.append("[");
+ for (Iterator it = otherNames.iterator(); it.hasNext(); )
{
- temp = temp.substring(0, temp.length() - 1);
+ if (temp.length() > 1)
+ {
+ temp.append(",");
+ }
+ OtherName name = OtherName.getInstance(it.next());
+ temp.append(name.getTypeID().getId());
+ temp.append(":");
+ try
+ {
+ temp.append(Hex.toHexString(name.getValue().toASN1Primitive().getEncoded()));
+ }
+ catch (IOException e)
+ {
+ temp.append(e.toString());
+ }
}
- temp += "]";
- return temp;
+ temp.append("]");
+ return temp.toString();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java
index 0938a948..97c0f143 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java
@@ -5,7 +5,6 @@ import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
@@ -14,7 +13,7 @@ import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
/**
- * The object that contains the public key stored in a certficate.
+ * The object that contains the public key stored in a certificate.
* <p>
* The getEncoded() method in the public keys in the JCE produces a DER
* encoded one of these.
@@ -107,9 +106,7 @@ public class SubjectPublicKeyInfo
public ASN1Primitive parsePublicKey()
throws IOException
{
- ASN1InputStream aIn = new ASN1InputStream(keyData.getOctets());
-
- return aIn.readObject();
+ return ASN1Primitive.fromByteArray(keyData.getOctets());
}
/**
@@ -124,9 +121,7 @@ public class SubjectPublicKeyInfo
public ASN1Primitive getPublicKey()
throws IOException
{
- ASN1InputStream aIn = new ASN1InputStream(keyData.getOctets());
-
- return aIn.readObject();
+ return ASN1Primitive.fromByteArray(keyData.getOctets());
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java
index f7f60050..3d5e1be1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java
@@ -1,12 +1,13 @@
package org.bouncycastle.asn1.x509;
+import java.math.BigInteger;
+
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x500.X500Name;
/**
@@ -87,6 +88,22 @@ public class TBSCertificate
version = new ASN1Integer(0);
}
+ boolean isV1 = false;
+ boolean isV2 = false;
+
+ if (version.getValue().equals(BigInteger.valueOf(0)))
+ {
+ isV1 = true;
+ }
+ else if (version.getValue().equals(BigInteger.valueOf(1)))
+ {
+ isV2 = true;
+ }
+ else if (!version.getValue().equals(BigInteger.valueOf(2)))
+ {
+ throw new IllegalArgumentException("version number not recognised");
+ }
+
serialNumber = ASN1Integer.getInstance(seq.getObjectAt(seqStart + 1));
signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
@@ -107,7 +124,13 @@ public class TBSCertificate
//
subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
- for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
+ int extras = seq.size() - (seqStart + 6) - 1;
+ if (extras != 0 && isV1)
+ {
+ throw new IllegalArgumentException("version 1 certificate contains extra data");
+ }
+
+ while (extras > 0)
{
ASN1TaggedObject extra = (ASN1TaggedObject)seq.getObjectAt(seqStart + 6 + extras);
@@ -120,8 +143,16 @@ public class TBSCertificate
subjectUniqueId = DERBitString.getInstance(extra, false);
break;
case 3:
+ if (isV2)
+ {
+ throw new IllegalArgumentException("version 2 certificate cannot contain extensions");
+ }
extensions = Extensions.getInstance(ASN1Sequence.getInstance(extra, true));
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown tag encountered in structure: " + extra.getTagNo());
}
+ extras--;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificateStructure.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificateStructure.java
index 2c5d920a..e7bdedc5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificateStructure.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificateStructure.java
@@ -29,6 +29,7 @@ import org.bouncycastle.asn1.x500.X500Name;
* <p>
* Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
* will parse them, but you really shouldn't be creating new ones.
+ * @deprecated use TBSCertificate
*/
public class TBSCertificateStructure
extends ASN1Object
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
index e58220e6..af218bca 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
@@ -23,6 +23,8 @@ public interface X509ObjectIdentifiers
/** Subject RDN components: name = 2.5.4.41 */
static final ASN1ObjectIdentifier id_at_name = new ASN1ObjectIdentifier("2.5.4.41").intern();
+ static final ASN1ObjectIdentifier id_at_organizationIdentifier = new ASN1ObjectIdentifier("2.5.4.97").intern();
+
/**
* id-SHA1 OBJECT IDENTIFIER ::=
* {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DomainParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DomainParameters.java
index e23f1b84..0555190a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/DomainParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/DomainParameters.java
@@ -19,7 +19,7 @@ import org.bouncycastle.asn1.DERSequence;
* p INTEGER, -- odd prime, p=jq +1
* g INTEGER, -- generator, g
* q INTEGER, -- factor of p-1
- * j INTEGER OPTIONAL, -- subgroup factor, j>= 2
+ * j INTEGER OPTIONAL, -- subgroup factor, j &gt;= 2
* validationParams ValidationParams OPTIONAL
* }
* </pre>
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 0fc87379..41f12b1c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
@@ -7,10 +7,13 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
// Android-removed: Unsupported curves
// import org.bouncycastle.asn1.anssi.ANSSINamedCurves;
// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
+// import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.sec.SECNamedCurves;
// Android-removed: Unsupported curves
// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
+import org.bouncycastle.crypto.ec.CustomNamedCurves;
+import org.bouncycastle.crypto.params.ECDomainParameters;
/**
* A general class that reads all X9.62 style EC curve tables.
@@ -50,6 +53,16 @@ public class ECNamedCurveTable
{
ecP = ANSSINamedCurves.getByName(name);
}
+
+ if (ecP == null)
+ {
+ ecP = fromDomainParameters(ECGOST3410NamedCurves.getByName(name));
+ }
+
+ if (ecP == null)
+ {
+ ecP = GMNamedCurves.getByName(name);
+ }
*/
// END Android-removed: Unsupported curves
@@ -88,6 +101,16 @@ public class ECNamedCurveTable
{
oid = ANSSINamedCurves.getOID(name);
}
+
+ if (oid == null)
+ {
+ oid = ECGOST3410NamedCurves.getOID(name);
+ }
+
+ if (oid == null)
+ {
+ oid = GMNamedCurves.getOID(name);
+ }
*/
// END Android-removed: Unsupported curves
@@ -104,33 +127,44 @@ public class ECNamedCurveTable
public static String getName(
ASN1ObjectIdentifier oid)
{
- String name = NISTNamedCurves.getName(oid);
+ String name = X962NamedCurves.getName(oid);
if (name == null)
{
name = SECNamedCurves.getName(oid);
}
+ if (name == null)
+ {
+ name = NISTNamedCurves.getName(oid);
+ }
+
// BEGIN Android-removed: Unsupported curves
/*
if (name == null)
{
name = TeleTrusTNamedCurves.getName(oid);
}
- */
- // END Android-removed: Unsupported curves
if (name == null)
{
- name = X962NamedCurves.getName(oid);
+ name = ANSSINamedCurves.getName(oid);
}
- // BEGIN Android-removed: Unsupported curves
- /*
if (name == null)
{
name = ECGOST3410NamedCurves.getName(oid);
}
+
+ if (name == null)
+ {
+ name = GMNamedCurves.getName(oid);
+ }
+
+ if (name == null)
+ {
+ name = CustomNamedCurves.getName(oid);
+ }
*/
// END Android-removed: Unsupported curves
@@ -167,6 +201,16 @@ public class ECNamedCurveTable
{
ecP = ANSSINamedCurves.getByOID(oid);
}
+
+ if (ecP == null)
+ {
+ ecP = fromDomainParameters(ECGOST3410NamedCurves.getByOID(oid));
+ }
+
+ if (ecP == null)
+ {
+ ecP = GMNamedCurves.getByOID(oid);
+ }
*/
// END Android-removed: Unsupported curves
@@ -188,6 +232,8 @@ public class ECNamedCurveTable
// BEGIN Android-removed: Unsupported curves
// addEnumeration(v, TeleTrusTNamedCurves.getNames());
// addEnumeration(v, ANSSINamedCurves.getNames());
+ // addEnumeration(v, ECGOST3410NamedCurves.getNames());
+ // addEnumeration(v, GMNamedCurves.getNames());
// END Android-removed: Unsupported curves
return v.elements();
@@ -202,4 +248,9 @@ public class ECNamedCurveTable
v.addElement(e.nextElement());
}
}
+
+ private static X9ECParameters fromDomainParameters(ECDomainParameters dp)
+ {
+ return dp == null ? null : new X9ECParameters(dp.getCurve(), dp.getG(), dp.getN(), dp.getH(), dp.getSeed());
+ }
}
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 022c0183..02968345 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java
@@ -23,7 +23,7 @@ public class X962NamedCurves
BigInteger h = BigInteger.valueOf(1);
ECCurve cFp192v1 = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16),
new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16),
n, h);
@@ -45,7 +45,7 @@ public class X962NamedCurves
BigInteger h = BigInteger.valueOf(1);
ECCurve cFp192v2 = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16),
new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16),
n, h);
@@ -67,7 +67,7 @@ public class X962NamedCurves
BigInteger h = BigInteger.valueOf(1);
ECCurve cFp192v3 = new ECCurve.Fp(
- new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16),
new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16),
n, h);
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 f1bac2b8..3838a232 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9Curve.java
@@ -13,6 +13,7 @@ import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.util.Arrays;
/**
* ASN.1 def for Elliptic-Curve Curve structure. See
@@ -29,9 +30,7 @@ public class X9Curve
public X9Curve(
ECCurve curve)
{
- this.curve = curve;
- this.seed = null;
- setFieldIdentifier();
+ this(curve, null);
}
public X9Curve(
@@ -39,25 +38,25 @@ public class X9Curve
byte[] seed)
{
this.curve = curve;
- this.seed = seed;
+ this.seed = Arrays.clone(seed);
setFieldIdentifier();
}
public X9Curve(
X9FieldID fieldID,
+ BigInteger order,
+ BigInteger cofactor,
ASN1Sequence seq)
- {
- // TODO Is it possible to get the order(n) and cofactor(h) too?
-
+ {
fieldIdentifier = fieldID.getIdentifier();
if (fieldIdentifier.equals(prime_field))
- {
- BigInteger p = ((ASN1Integer)fieldID.getParameters()).getValue();
- X9FieldElement x9A = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(0));
- X9FieldElement x9B = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(1));
- curve = new ECCurve.Fp(p, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
+ {
+ BigInteger p = ((ASN1Integer)fieldID.getParameters()).getValue();
+ BigInteger A = new BigInteger(1, ASN1OctetString.getInstance(seq.getObjectAt(0)).getOctets());
+ BigInteger B = new BigInteger(1, ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets());
+ curve = new ECCurve.Fp(p, A, B, order, cofactor);
}
- else if (fieldIdentifier.equals(characteristic_two_field))
+ else if (fieldIdentifier.equals(characteristic_two_field))
{
// Characteristic two field
ASN1Sequence parameters = ASN1Sequence.getInstance(fieldID.getParameters());
@@ -70,11 +69,11 @@ public class X9Curve
int k2 = 0;
int k3 = 0;
- if (representation.equals(tpBasis))
+ if (representation.equals(tpBasis))
{
// Trinomial basis representation
k1 = ASN1Integer.getInstance(parameters.getObjectAt(2)).getValue().intValue();
- }
+ }
else if (representation.equals(ppBasis))
{
// Pentanomial basis representation
@@ -82,25 +81,25 @@ public class X9Curve
k1 = ASN1Integer.getInstance(pentanomial.getObjectAt(0)).getValue().intValue();
k2 = ASN1Integer.getInstance(pentanomial.getObjectAt(1)).getValue().intValue();
k3 = ASN1Integer.getInstance(pentanomial.getObjectAt(2)).getValue().intValue();
- }
+ }
else
{
throw new IllegalArgumentException("This type of EC basis is not implemented");
- }
- X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0));
- X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1));
- curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
- }
+ }
+ BigInteger A = new BigInteger(1, ASN1OctetString.getInstance(seq.getObjectAt(0)).getOctets());
+ BigInteger B = new BigInteger(1, ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets());
+ curve = new ECCurve.F2m(m, k1, k2, k3, A, B, order, cofactor);
+ }
else
{
throw new IllegalArgumentException("This type of ECCurve is not implemented");
- }
+ }
if (seq.size() == 3)
{
- seed = ((DERBitString)seq.getObjectAt(2)).getBytes();
- }
- }
+ seed = Arrays.clone(((DERBitString)seq.getObjectAt(2)).getBytes());
+ }
+ }
private void setFieldIdentifier()
{
@@ -125,7 +124,7 @@ public class X9Curve
public byte[] getSeed()
{
- return seed;
+ return Arrays.clone(seed);
}
/**
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 85163651..f02404a9 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
@@ -13,6 +13,7 @@ import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.field.PolynomialExtensionField;
+import org.bouncycastle.util.Arrays;
/**
* ASN.1 def for Elliptic-Curve ECParameters structure. See
@@ -35,34 +36,35 @@ public class X9ECParameters
ASN1Sequence seq)
{
if (!(seq.getObjectAt(0) instanceof ASN1Integer)
- || !((ASN1Integer)seq.getObjectAt(0)).getValue().equals(ONE))
+ || !((ASN1Integer)seq.getObjectAt(0)).getValue().equals(ONE))
{
throw new IllegalArgumentException("bad version in X9ECParameters");
}
- X9Curve x9c = new X9Curve(
- X9FieldID.getInstance(seq.getObjectAt(1)),
- ASN1Sequence.getInstance(seq.getObjectAt(2)));
+ this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue();
+
+ if (seq.size() == 6)
+ {
+ this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue();
+ }
+
+ X9Curve x9c = new X9Curve(
+ X9FieldID.getInstance(seq.getObjectAt(1)), n, h,
+ ASN1Sequence.getInstance(seq.getObjectAt(2)));
this.curve = x9c.getCurve();
Object p = seq.getObjectAt(3);
if (p instanceof X9ECPoint)
{
- this.g = ((X9ECPoint)p);
+ this.g = (X9ECPoint)p;
}
else
{
this.g = new X9ECPoint(curve, (ASN1OctetString)p);
}
- this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue();
this.seed = x9c.getSeed();
-
- if (seq.size() == 6)
- {
- this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue();
- }
}
public static X9ECParameters getInstance(Object obj)
@@ -127,7 +129,7 @@ public class X9ECParameters
this.g = g;
this.n = n;
this.h = h;
- this.seed = seed;
+ this.seed = Arrays.clone(seed);
if (ECAlgorithms.isFpCurve(curve))
{
@@ -178,7 +180,7 @@ public class X9ECParameters
public byte[] getSeed()
{
- return seed;
+ return Arrays.clone(seed);
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java
index 96130c6a..2dd8ff1c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParametersHolder.java
@@ -1,5 +1,8 @@
package org.bouncycastle.asn1.x9;
+/**
+ * A holding class that allows for X9ECParameters to be lazily constructed.
+ */
public abstract class X9ECParametersHolder
{
private X9ECParameters params;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
index 95fdc672..b5037849 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
@@ -9,7 +9,7 @@ import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.Arrays;
/**
- * class for describing an ECPoint as a DER object.
+ * Class for describing an ECPoint as a DER object.
*/
public class X9ECPoint
extends ASN1Object
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java
index 13fe7721..4cba82de 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldElement.java
@@ -22,17 +22,23 @@ public class X9FieldElement
{
this.f = f;
}
-
+
+ /**
+ * @deprecated Will be removed
+ */
public X9FieldElement(BigInteger p, ASN1OctetString s)
{
this(new ECFieldElement.Fp(p, new BigInteger(1, s.getOctets())));
}
-
+
+ /**
+ * @deprecated Will be removed
+ */
public X9FieldElement(int m, int k1, int k2, int k3, ASN1OctetString s)
{
this(new ECFieldElement.F2m(m, k1, k2, k3, new BigInteger(1, s.getOctets())));
}
-
+
public ECFieldElement getValue()
{
return f;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
index 1317b4ab..ce6f86df 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
@@ -4,7 +4,7 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
/**
*
- * X9.62
+ * Object identifiers for the various X9 standards.
* <pre>
* ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
* us(840) ansi-x962(10045) }
@@ -13,129 +13,129 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
public interface X9ObjectIdentifiers
{
/** Base OID: 1.2.840.10045 */
- static final ASN1ObjectIdentifier ansi_X9_62 = new ASN1ObjectIdentifier("1.2.840.10045");
+ ASN1ObjectIdentifier ansi_X9_62 = new ASN1ObjectIdentifier("1.2.840.10045");
/** OID: 1.2.840.10045.1 */
- static final ASN1ObjectIdentifier id_fieldType = ansi_X9_62.branch("1");
+ ASN1ObjectIdentifier id_fieldType = ansi_X9_62.branch("1");
/** OID: 1.2.840.10045.1.1 */
- static final ASN1ObjectIdentifier prime_field = id_fieldType.branch("1");
+ ASN1ObjectIdentifier prime_field = id_fieldType.branch("1");
/** OID: 1.2.840.10045.1.2 */
- static final ASN1ObjectIdentifier characteristic_two_field = id_fieldType.branch("2");
+ ASN1ObjectIdentifier characteristic_two_field = id_fieldType.branch("2");
/** OID: 1.2.840.10045.1.2.3.1 */
- static final ASN1ObjectIdentifier gnBasis = characteristic_two_field.branch("3.1");
+ ASN1ObjectIdentifier gnBasis = characteristic_two_field.branch("3.1");
/** OID: 1.2.840.10045.1.2.3.2 */
- static final ASN1ObjectIdentifier tpBasis = characteristic_two_field.branch("3.2");
+ ASN1ObjectIdentifier tpBasis = characteristic_two_field.branch("3.2");
/** OID: 1.2.840.10045.1.2.3.3 */
- static final ASN1ObjectIdentifier ppBasis = characteristic_two_field.branch("3.3");
+ ASN1ObjectIdentifier ppBasis = characteristic_two_field.branch("3.3");
/** OID: 1.2.840.10045.4 */
- static final ASN1ObjectIdentifier id_ecSigType = ansi_X9_62.branch("4");
+ ASN1ObjectIdentifier id_ecSigType = ansi_X9_62.branch("4");
/** OID: 1.2.840.10045.4.1 */
- static final ASN1ObjectIdentifier ecdsa_with_SHA1 = id_ecSigType.branch("1");
+ ASN1ObjectIdentifier ecdsa_with_SHA1 = id_ecSigType.branch("1");
/** OID: 1.2.840.10045.2 */
- static final ASN1ObjectIdentifier id_publicKeyType = ansi_X9_62.branch("2");
+ ASN1ObjectIdentifier id_publicKeyType = ansi_X9_62.branch("2");
/** OID: 1.2.840.10045.2.1 */
- static final ASN1ObjectIdentifier id_ecPublicKey = id_publicKeyType.branch("1");
+ ASN1ObjectIdentifier id_ecPublicKey = id_publicKeyType.branch("1");
/** OID: 1.2.840.10045.4.3 */
- static final ASN1ObjectIdentifier ecdsa_with_SHA2 = id_ecSigType.branch("3");
+ ASN1ObjectIdentifier ecdsa_with_SHA2 = id_ecSigType.branch("3");
/** OID: 1.2.840.10045.4.3.1 */
- static final ASN1ObjectIdentifier ecdsa_with_SHA224 = ecdsa_with_SHA2.branch("1");
+ ASN1ObjectIdentifier ecdsa_with_SHA224 = ecdsa_with_SHA2.branch("1");
/** OID: 1.2.840.10045.4.3.2 */
- static final ASN1ObjectIdentifier ecdsa_with_SHA256 = ecdsa_with_SHA2.branch("2");
+ ASN1ObjectIdentifier ecdsa_with_SHA256 = ecdsa_with_SHA2.branch("2");
/** OID: 1.2.840.10045.4.3.3 */
- static final ASN1ObjectIdentifier ecdsa_with_SHA384 = ecdsa_with_SHA2.branch("3");
+ ASN1ObjectIdentifier ecdsa_with_SHA384 = ecdsa_with_SHA2.branch("3");
/** OID: 1.2.840.10045.4.3.4 */
- static final ASN1ObjectIdentifier ecdsa_with_SHA512 = ecdsa_with_SHA2.branch("4");
+ ASN1ObjectIdentifier ecdsa_with_SHA512 = ecdsa_with_SHA2.branch("4");
/**
* Named curves base
* <p>
* OID: 1.2.840.10045.3
*/
- static final ASN1ObjectIdentifier ellipticCurve = ansi_X9_62.branch("3");
+ ASN1ObjectIdentifier ellipticCurve = ansi_X9_62.branch("3");
/**
* Two Curves
* <p>
* OID: 1.2.840.10045.3.0
*/
- static final ASN1ObjectIdentifier cTwoCurve = ellipticCurve.branch("0");
+ ASN1ObjectIdentifier cTwoCurve = ellipticCurve.branch("0");
/** Two Curve c2pnb163v1, OID: 1.2.840.10045.3.0.1 */
- static final ASN1ObjectIdentifier c2pnb163v1 = cTwoCurve.branch("1");
+ ASN1ObjectIdentifier c2pnb163v1 = cTwoCurve.branch("1");
/** Two Curve c2pnb163v2, OID: 1.2.840.10045.3.0.2 */
- static final ASN1ObjectIdentifier c2pnb163v2 = cTwoCurve.branch("2");
+ ASN1ObjectIdentifier c2pnb163v2 = cTwoCurve.branch("2");
/** Two Curve c2pnb163v3, OID: 1.2.840.10045.3.0.3 */
- static final ASN1ObjectIdentifier c2pnb163v3 = cTwoCurve.branch("3");
+ ASN1ObjectIdentifier c2pnb163v3 = cTwoCurve.branch("3");
/** Two Curve c2pnb176w1, OID: 1.2.840.10045.3.0.4 */
- static final ASN1ObjectIdentifier c2pnb176w1 = cTwoCurve.branch("4");
+ ASN1ObjectIdentifier c2pnb176w1 = cTwoCurve.branch("4");
/** Two Curve c2tnb191v1, OID: 1.2.840.10045.3.0.5 */
- static final ASN1ObjectIdentifier c2tnb191v1 = cTwoCurve.branch("5");
+ ASN1ObjectIdentifier c2tnb191v1 = cTwoCurve.branch("5");
/** Two Curve c2tnb191v2, OID: 1.2.840.10045.3.0.6 */
- static final ASN1ObjectIdentifier c2tnb191v2 = cTwoCurve.branch("6");
+ ASN1ObjectIdentifier c2tnb191v2 = cTwoCurve.branch("6");
/** Two Curve c2tnb191v3, OID: 1.2.840.10045.3.0.7 */
- static final ASN1ObjectIdentifier c2tnb191v3 = cTwoCurve.branch("7");
+ ASN1ObjectIdentifier c2tnb191v3 = cTwoCurve.branch("7");
/** Two Curve c2onb191v4, OID: 1.2.840.10045.3.0.8 */
- static final ASN1ObjectIdentifier c2onb191v4 = cTwoCurve.branch("8");
+ ASN1ObjectIdentifier c2onb191v4 = cTwoCurve.branch("8");
/** Two Curve c2onb191v5, OID: 1.2.840.10045.3.0.9 */
- static final ASN1ObjectIdentifier c2onb191v5 = cTwoCurve.branch("9");
+ ASN1ObjectIdentifier c2onb191v5 = cTwoCurve.branch("9");
/** Two Curve c2pnb208w1, OID: 1.2.840.10045.3.0.10 */
- static final ASN1ObjectIdentifier c2pnb208w1 = cTwoCurve.branch("10");
+ ASN1ObjectIdentifier c2pnb208w1 = cTwoCurve.branch("10");
/** Two Curve c2tnb239v1, OID: 1.2.840.10045.3.0.11 */
- static final ASN1ObjectIdentifier c2tnb239v1 = cTwoCurve.branch("11");
+ ASN1ObjectIdentifier c2tnb239v1 = cTwoCurve.branch("11");
/** Two Curve c2tnb239v2, OID: 1.2.840.10045.3.0.12 */
- static final ASN1ObjectIdentifier c2tnb239v2 = cTwoCurve.branch("12");
+ ASN1ObjectIdentifier c2tnb239v2 = cTwoCurve.branch("12");
/** Two Curve c2tnb239v3, OID: 1.2.840.10045.3.0.13 */
- static final ASN1ObjectIdentifier c2tnb239v3 = cTwoCurve.branch("13");
+ ASN1ObjectIdentifier c2tnb239v3 = cTwoCurve.branch("13");
/** Two Curve c2onb239v4, OID: 1.2.840.10045.3.0.14 */
- static final ASN1ObjectIdentifier c2onb239v4 = cTwoCurve.branch("14");
+ ASN1ObjectIdentifier c2onb239v4 = cTwoCurve.branch("14");
/** Two Curve c2onb239v5, OID: 1.2.840.10045.3.0.15 */
- static final ASN1ObjectIdentifier c2onb239v5 = cTwoCurve.branch("15");
+ ASN1ObjectIdentifier c2onb239v5 = cTwoCurve.branch("15");
/** Two Curve c2pnb272w1, OID: 1.2.840.10045.3.0.16 */
- static final ASN1ObjectIdentifier c2pnb272w1 = cTwoCurve.branch("16");
+ ASN1ObjectIdentifier c2pnb272w1 = cTwoCurve.branch("16");
/** Two Curve c2pnb304w1, OID: 1.2.840.10045.3.0.17 */
- static final ASN1ObjectIdentifier c2pnb304w1 = cTwoCurve.branch("17");
+ ASN1ObjectIdentifier c2pnb304w1 = cTwoCurve.branch("17");
/** Two Curve c2tnb359v1, OID: 1.2.840.10045.3.0.18 */
- static final ASN1ObjectIdentifier c2tnb359v1 = cTwoCurve.branch("18");
+ ASN1ObjectIdentifier c2tnb359v1 = cTwoCurve.branch("18");
/** Two Curve c2pnb368w1, OID: 1.2.840.10045.3.0.19 */
- static final ASN1ObjectIdentifier c2pnb368w1 = cTwoCurve.branch("19");
+ ASN1ObjectIdentifier c2pnb368w1 = cTwoCurve.branch("19");
/** Two Curve c2tnb431r1, OID: 1.2.840.10045.3.0.20 */
- static final ASN1ObjectIdentifier c2tnb431r1 = cTwoCurve.branch("20");
+ ASN1ObjectIdentifier c2tnb431r1 = cTwoCurve.branch("20");
/**
* Prime Curves
* <p>
* OID: 1.2.840.10045.3.1
*/
- static final ASN1ObjectIdentifier primeCurve = ellipticCurve.branch("1");
+ ASN1ObjectIdentifier primeCurve = ellipticCurve.branch("1");
/** Prime Curve prime192v1, OID: 1.2.840.10045.3.1.1 */
- static final ASN1ObjectIdentifier prime192v1 = primeCurve.branch("1");
+ ASN1ObjectIdentifier prime192v1 = primeCurve.branch("1");
/** Prime Curve prime192v2, OID: 1.2.840.10045.3.1.2 */
- static final ASN1ObjectIdentifier prime192v2 = primeCurve.branch("2");
+ ASN1ObjectIdentifier prime192v2 = primeCurve.branch("2");
/** Prime Curve prime192v3, OID: 1.2.840.10045.3.1.3 */
- static final ASN1ObjectIdentifier prime192v3 = primeCurve.branch("3");
+ ASN1ObjectIdentifier prime192v3 = primeCurve.branch("3");
/** Prime Curve prime239v1, OID: 1.2.840.10045.3.1.4 */
- static final ASN1ObjectIdentifier prime239v1 = primeCurve.branch("4");
+ ASN1ObjectIdentifier prime239v1 = primeCurve.branch("4");
/** Prime Curve prime239v2, OID: 1.2.840.10045.3.1.5 */
- static final ASN1ObjectIdentifier prime239v2 = primeCurve.branch("5");
+ ASN1ObjectIdentifier prime239v2 = primeCurve.branch("5");
/** Prime Curve prime239v3, OID: 1.2.840.10045.3.1.6 */
- static final ASN1ObjectIdentifier prime239v3 = primeCurve.branch("6");
+ ASN1ObjectIdentifier prime239v3 = primeCurve.branch("6");
/** Prime Curve prime256v1, OID: 1.2.840.10045.3.1.7 */
- static final ASN1ObjectIdentifier prime256v1 = primeCurve.branch("7");
+ ASN1ObjectIdentifier prime256v1 = primeCurve.branch("7");
/**
* DSA
@@ -145,7 +145,7 @@ public interface X9ObjectIdentifiers
* </pre>
* Base OID: 1.2.840.10040.4.1
*/
- static final ASN1ObjectIdentifier id_dsa = new ASN1ObjectIdentifier("1.2.840.10040.4.1");
+ ASN1ObjectIdentifier id_dsa = new ASN1ObjectIdentifier("1.2.840.10040.4.1");
/**
* <pre>
@@ -154,26 +154,26 @@ public interface X9ObjectIdentifiers
* </pre>
* OID: 1.2.840.10040.4.3
*/
- static final ASN1ObjectIdentifier id_dsa_with_sha1 = new ASN1ObjectIdentifier("1.2.840.10040.4.3");
+ ASN1ObjectIdentifier id_dsa_with_sha1 = new ASN1ObjectIdentifier("1.2.840.10040.4.3");
/**
* X9.63 - Signature Specification
* <p>
* Base OID: 1.3.133.16.840.63.0
*/
- static final ASN1ObjectIdentifier x9_63_scheme = new ASN1ObjectIdentifier("1.3.133.16.840.63.0");
+ ASN1ObjectIdentifier x9_63_scheme = new ASN1ObjectIdentifier("1.3.133.16.840.63.0");
/** OID: 1.3.133.16.840.63.0.2 */
- static final ASN1ObjectIdentifier dhSinglePass_stdDH_sha1kdf_scheme = x9_63_scheme.branch("2");
+ ASN1ObjectIdentifier dhSinglePass_stdDH_sha1kdf_scheme = x9_63_scheme.branch("2");
/** OID: 1.3.133.16.840.63.0.3 */
- static final ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha1kdf_scheme = x9_63_scheme.branch("3");
+ ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha1kdf_scheme = x9_63_scheme.branch("3");
/** OID: 1.3.133.16.840.63.0.16 */
- static final ASN1ObjectIdentifier mqvSinglePass_sha1kdf_scheme = x9_63_scheme.branch("16");
+ ASN1ObjectIdentifier mqvSinglePass_sha1kdf_scheme = x9_63_scheme.branch("16");
/**
* X9.42
*/
- static final ASN1ObjectIdentifier ansi_X9_42 = new ASN1ObjectIdentifier("1.2.840.10046");
+ ASN1ObjectIdentifier ansi_X9_42 = new ASN1ObjectIdentifier("1.2.840.10046");
/**
* Diffie-Hellman
@@ -184,26 +184,26 @@ public interface X9ObjectIdentifiers
* </pre>
* OID: 1.2.840.10046.2.1
*/
- static final ASN1ObjectIdentifier dhpublicnumber = ansi_X9_42.branch("2.1");
+ ASN1ObjectIdentifier dhpublicnumber = ansi_X9_42.branch("2.1");
/** X9.42 schemas base OID: 1.2.840.10046.3 */
- static final ASN1ObjectIdentifier x9_42_schemes = ansi_X9_42.branch("3");
+ ASN1ObjectIdentifier x9_42_schemes = ansi_X9_42.branch("3");
/** X9.42 dhStatic OID: 1.2.840.10046.3.1 */
- static final ASN1ObjectIdentifier dhStatic = x9_42_schemes.branch("1");
+ ASN1ObjectIdentifier dhStatic = x9_42_schemes.branch("1");
/** X9.42 dhEphem OID: 1.2.840.10046.3.2 */
- static final ASN1ObjectIdentifier dhEphem = x9_42_schemes.branch("2");
+ ASN1ObjectIdentifier dhEphem = x9_42_schemes.branch("2");
/** X9.42 dhOneFlow OID: 1.2.840.10046.3.3 */
- static final ASN1ObjectIdentifier dhOneFlow = x9_42_schemes.branch("3");
+ ASN1ObjectIdentifier dhOneFlow = x9_42_schemes.branch("3");
/** X9.42 dhHybrid1 OID: 1.2.840.10046.3.4 */
- static final ASN1ObjectIdentifier dhHybrid1 = x9_42_schemes.branch("4");
+ ASN1ObjectIdentifier dhHybrid1 = x9_42_schemes.branch("4");
/** X9.42 dhHybrid2 OID: 1.2.840.10046.3.5 */
- static final ASN1ObjectIdentifier dhHybrid2 = x9_42_schemes.branch("5");
+ ASN1ObjectIdentifier dhHybrid2 = x9_42_schemes.branch("5");
/** X9.42 dhHybridOneFlow OID: 1.2.840.10046.3.6 */
- static final ASN1ObjectIdentifier dhHybridOneFlow = x9_42_schemes.branch("6");
+ ASN1ObjectIdentifier dhHybridOneFlow = x9_42_schemes.branch("6");
/** X9.42 MQV2 OID: 1.2.840.10046.3.7 */
- static final ASN1ObjectIdentifier mqv2 = x9_42_schemes.branch("7");
+ ASN1ObjectIdentifier mqv2 = x9_42_schemes.branch("7");
/** X9.42 MQV1 OID: 1.2.840.10046.3.8 */
- static final ASN1ObjectIdentifier mqv1 = x9_42_schemes.branch("8");
+ ASN1ObjectIdentifier mqv1 = x9_42_schemes.branch("8");
/**
* X9.44
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/CryptoServicesPermission.java b/bcprov/src/main/java/org/bouncycastle/crypto/CryptoServicesPermission.java
new file mode 100644
index 00000000..8a62a8df
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/CryptoServicesPermission.java
@@ -0,0 +1,81 @@
+package org.bouncycastle.crypto;
+
+import java.security.Permission;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Permissions that need to be configured if a SecurityManager is used.
+ */
+public class CryptoServicesPermission
+ extends Permission
+{
+ /**
+ * Enable the setting of global configuration properties. This permission implies THREAD_LOCAL_CONFIG
+ */
+ public static final String GLOBAL_CONFIG = "globalConfig";
+
+ /**
+ * Enable the setting of thread local configuration properties.
+ */
+ public static final String THREAD_LOCAL_CONFIG = "threadLocalConfig";
+
+ /**
+ * Enable the setting of the default SecureRandom.
+ */
+ public static final String DEFAULT_RANDOM = "defaultRandomConfig";
+
+ private final Set<String> actions = new HashSet<String>();
+
+ public CryptoServicesPermission(String name)
+ {
+ super(name);
+
+ this.actions.add(name);
+ }
+
+ public boolean implies(Permission permission)
+ {
+ if (permission instanceof CryptoServicesPermission)
+ {
+ CryptoServicesPermission other = (CryptoServicesPermission)permission;
+
+ if (this.getName().equals(other.getName()))
+ {
+ return true;
+ }
+
+ if (this.actions.containsAll(other.actions))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof CryptoServicesPermission)
+ {
+ CryptoServicesPermission other = (CryptoServicesPermission)obj;
+
+ if (this.actions.equals(other.actions))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public int hashCode()
+ {
+ return actions.hashCode();
+ }
+
+ public String getActions()
+ {
+ return actions.toString();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/CryptoServicesRegistrar.java b/bcprov/src/main/java/org/bouncycastle/crypto/CryptoServicesRegistrar.java
new file mode 100644
index 00000000..4448be04
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/CryptoServicesRegistrar.java
@@ -0,0 +1,417 @@
+package org.bouncycastle.crypto;
+
+import java.math.BigInteger;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.security.SecureRandom;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.params.DHParameters;
+import org.bouncycastle.crypto.params.DHValidationParameters;
+import org.bouncycastle.crypto.params.DSAParameters;
+import org.bouncycastle.crypto.params.DSAValidationParameters;
+import org.bouncycastle.util.encoders.Hex;
+
+/**
+ * Basic registrar class for providing defaults for cryptography services in this module.
+ */
+public final class CryptoServicesRegistrar
+{
+ private static final Permission CanSetDefaultProperty = new CryptoServicesPermission(CryptoServicesPermission.GLOBAL_CONFIG);
+ private static final Permission CanSetThreadProperty = new CryptoServicesPermission(CryptoServicesPermission.THREAD_LOCAL_CONFIG);
+ private static final Permission CanSetDefaultRandom = new CryptoServicesPermission(CryptoServicesPermission.DEFAULT_RANDOM);
+
+ private static final ThreadLocal<Map<String, Object[]>> threadProperties = new ThreadLocal<Map<String, Object[]>>();
+ private static final Map<String, Object[]> globalProperties = Collections.synchronizedMap(new HashMap<String, Object[]>());
+
+ private static volatile SecureRandom defaultSecureRandom;
+
+ static
+ {
+ // default domain parameters for DSA and Diffie-Hellman
+
+ DSAParameters def512Params = new DSAParameters(
+ new BigInteger("fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e17", 16),
+ new BigInteger("962eddcc369cba8ebb260ee6b6a126d9346e38c5", 16),
+ new BigInteger("678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4", 16),
+ new DSAValidationParameters(Hex.decode("b869c82b35d70e1b1ff91b28e37a62ecdc34409b"), 123));
+
+ DSAParameters def768Params = new DSAParameters(
+ new BigInteger("e9e642599d355f37c97ffd3567120b8e25c9cd43e927b3a9670fbec5" +
+ "d890141922d2c3b3ad2480093799869d1e846aab49fab0ad26d2ce6a" +
+ "22219d470bce7d777d4a21fbe9c270b57f607002f3cef8393694cf45" +
+ "ee3688c11a8c56ab127a3daf", 16),
+ new BigInteger("9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511", 16),
+ new BigInteger("30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5facbaecbe95f190aa7" +
+ "a31d23c4dbbcbe06174544401a5b2c020965d8c2bd2171d366844577" +
+ "1f74ba084d2029d83c1c158547f3a9f1a2715be23d51ae4d3e5a1f6a" +
+ "7064f316933a346d3f529252", 16),
+ new DSAValidationParameters(Hex.decode("77d0f8c4dad15eb8c4f2f8d6726cefd96d5bb399"), 263));
+
+ DSAParameters def1024Params = new DSAParameters(
+ new BigInteger("fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80" +
+ "b6512669455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b" +
+ "801d346ff26660b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c6" +
+ "1bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554135a169132f675" +
+ "f3ae2b61d72aeff22203199dd14801c7", 16),
+ new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16),
+ new BigInteger("f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b" +
+ "3d0782675159578ebad4594fe67107108180b449167123e84c281613" +
+ "b7cf09328cc8a6e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f" +
+ "0bfa213562f1fb627a01243bcca4f1bea8519089a883dfe15ae59f06" +
+ "928b665e807b552564014c3bfecf492a", 16),
+ new DSAValidationParameters(Hex.decode("8d5155894229d5e689ee01e6018a237e2cae64cd"), 92));
+
+ DSAParameters def2048Params = new DSAParameters(
+ new BigInteger("95475cf5d93e596c3fcd1d902add02f427f5f3c7210313bb45fb4d5b" +
+ "b2e5fe1cbd678cd4bbdd84c9836be1f31c0777725aeb6c2fc38b85f4" +
+ "8076fa76bcd8146cc89a6fb2f706dd719898c2083dc8d896f84062e2" +
+ "c9c94d137b054a8d8096adb8d51952398eeca852a0af12df83e475aa" +
+ "65d4ec0c38a9560d5661186ff98b9fc9eb60eee8b030376b236bc73b" +
+ "e3acdbd74fd61c1d2475fa3077b8f080467881ff7e1ca56fee066d79" +
+ "506ade51edbb5443a563927dbc4ba520086746175c8885925ebc64c6" +
+ "147906773496990cb714ec667304e261faee33b3cbdf008e0c3fa906" +
+ "50d97d3909c9275bf4ac86ffcb3d03e6dfc8ada5934242dd6d3bcca2" +
+ "a406cb0b", 16),
+ new BigInteger("f8183668ba5fc5bb06b5981e6d8b795d30b8978d43ca0ec572e37e09939a9773", 16),
+ new BigInteger("42debb9da5b3d88cc956e08787ec3f3a09bba5f48b889a74aaf53174" +
+ "aa0fbe7e3c5b8fcd7a53bef563b0e98560328960a9517f4014d3325f" +
+ "c7962bf1e049370d76d1314a76137e792f3f0db859d095e4a5b93202" +
+ "4f079ecf2ef09c797452b0770e1350782ed57ddf794979dcef23cb96" +
+ "f183061965c4ebc93c9c71c56b925955a75f94cccf1449ac43d586d0" +
+ "beee43251b0b2287349d68de0d144403f13e802f4146d882e057af19" +
+ "b6f6275c6676c8fa0e3ca2713a3257fd1b27d0639f695e347d8d1cf9" +
+ "ac819a26ca9b04cb0eb9b7b035988d15bbac65212a55239cfc7e58fa" +
+ "e38d7250ab9991ffbc97134025fe8ce04c4399ad96569be91a546f49" +
+ "78693c7a", 16),
+ new DSAValidationParameters(Hex.decode("b0b4417601b59cbc9d8ac8f935cadaec4f5fbb2f23785609ae466748d9b5a536"), 497));
+
+ localSetGlobalProperty(Property.DSA_DEFAULT_PARAMS, def512Params, def768Params, def1024Params, def2048Params);
+ localSetGlobalProperty(Property.DH_DEFAULT_PARAMS, toDH(def512Params), toDH(def768Params), toDH(def1024Params), toDH(def2048Params));
+ }
+
+ private CryptoServicesRegistrar()
+ {
+
+ }
+
+ /**
+ * Return the default source of randomness.
+ *
+ * @return the default SecureRandom
+ * @throws IllegalStateException if no source of randomness has been provided.
+ */
+ public static SecureRandom getSecureRandom()
+ {
+ if (defaultSecureRandom == null)
+ {
+ return new SecureRandom();
+ }
+
+ return defaultSecureRandom;
+ }
+
+ /**
+ * Set a default secure random to be used where none is otherwise provided.
+ *
+ * @param secureRandom the SecureRandom to use as the default.
+ */
+ public static void setSecureRandom(SecureRandom secureRandom)
+ {
+ checkPermission(CanSetDefaultRandom);
+
+ defaultSecureRandom = secureRandom;
+ }
+
+ /**
+ * Return the default value for a particular property if one exists. The look up is done on the thread's local
+ * configuration first and then on the global configuration in no local configuration exists.
+ *
+ * @param property the property to look up.
+ * @param <T> the type to be returned
+ * @return null if the property is not set, the default value otherwise,
+ */
+ public static <T> T getProperty(Property property)
+ {
+ Object[] values = lookupProperty(property);
+
+ if (values != null)
+ {
+ return (T)values[0];
+ }
+
+ return null;
+ }
+
+ private static Object[] lookupProperty(Property property)
+ {
+ Map<String, Object[]> properties = threadProperties.get();
+ Object[] values;
+
+ if (properties == null || !properties.containsKey(property.name))
+ {
+ values = globalProperties.get(property.name);
+ }
+ else
+ {
+ values = properties.get(property.name);
+ }
+ return values;
+ }
+
+ /**
+ * Return an array representing the current values for a sized property such as DH_DEFAULT_PARAMS or
+ * DSA_DEFAULT_PARAMS.
+ *
+ * @param property the name of the property to look up.
+ * @param <T> the base type of the array to be returned.
+ * @return null if the property is not set, an array of the current values otherwise.
+ */
+ public static <T> T[] getSizedProperty(Property property)
+ {
+ Object[] values = lookupProperty(property);
+
+ if (values == null)
+ {
+ return null;
+ }
+
+ return (T[])values.clone();
+ }
+
+ /**
+ * Return the value for a specific size for a sized property such as DH_DEFAULT_PARAMS or
+ * DSA_DEFAULT_PARAMS.
+ *
+ * @param property the name of the property to look up.
+ * @param size the size (in bits) of the defining value in the property type.
+ * @param <T> the type of the value to be returned.
+ * @return the current value for the size, null if there is no value set,
+ */
+ public static <T> T getSizedProperty(Property property, int size)
+ {
+ Object[] values = lookupProperty(property);
+
+ if (values == null)
+ {
+ return null;
+ }
+
+ if (property.type.isAssignableFrom(DHParameters.class))
+ {
+ for (int i = 0; i != values.length; i++)
+ {
+ DHParameters params = (DHParameters)values[i];
+
+ if (params.getP().bitLength() == size)
+ {
+ return (T)params;
+ }
+ }
+ }
+ else if (property.type.isAssignableFrom(DSAParameters.class))
+ {
+ for (int i = 0; i != values.length; i++)
+ {
+ DSAParameters params = (DSAParameters)values[i];
+
+ if (params.getP().bitLength() == size)
+ {
+ return (T)params;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Set the value of the the passed in property on the current thread only. More than
+ * one value can be passed in for a sized property. If more than one value is provided the
+ * first value in the argument list becomes the default value.
+ *
+ * @param property the name of the property to set.
+ * @param propertyValue the values to assign to the property.
+ * @param <T> the base type of the property value.
+ */
+ public static <T> void setThreadProperty(Property property, T... propertyValue)
+ {
+ checkPermission(CanSetThreadProperty);
+
+ if (!property.type.isAssignableFrom(propertyValue[0].getClass()))
+ {
+ throw new IllegalArgumentException("Bad property value passed");
+ }
+
+ localSetThread(property, propertyValue.clone());
+ }
+
+ /**
+ * Set the value of the the passed in property globally in the JVM. More than
+ * one value can be passed in for a sized property. If more than one value is provided the
+ * first value in the argument list becomes the default value.
+ *
+ * @param property the name of the property to set.
+ * @param propertyValue the values to assign to the property.
+ * @param <T> the base type of the property value.
+ */
+ public static <T> void setGlobalProperty(Property property, T... propertyValue)
+ {
+ checkPermission(CanSetDefaultProperty);
+
+ localSetGlobalProperty(property, propertyValue.clone());
+ }
+
+ private static <T> void localSetThread(Property property, T[] propertyValue)
+ {
+ Map<String, Object[]> properties = threadProperties.get();
+
+ if (properties == null)
+ {
+ properties = new HashMap<String, Object[]>();
+ threadProperties.set(properties);
+ }
+
+ properties.put(property.name, propertyValue);
+ }
+
+ private static <T> void localSetGlobalProperty(Property property, T... propertyValue)
+ {
+ if (!property.type.isAssignableFrom(propertyValue[0].getClass()))
+ {
+ throw new IllegalArgumentException("Bad property value passed");
+ }
+
+ // set the property for the current thread as well to avoid mass confusion
+ localSetThread(property, propertyValue);
+
+ globalProperties.put(property.name, propertyValue);
+ }
+
+ /**
+ * Clear the global value for the passed in property.
+ *
+ * @param property the property to be cleared.
+ * @param <T> the base type of the property value
+ * @return an array of T if a value was previously set, null otherwise.
+ */
+ public static <T> T[] clearGlobalProperty(Property property)
+ {
+ checkPermission(CanSetDefaultProperty);
+
+ // clear the property for the current thread as well to avoid confusion
+ localClearThreadProperty(property);
+
+ return (T[])globalProperties.remove(property.name);
+ }
+
+ /**
+ * Clear the thread local value for the passed in property.
+ *
+ * @param property the property to be cleared.
+ * @param <T> the base type of the property value
+ * @return an array of T if a value was previously set, null otherwise.
+ */
+ public static <T> T[] clearThreadProperty(Property property)
+ {
+ checkPermission(CanSetThreadProperty);
+
+ return (T[])localClearThreadProperty(property);
+ }
+
+ private static Object[] localClearThreadProperty(Property property)
+ {
+ Map<String, Object[]> properties = threadProperties.get();
+
+ if (properties == null)
+ {
+ properties = new HashMap<String, Object[]>();
+ threadProperties.set(properties);
+ }
+
+ return properties.remove(property.name);
+ }
+
+ private static void checkPermission(final Permission permission)
+ {
+ final SecurityManager securityManager = System.getSecurityManager();
+
+ if (securityManager != null)
+ {
+ AccessController.doPrivileged(new PrivilegedAction<Object>()
+ {
+ public Object run()
+ {
+ securityManager.checkPermission(permission);
+
+ return null;
+ }
+ });
+ }
+ }
+
+ private static DHParameters toDH(DSAParameters dsaParams)
+ {
+ int pSize = dsaParams.getP().bitLength();
+ int m = chooseLowerBound(pSize);
+ return new DHParameters(dsaParams.getP(), dsaParams.getG(), dsaParams.getQ(), m, 0, null,
+ new DHValidationParameters(dsaParams.getValidationParameters().getSeed(), dsaParams.getValidationParameters().getCounter()));
+ }
+
+ // based on lower limit of at least 2^{2 * bits_of_security}
+ private static int chooseLowerBound(int pSize)
+ {
+ int m = 160;
+ if (pSize > 1024)
+ {
+ if (pSize <= 2048)
+ {
+ m = 224;
+ }
+ else if (pSize <= 3072)
+ {
+ m = 256;
+ }
+ else if (pSize <= 7680)
+ {
+ m = 384;
+ }
+ else
+ {
+ m = 512;
+ }
+ }
+ return m;
+ }
+
+ /**
+ * Available properties that can be set.
+ */
+ public static final class Property
+ {
+ /**
+ * The parameters to be used for processing implicitlyCA X9.62 parameters
+ */
+ public static final Property EC_IMPLICITLY_CA = new Property("ecImplicitlyCA", X9ECParameters.class);
+ /**
+ * The default parameters for a particular size of Diffie-Hellman key.This is a sized property.
+ */
+ public static final Property DH_DEFAULT_PARAMS= new Property("dhDefaultParams", DHParameters.class);
+ /**
+ * The default parameters for a particular size of DSA key. This is a sized property.
+ */
+ public static final Property DSA_DEFAULT_PARAMS= new Property("dsaDefaultParams", DSAParameters.class);
+ private final String name;
+ private final Class type;
+
+ private Property(String name, Class type)
+ {
+ this.name = name;
+ this.type = type;
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/DSAExt.java b/bcprov/src/main/java/org/bouncycastle/crypto/DSAExt.java
new file mode 100644
index 00000000..b6099619
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/DSAExt.java
@@ -0,0 +1,16 @@
+package org.bouncycastle.crypto;
+
+import java.math.BigInteger;
+
+/**
+ * An "extended" interface for classes implementing DSA-style algorithms, that provides access to
+ * the group order.
+ */
+public interface DSAExt
+ extends DSA
+{
+ /**
+ * Get the order of the group that the r, s values in signatures belong to.
+ */
+ public BigInteger getOrder();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/RawAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/RawAgreement.java
new file mode 100644
index 00000000..4bac34d1
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/RawAgreement.java
@@ -0,0 +1,10 @@
+package org.bouncycastle.crypto;
+
+public interface RawAgreement
+{
+ void init(CipherParameters parameters);
+
+ int getAgreementSize();
+
+ void calculateAgreement(CipherParameters publicKey, byte[] buf, int off);
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java
index 09aadfbf..77d8ac91 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/StreamBlockCipher.java
@@ -32,15 +32,14 @@ public abstract class StreamBlockCipher
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 short");
- }
-
if (inOff + len > in.length)
{
throw new DataLengthException("input buffer too small");
}
+ if (outOff + len > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
int inStart = inOff;
int inEnd = inOff + len;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
index 4dd80d0a..34908191 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
@@ -68,8 +68,16 @@ public class DHBasicAgreement
throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters.");
}
- BigInteger result = pub.getY().modPow(key.getX(), dhParams.getP());
- if (result.compareTo(ONE) == 0)
+ BigInteger p = dhParams.getP();
+
+ BigInteger peerY = pub.getY();
+ if (peerY == null || peerY.compareTo(ONE) <= 0 || peerY.compareTo(p.subtract(ONE)) >= 0)
+ {
+ throw new IllegalArgumentException("Diffie-Hellman public key is weak");
+ }
+
+ BigInteger result = peerY.modPow(key.getX(), p);
+ if (result.equals(ONE))
{
throw new IllegalStateException("Shared key can't be 1");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
index 45ff0d36..49a79c81 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
@@ -4,11 +4,11 @@ import java.math.BigInteger;
import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-// BEGIN android-added
-import org.bouncycastle.math.ec.ECCurve;
-// END android-added
+import org.bouncycastle.math.ec.ECAlgorithms;
+import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECPoint;
/**
@@ -44,29 +44,30 @@ public class ECDHBasicAgreement
public BigInteger calculateAgreement(
CipherParameters pubKey)
{
- // BEGIN android-changed
- ECPoint peerPoint = ((ECPublicKeyParameters) pubKey).getQ();
- ECCurve myCurve = key.getParameters().getCurve();
- if (peerPoint.isInfinity()) {
- throw new IllegalStateException("Infinity is not a valid public key for ECDH");
- }
- try {
- myCurve.validatePoint(peerPoint.getXCoord().toBigInteger(),
- peerPoint.getYCoord().toBigInteger());
- } catch (IllegalArgumentException ex) {
- throw new IllegalStateException("The peer public key must be on the curve for ECDH");
- }
- // Explicitly construct a public key using the private key's curve.
- ECPoint pubPoint = myCurve.createPoint(peerPoint.getXCoord().toBigInteger(),
- peerPoint.getYCoord().toBigInteger());
ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
- if (!pub.getParameters().equals(key.getParameters()))
+ ECDomainParameters params = key.getParameters();
+ if (!params.equals(pub.getParameters()))
{
throw new IllegalStateException("ECDH public key has wrong domain parameters");
}
- ECPoint P = pubPoint.multiply(key.getD()).normalize();
- // END android-changed
+ BigInteger d = key.getD();
+
+ // Always perform calculations on the exact curve specified by our private key's parameters
+ ECPoint Q = ECAlgorithms.cleanPoint(params.getCurve(), pub.getQ());
+ if (Q.isInfinity())
+ {
+ throw new IllegalStateException("Infinity is not a valid public key for ECDH");
+ }
+
+ BigInteger h = params.getH();
+ if (!h.equals(ECConstants.ONE))
+ {
+ d = params.getHInv().multiply(d).mod(params.getN());
+ Q = ECAlgorithms.referenceMultiply(Q, h);
+ }
+
+ ECPoint P = Q.multiply(d).normalize();
if (P.isInfinity())
{
throw new IllegalStateException("Infinity is not a valid agreement value for ECDH");
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/NullDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/NullDigest.java
index 6cb0d4ac..9219d9df 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/NullDigest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/NullDigest.java
@@ -3,12 +3,13 @@ package org.bouncycastle.crypto.digests;
import java.io.ByteArrayOutputStream;
import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.util.Arrays;
public class NullDigest
implements Digest
{
- private ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ private OpenByteArrayOutputStream bOut = new OpenByteArrayOutputStream();
public String getAlgorithmName()
{
@@ -32,17 +33,33 @@ public class NullDigest
public int doFinal(byte[] out, int outOff)
{
- byte[] res = bOut.toByteArray();
+ int size = bOut.size();
- System.arraycopy(res, 0, out, outOff, res.length);
+ bOut.copy(out, outOff);
reset();
- return res.length;
+ return size;
}
public void reset()
{
bOut.reset();
}
+
+ private static class OpenByteArrayOutputStream
+ extends ByteArrayOutputStream
+ {
+ public void reset()
+ {
+ super.reset();
+
+ Arrays.clear(buf);
+ }
+
+ void copy(byte[] out, int outOff)
+ {
+ System.arraycopy(buf, 0, out, outOff, this.size());
+ }
+ }
} \ No newline at end of file
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 b81e7c0a..4290d200 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java
@@ -110,7 +110,7 @@ public class SHA1Digest
}
X[14] = (int)(bitLength >>> 32);
- X[15] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)bitLength;
}
public int doFinal(
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
index 2c23bed1..006047cc 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/CustomNamedCurves.java
@@ -6,14 +6,17 @@ import java.util.Hashtable;
import java.util.Vector;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.asn1.cryptlib.CryptlibObjectIdentifiers;
+import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECParametersHolder;
import org.bouncycastle.asn1.x9.X9ECPoint;
import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
// BEGIN android-removed
// import org.bouncycastle.math.ec.custom.djb.Curve25519;
+// import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve;
// import org.bouncycastle.math.ec.custom.sec.SecP128R1Curve;
// import org.bouncycastle.math.ec.custom.sec.SecP160K1Curve;
// import org.bouncycastle.math.ec.custom.sec.SecP160R1Curve;
@@ -624,10 +627,25 @@ public class CustomNamedCurves
return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
}
};
+
+ /*
+ * sm2p256v1
+ *
+ static X9ECParametersHolder sm2p256v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ byte[] S = null;
+ ECCurve curve = configureCurve(new SM2P256V1Curve());
+ X9ECPoint G = new X9ECPoint(curve, Hex.decode("04"
+ + "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
+ + "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"));
+ return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S);
+ }
+ };
*/
// END Android-removed: Unsupported curves
-
static final Hashtable nameToCurve = new Hashtable();
static final Hashtable nameToOID = new Hashtable();
static final Hashtable oidToCurve = new Hashtable();
@@ -668,7 +686,7 @@ public class CustomNamedCurves
{
// BEGIN Android-removed: Unsupported curves
/*
- defineCurve("curve25519", curve25519);
+ defineCurveWithOID("curve25519", CryptlibObjectIdentifiers.curvey25519, curve25519);
// defineCurveWithOID("secp112r1", SECObjectIdentifiers.secp112r1, secp112r1);
// defineCurveWithOID("secp112r2", SECObjectIdentifiers.secp112r2, secp112r2);
@@ -709,6 +727,8 @@ public class CustomNamedCurves
defineCurveWithOID("sect571k1", SECObjectIdentifiers.sect571k1, sect571k1);
defineCurveWithOID("sect571r1", SECObjectIdentifiers.sect571r1, sect571r1);
+ defineCurveWithOID("sm2p256v1", GMObjectIdentifiers.sm2p256v1, sm2p256v1);
+
defineCurveAlias("B-163", SECObjectIdentifiers.sect163r2);
defineCurveAlias("B-233", SECObjectIdentifiers.sect233r1);
defineCurveAlias("B-283", SECObjectIdentifiers.sect283r1);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java
index 8df10697..417161e4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java
@@ -4,6 +4,7 @@ import java.security.SecureRandom;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.InvalidCipherTextException;
@@ -86,7 +87,7 @@ public class OAEPEncoding
}
else
{
- this.random = new SecureRandom();
+ this.random = CryptoServicesRegistrar.getSecureRandom();
}
engine.init(forEncryption, param);
@@ -224,10 +225,17 @@ public class OAEPEncoding
// on encryption, we need to make sure our decrypted block comes back
// the same size.
//
+ boolean wrongData = (block.length < (2 * defHash.length) + 1);
- System.arraycopy(data, 0, block, block.length - data.length, data.length);
-
- boolean shortData = (block.length < (2 * defHash.length) + 1);
+ if (data.length <= block.length)
+ {
+ System.arraycopy(data, 0, block, block.length - data.length, data.length);
+ }
+ else
+ {
+ System.arraycopy(data, 0, block, 0, block.length);
+ wrongData = true;
+ }
//
// unmask the seed.
@@ -281,7 +289,7 @@ public class OAEPEncoding
start++;
- if (defHashWrong | shortData | dataStartWrong)
+ if (defHashWrong | wrongData | dataStartWrong)
{
Arrays.fill(block, (byte)0);
throw new InvalidCipherTextException("data wrong");
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 e79557f4..cfd6dcf9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
@@ -6,6 +6,7 @@ import java.security.SecureRandom;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ParametersWithRandom;
@@ -141,7 +142,7 @@ public class PKCS1Encoding
kParam = (AsymmetricKeyParameter)param;
if (!kParam.isPrivate() && forEncryption)
{
- this.random = new SecureRandom();
+ this.random = CryptoServicesRegistrar.getSecureRandom();
}
}
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 6980fd08..58ea618b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.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;
/**
* a class that provides a basic DES engine.
@@ -407,15 +408,8 @@ public class DESEngine
{
int work, right, left;
- left = (in[inOff + 0] & 0xff) << 24;
- left |= (in[inOff + 1] & 0xff) << 16;
- left |= (in[inOff + 2] & 0xff) << 8;
- left |= (in[inOff + 3] & 0xff);
-
- right = (in[inOff + 4] & 0xff) << 24;
- right |= (in[inOff + 5] & 0xff) << 16;
- right |= (in[inOff + 6] & 0xff) << 8;
- right |= (in[inOff + 7] & 0xff);
+ left = Pack.bigEndianToInt(in, inOff);
+ right = Pack.bigEndianToInt(in, inOff + 4);
work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
right ^= work;
@@ -429,11 +423,11 @@ public class DESEngine
work = ((right >>> 8) ^ left) & 0x00ff00ff;
left ^= work;
right ^= (work << 8);
- right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
+ right = (right << 1) | (right >>> 31);
work = (left ^ right) & 0xaaaaaaaa;
left ^= work;
right ^= work;
- left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
+ left = (left << 1) | (left >>> 31);
for (int round = 0; round < 8; round++)
{
@@ -483,13 +477,7 @@ public class DESEngine
left ^= work;
right ^= (work << 4);
- out[outOff + 0] = (byte)((right >>> 24) & 0xff);
- out[outOff + 1] = (byte)((right >>> 16) & 0xff);
- out[outOff + 2] = (byte)((right >>> 8) & 0xff);
- out[outOff + 3] = (byte)(right & 0xff);
- out[outOff + 4] = (byte)((left >>> 24) & 0xff);
- out[outOff + 5] = (byte)((left >>> 16) & 0xff);
- out[outOff + 6] = (byte)((left >>> 8) & 0xff);
- out[outOff + 7] = (byte)(left & 0xff);
+ Pack.intToBigEndian(right, out, outOff);
+ Pack.intToBigEndian(left, out, outOff + 4);
}
}
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 652d8ac8..76f20bbc 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
@@ -3,6 +3,7 @@ package org.bouncycastle.crypto.engines;
import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.Wrapper;
@@ -79,7 +80,7 @@ public class DESedeWrapEngine
}
else
{
- sr = new SecureRandom();
+ sr = CryptoServicesRegistrar.getSecureRandom();
}
if (param instanceof KeyParameter)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
index d74e2b3c..65ac67bd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
@@ -5,6 +5,7 @@ import java.security.SecureRandom;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyParameters;
@@ -45,7 +46,7 @@ public class RSABlindedEngine
else
{
key = (RSAKeyParameters)param;
- random = new SecureRandom();
+ random = CryptoServicesRegistrar.getSecureRandom();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java
index 510cd5a5..ca482d9b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java
@@ -1,12 +1,13 @@
package org.bouncycastle.crypto.engines;
+import java.math.BigInteger;
+
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-
-import java.math.BigInteger;
+import org.bouncycastle.util.Arrays;
/**
* this does your basic RSA algorithm.
@@ -142,20 +143,29 @@ class RSACoreEngine
return tmp;
}
+
+ return output;
}
else
{
+ byte[] rv;
if (output[0] == 0) // have ended up with an extra zero byte, copy down.
{
- byte[] tmp = new byte[output.length - 1];
+ rv = new byte[output.length - 1];
- System.arraycopy(output, 1, tmp, 0, tmp.length);
+ System.arraycopy(output, 1, rv, 0, rv.length);
+ }
+ else // maintain decryption time
+ {
+ rv = new byte[output.length];
- return tmp;
+ System.arraycopy(output, 0, rv, 0, rv.length);
}
- }
- return output;
+ Arrays.fill(output, (byte)0);
+
+ return rv;
+ }
}
public BigInteger processBlock(BigInteger input)
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 6795ec96..17d9403b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java
@@ -27,7 +27,7 @@ class DHKeyGeneratorHelper
int minWeight = limit >>> 2;
for (;;)
{
- BigInteger x = new BigInteger(limit, random).setBit(limit - 1);
+ BigInteger x = BigIntegers.createRandomBigInteger(limit, random).setBit(limit - 1);
if (WNafUtil.getNafWeight(x) >= minWeight)
{
return x;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersGenerator.java
index f5d42642..9b7bb863 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersGenerator.java
@@ -1,10 +1,10 @@
package org.bouncycastle.crypto.generators;
-import org.bouncycastle.crypto.params.DHParameters;
-
import java.math.BigInteger;
import java.security.SecureRandom;
+import org.bouncycastle.crypto.params.DHParameters;
+
public class DHParametersGenerator
{
private int size;
@@ -35,6 +35,7 @@ public class DHParametersGenerator
* returning the DHParameters object.
* <p>
* Note: can take a while...
+ * @return a generated Diffie-Hellman parameters object.
*/
public DHParameters generateParameters()
{
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 1075f22e..c857af1e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DHParametersHelper.java
@@ -36,7 +36,7 @@ class DHParametersHelper
{
// Android-added: Log long-running operation
tries++;
- q = new BigInteger(qLength, 2, random);
+ q = BigIntegers.createRandomPrime(qLength, 2, random);
// p <- 2q + 1
p = q.shiftLeft(1).add(ONE);
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 961b367d..cb09f73f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
@@ -113,6 +113,7 @@ public class DSAParametersGenerator
* returning the DSAParameters object.
* <p>
* Note: can take a while...
+ * @return a generated DSA parameters object.
*/
public DSAParameters generateParameters()
{
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 c7660719..502f8b3e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
@@ -5,6 +5,7 @@ import java.security.SecureRandom;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
@@ -15,6 +16,7 @@ import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.math.ec.WNafUtil;
+import org.bouncycastle.util.BigIntegers;
public class ECKeyPairGenerator
implements AsymmetricCipherKeyPairGenerator, ECConstants
@@ -32,7 +34,7 @@ public class ECKeyPairGenerator
if (this.random == null)
{
- this.random = new SecureRandom();
+ this.random = CryptoServicesRegistrar.getSecureRandom();
}
}
@@ -49,7 +51,7 @@ public class ECKeyPairGenerator
BigInteger d;
for (;;)
{
- d = new BigInteger(nBitLength, random);
+ d = BigIntegers.createRandomBigInteger(nBitLength, random);
if (d.compareTo(TWO) < 0 || (d.compareTo(n) >= 0))
{
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 beb1aee2..eadbaa6c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
@@ -10,6 +10,7 @@ import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.math.Primes;
import org.bouncycastle.math.ec.WNafUtil;
+import org.bouncycastle.util.BigIntegers;
/**
* an RSA key pair generator.
@@ -159,7 +160,7 @@ public class RSAKeyPairGenerator
{
for (int i = 0; i != 5 * bitlength; i++)
{
- BigInteger p = new BigInteger(bitlength, 1, param.getRandom());
+ BigInteger p = BigIntegers.createRandomPrime(bitlength, 1, param.getRandom());
if (p.mod(e).equals(ONE))
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
index 64b076dd..ea807067 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
@@ -4,6 +4,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.StreamBlockCipher;
/**
@@ -135,7 +136,7 @@ public class CTSBlockCipher
{
if ((outOff + length) > out.length)
{
- throw new DataLengthException("output buffer too short");
+ throw new OutputLengthException("output buffer too short");
}
}
@@ -192,7 +193,7 @@ public class CTSBlockCipher
{
if (bufOff + outOff > out.length)
{
- throw new DataLengthException("output buffer to small in doFinal");
+ throw new OutputLengthException("output buffer to small in doFinal");
}
int blockSize = cipher.getBlockSize();
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 c6453a3b..75343d8b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
@@ -5,11 +5,11 @@ 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.BasicGCMExponentiator;
import org.bouncycastle.crypto.modes.gcm.GCMExponentiator;
import org.bouncycastle.crypto.modes.gcm.GCMMultiplier;
import org.bouncycastle.crypto.modes.gcm.GCMUtil;
-import org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
-import org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
+import org.bouncycastle.crypto.modes.gcm.Tables4kGCMMultiplier;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
@@ -73,8 +73,7 @@ public class GCMBlockCipher
if (m == null)
{
- // TODO Consider a static property specifying default multiplier
- m = new Tables8kGCMMultiplier();
+ m = new Tables4kGCMMultiplier();
}
this.cipher = c;
@@ -268,6 +267,7 @@ public class GCMBlockCipher
throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes");
}
// END Android-added: Max input size limitation from NIST.
+
atBlock[atBlockPos] = in;
if (++atBlockPos == BLOCK_SIZE)
{
@@ -280,11 +280,13 @@ public class GCMBlockCipher
public void processAADBytes(byte[] in, int inOff, int len)
{
+ checkStatus();
// BEGIN Android-added: Max input size limitation from NIST.
if (getTotalInputSizeAfterNewInput(len) > MAX_INPUT_SIZE) {
throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes");
}
// END Android-added: Max input size limitation from NIST.
+
for (int i = 0; i < len; ++i)
{
atBlock[atBlockPos] = in[inOff + i];
@@ -328,11 +330,20 @@ public class GCMBlockCipher
throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes");
}
// END Android-added: Max input size limitation from NIST.
-
+
bufBlock[bufOff] = in;
if (++bufOff == bufBlock.length)
{
- outputBlock(out, outOff);
+ processBlock(bufBlock, 0, out, outOff);
+ if (forEncryption)
+ {
+ bufOff = 0;
+ }
+ else
+ {
+ System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize);
+ bufOff = macSize;
+ }
return BLOCK_SIZE;
}
return 0;
@@ -348,45 +359,61 @@ public class GCMBlockCipher
}
// END Android-added: Max input size limitation from NIST.
- if (in.length < (inOff + len))
+ if ((in.length - inOff) < len)
{
throw new DataLengthException("Input buffer too short");
}
+
int resultLen = 0;
- for (int i = 0; i < len; ++i)
+ if (forEncryption)
{
- bufBlock[bufOff] = in[inOff + i];
- if (++bufOff == bufBlock.length)
+ if (bufOff != 0)
{
- outputBlock(out, outOff + resultLen);
- resultLen += BLOCK_SIZE;
+ while (len > 0)
+ {
+ --len;
+ bufBlock[bufOff] = in[inOff++];
+ if (++bufOff == BLOCK_SIZE)
+ {
+ processBlock(bufBlock, 0, out, outOff);
+ bufOff = 0;
+ resultLen += BLOCK_SIZE;
+ break;
+ }
+ }
}
- }
- return resultLen;
- }
+ while (len >= BLOCK_SIZE)
+ {
+ processBlock(in, inOff, out, outOff + resultLen);
+ inOff += BLOCK_SIZE;
+ len -= BLOCK_SIZE;
+ resultLen += BLOCK_SIZE;
+ }
- private void outputBlock(byte[] output, int offset)
- {
- if (output.length < (offset + BLOCK_SIZE))
- {
- throw new OutputLengthException("Output buffer too short");
- }
- if (totalLength == 0)
- {
- initCipher();
- }
- gCTRBlock(bufBlock, output, offset);
- if (forEncryption)
- {
- bufOff = 0;
+ if (len > 0)
+ {
+ System.arraycopy(in, inOff, bufBlock, 0, len);
+ bufOff = len;
+ }
}
else
{
- System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize);
- bufOff = macSize;
+ for (int i = 0; i < len; ++i)
+ {
+ bufBlock[bufOff] = in[inOff + i];
+ if (++bufOff == bufBlock.length)
+ {
+ processBlock(bufBlock, 0, out, outOff + resultLen);
+ System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize);
+ bufOff = macSize;
+ resultLen += BLOCK_SIZE;
+ }
+ }
}
+
+ return resultLen;
}
public int doFinal(byte[] out, int outOff)
@@ -403,7 +430,7 @@ public class GCMBlockCipher
if (forEncryption)
{
- if (out.length < (outOff + extra + macSize))
+ if ((out.length - outOff) < (extra + macSize))
{
throw new OutputLengthException("Output buffer too short");
}
@@ -416,7 +443,7 @@ public class GCMBlockCipher
}
extra -= macSize;
- if (out.length < (outOff + extra))
+ if ((out.length - outOff) < extra)
{
throw new OutputLengthException("Output buffer too short");
}
@@ -424,7 +451,7 @@ public class GCMBlockCipher
if (extra > 0)
{
- gCTRPartial(bufBlock, 0, extra, out, outOff);
+ processPartial(bufBlock, 0, extra, out, outOff);
}
atLength += atBlockPos;
@@ -457,7 +484,7 @@ public class GCMBlockCipher
byte[] H_c = new byte[16];
if (exp == null)
{
- exp = new Tables1kGCMExponentiator();
+ exp = new BasicGCMExponentiator();
exp.init(H);
}
exp.exponentiateX(c, H_c);
@@ -556,27 +583,52 @@ public class GCMBlockCipher
}
}
- private void gCTRBlock(byte[] block, byte[] out, int outOff)
+ private void processBlock(byte[] buf, int bufOff, byte[] out, int outOff)
{
- byte[] tmp = getNextCounterBlock();
+ if ((out.length - outOff) < BLOCK_SIZE)
+ {
+ throw new OutputLengthException("Output buffer too short");
+ }
+ if (totalLength == 0)
+ {
+ initCipher();
+ }
- GCMUtil.xor(tmp, block);
- System.arraycopy(tmp, 0, out, outOff, BLOCK_SIZE);
+ byte[] ctrBlock = new byte[BLOCK_SIZE];
+ getNextCTRBlock(ctrBlock);
- gHASHBlock(S, forEncryption ? tmp : block);
+ if (forEncryption)
+ {
+ GCMUtil.xor(ctrBlock, buf, bufOff);
+ gHASHBlock(S, ctrBlock);
+ System.arraycopy(ctrBlock, 0, out, outOff, BLOCK_SIZE);
+ }
+ else
+ {
+ gHASHBlock(S, buf, bufOff);
+ GCMUtil.xor(ctrBlock, 0, buf, bufOff, out, outOff);
+ }
totalLength += BLOCK_SIZE;
}
- private void gCTRPartial(byte[] buf, int off, int len, byte[] out, int outOff)
+ private void processPartial(byte[] buf, int off, int len, byte[] out, int outOff)
{
- byte[] tmp = getNextCounterBlock();
+ byte[] ctrBlock = new byte[BLOCK_SIZE];
+ getNextCTRBlock(ctrBlock);
- GCMUtil.xor(tmp, buf, off, len);
- System.arraycopy(tmp, 0, out, outOff, len);
-
- gHASHPartial(S, forEncryption ? tmp : buf, 0, len);
+ if (forEncryption)
+ {
+ GCMUtil.xor(buf, off, ctrBlock, 0, len);
+ gHASHPartial(S, buf, off, len);
+ }
+ else
+ {
+ gHASHPartial(S, buf, off, len);
+ GCMUtil.xor(buf, off, ctrBlock, 0, len);
+ }
+ System.arraycopy(buf, off, out, outOff, len);
totalLength += len;
}
@@ -595,13 +647,19 @@ public class GCMBlockCipher
multiplier.multiplyH(Y);
}
+ private void gHASHBlock(byte[] Y, byte[] b, int off)
+ {
+ GCMUtil.xor(Y, b, off);
+ multiplier.multiplyH(Y);
+ }
+
private void gHASHPartial(byte[] Y, byte[] b, int off, int len)
{
GCMUtil.xor(Y, b, off, len);
multiplier.multiplyH(Y);
}
- private byte[] getNextCounterBlock()
+ private void getNextCTRBlock(byte[] block)
{
if (blocksRemaining == 0)
{
@@ -615,10 +673,7 @@ public class GCMBlockCipher
c += counter[13] & 0xFF; counter[13] = (byte)c; c >>>= 8;
c += counter[12] & 0xFF; counter[12] = (byte)c;
- byte[] tmp = new byte[BLOCK_SIZE];
- // TODO Sure would be nice if ciphers could operate on int[]
- cipher.processBlock(counter, 0, tmp, 0);
- return tmp;
+ cipher.processBlock(counter, 0, block, 0);
}
private void checkStatus()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
new file mode 100644
index 00000000..7316a04b
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
@@ -0,0 +1,37 @@
+package org.bouncycastle.crypto.modes.gcm;
+
+import org.bouncycastle.util.Arrays;
+
+public class BasicGCMExponentiator
+ implements GCMExponentiator
+{
+ private long[] x;
+
+ public void init(byte[] x)
+ {
+ this.x = GCMUtil.asLongs(x);
+ }
+
+ public void exponentiateX(long pow, byte[] output)
+ {
+ // Initial value is little-endian 1
+ long[] y = GCMUtil.oneAsLongs();
+
+ if (pow > 0)
+ {
+ long[] powX = Arrays.clone(x);
+ do
+ {
+ if ((pow & 1L) != 0)
+ {
+ GCMUtil.multiply(y, powX);
+ }
+ GCMUtil.square(powX, powX);
+ pow >>>= 1;
+ }
+ while (pow > 0);
+ }
+
+ GCMUtil.asBytes(y, output);
+ }
+}
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 f08f71f3..3e24a15f 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,5 +1,6 @@
package org.bouncycastle.crypto.modes.gcm;
+import org.bouncycastle.math.raw.Interleave;
import org.bouncycastle.util.Pack;
public abstract class GCMUtil
@@ -7,28 +8,6 @@ public abstract class GCMUtil
private static final int E1 = 0xe1000000;
private static final long E1L = (E1 & 0xFFFFFFFFL) << 32;
- private static int[] generateLookup()
- {
- int[] lookup = new int[256];
-
- for (int c = 0; c < 256; ++c)
- {
- int v = 0;
- for (int i = 7; i >= 0; --i)
- {
- if ((c & (1 << i)) != 0)
- {
- v ^= (E1 >>> (7 - i));
- }
- }
- lookup[c] = v;
- }
-
- return lookup;
- }
-
- private static final int[] LOOKUP = generateLookup();
-
public static byte[] oneAsBytes()
{
byte[] tmp = new byte[16];
@@ -98,216 +77,214 @@ public abstract class GCMUtil
Pack.bigEndianToLong(x, 0, z);
}
+ public static void copy(int[] x, int[] z)
+ {
+ z[0] = x[0];
+ z[1] = x[1];
+ z[2] = x[2];
+ z[3] = x[3];
+ }
+
+ public static void copy(long[] x, long[] z)
+ {
+ z[0] = x[0];
+ z[1] = x[1];
+ }
+
+ public static void divideP(long[] x, long[] z)
+ {
+ long x0 = x[0], x1 = x[1];
+ long m = x0 >> 63;
+ x0 ^= (m & E1L);
+ z[0] = (x0 << 1) | (x1 >>> 63);
+ z[1] = (x1 << 1) | -m;
+ }
+
public static void multiply(byte[] x, byte[] y)
{
- int[] t1 = GCMUtil.asInts(x);
- int[] t2 = GCMUtil.asInts(y);
+ long[] t1 = GCMUtil.asLongs(x);
+ long[] t2 = GCMUtil.asLongs(y);
GCMUtil.multiply(t1, t2);
GCMUtil.asBytes(t1, x);
}
public static void multiply(int[] x, int[] y)
{
- int r00 = x[0], r01 = x[1], r02 = x[2], r03 = x[3];
- int r10 = 0, r11 = 0, r12 = 0, r13 = 0;
-
+ int y0 = y[0], y1 = y[1], y2 = y[2], y3 = y[3];
+ int z0 = 0, z1 = 0, z2 = 0, z3 = 0;
+
for (int i = 0; i < 4; ++i)
{
- int bits = y[i];
+ int bits = x[i];
for (int j = 0; j < 32; ++j)
{
int m1 = bits >> 31; bits <<= 1;
- r10 ^= (r00 & m1);
- r11 ^= (r01 & m1);
- r12 ^= (r02 & m1);
- r13 ^= (r03 & m1);
-
- int m2 = (r03 << 31) >> 8;
- r03 = (r03 >>> 1) | (r02 << 31);
- r02 = (r02 >>> 1) | (r01 << 31);
- r01 = (r01 >>> 1) | (r00 << 31);
- r00 = (r00 >>> 1) ^ (m2 & E1);
+ z0 ^= (y0 & m1);
+ z1 ^= (y1 & m1);
+ z2 ^= (y2 & m1);
+ z3 ^= (y3 & m1);
+
+ int m2 = (y3 << 31) >> 8;
+ y3 = (y3 >>> 1) | (y2 << 31);
+ y2 = (y2 >>> 1) | (y1 << 31);
+ y1 = (y1 >>> 1) | (y0 << 31);
+ y0 = (y0 >>> 1) ^ (m2 & E1);
}
}
- x[0] = r10;
- x[1] = r11;
- x[2] = r12;
- x[3] = r13;
+ x[0] = z0;
+ x[1] = z1;
+ x[2] = z2;
+ x[3] = z3;
}
public static void multiply(long[] x, long[] y)
{
- long r00 = x[0], r01 = x[1], r10 = 0, r11 = 0;
+ long x0 = x[0], x1 = x[1];
+ long y0 = y[0], y1 = y[1];
+ long z0 = 0, z1 = 0, z2 = 0;
- for (int i = 0; i < 2; ++i)
+ for (int j = 0; j < 64; ++j)
{
- long bits = y[i];
- for (int j = 0; j < 64; ++j)
- {
- long m1 = bits >> 63; bits <<= 1;
- r10 ^= (r00 & m1);
- r11 ^= (r01 & m1);
+ long m0 = x0 >> 63; x0 <<= 1;
+ z0 ^= (y0 & m0);
+ z1 ^= (y1 & m0);
- long m2 = (r01 << 63) >> 8;
- r01 = (r01 >>> 1) | (r00 << 63);
- r00 = (r00 >>> 1) ^ (m2 & E1L);
- }
+ long m1 = x1 >> 63; x1 <<= 1;
+ z1 ^= (y0 & m1);
+ z2 ^= (y1 & m1);
+
+ long c = (y1 << 63) >> 8;
+ y1 = (y1 >>> 1) | (y0 << 63);
+ y0 = (y0 >>> 1) ^ (c & E1L);
}
- x[0] = r10;
- x[1] = r11;
+ z0 ^= z2 ^ (z2 >>> 1) ^ (z2 >>> 2) ^ (z2 >>> 7);
+ z1 ^= (z2 << 63) ^ (z2 << 62) ^ (z2 << 57);
+
+ x[0] = z0;
+ x[1] = z1;
}
- // P is the value with only bit i=1 set
public static void multiplyP(int[] x)
{
- int m = shiftRight(x) >> 8;
- x[0] ^= (m & E1);
+ int x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
+ int m = (x3 << 31) >> 31;
+ x[0] = (x0 >>> 1) ^ (m & E1);
+ x[1] = (x1 >>> 1) | (x0 << 31);
+ x[2] = (x2 >>> 1) | (x1 << 31);
+ x[3] = (x3 >>> 1) | (x2 << 31);
}
public static void multiplyP(int[] x, int[] z)
{
- int m = shiftRight(x, z) >> 8;
- z[0] ^= (m & E1);
+ int x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
+ int m = (x3 << 31) >> 31;
+ z[0] = (x0 >>> 1) ^ (m & E1);
+ z[1] = (x1 >>> 1) | (x0 << 31);
+ z[2] = (x2 >>> 1) | (x1 << 31);
+ z[3] = (x3 >>> 1) | (x2 << 31);
}
- // P is the value with only bit i=1 set
- public static void multiplyP8(int[] x)
+ public static void multiplyP(long[] x)
+ {
+ long x0 = x[0], x1 = x[1];
+ long m = (x1 << 63) >> 63;
+ x[0] = (x0 >>> 1) ^ (m & E1L);
+ x[1] = (x1 >>> 1) | (x0 << 63);
+ }
+
+ public static void multiplyP(long[] x, long[] z)
+ {
+ long x0 = x[0], x1 = x[1];
+ long m = (x1 << 63) >> 63;
+ z[0] = (x0 >>> 1) ^ (m & E1L);
+ z[1] = (x1 >>> 1) | (x0 << 63);
+ }
+
+ public static void multiplyP3(long[] x, long[] z)
+ {
+ long x0 = x[0], x1 = x[1];
+ long c = x1 << 61;
+ z[0] = (x0 >>> 3) ^ c ^ (c >>> 1) ^ (c >>> 2) ^ (c >>> 7);
+ z[1] = (x1 >>> 3) | (x0 << 61);
+ }
+
+ public static void multiplyP4(long[] x, long[] z)
+ {
+ long x0 = x[0], x1 = x[1];
+ long c = x1 << 60;
+ z[0] = (x0 >>> 4) ^ c ^ (c >>> 1) ^ (c >>> 2) ^ (c >>> 7);
+ z[1] = (x1 >>> 4) | (x0 << 60);
+ }
+
+ public static void multiplyP7(long[] x, long[] z)
{
-// for (int i = 8; i != 0; --i)
-// {
-// multiplyP(x);
-// }
+ long x0 = x[0], x1 = x[1];
+ long c = x1 << 57;
+ z[0] = (x0 >>> 7) ^ c ^ (c >>> 1) ^ (c >>> 2) ^ (c >>> 7);
+ z[1] = (x1 >>> 7) | (x0 << 57);
+ }
- int c = shiftRightN(x, 8);
- x[0] ^= LOOKUP[c >>> 24];
+ public static void multiplyP8(int[] x)
+ {
+ int x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
+ int c = x3 << 24;
+ x[0] = (x0 >>> 8) ^ c ^ (c >>> 1) ^ (c >>> 2) ^ (c >>> 7);
+ x[1] = (x1 >>> 8) | (x0 << 24);
+ x[2] = (x2 >>> 8) | (x1 << 24);
+ x[3] = (x3 >>> 8) | (x2 << 24);
}
public static void multiplyP8(int[] x, int[] y)
{
- int c = shiftRightN(x, 8, y);
- y[0] ^= LOOKUP[c >>> 24];
- }
-
- static int shiftRight(int[] x)
- {
-// int c = 0;
-// for (int i = 0; i < 4; ++i)
-// {
-// int b = x[i];
-// x[i] = (b >>> 1) | c;
-// c = b << 31;
-// }
-// return c;
-
- int b = x[0];
- x[0] = b >>> 1;
- int c = b << 31;
- b = x[1];
- x[1] = (b >>> 1) | c;
- c = b << 31;
- b = x[2];
- x[2] = (b >>> 1) | c;
- c = b << 31;
- b = x[3];
- x[3] = (b >>> 1) | c;
- return b << 31;
- }
-
- static int shiftRight(int[] x, int[] z)
- {
-// int c = 0;
-// for (int i = 0; i < 4; ++i)
-// {
-// int b = x[i];
-// z[i] = (b >>> 1) | c;
-// c = b << 31;
-// }
-// return c;
-
- int b = x[0];
- z[0] = b >>> 1;
- int c = b << 31;
- b = x[1];
- z[1] = (b >>> 1) | c;
- c = b << 31;
- b = x[2];
- z[2] = (b >>> 1) | c;
- c = b << 31;
- b = x[3];
- z[3] = (b >>> 1) | c;
- return b << 31;
- }
-
- static long shiftRight(long[] x)
- {
- long b = x[0];
- x[0] = b >>> 1;
- long c = b << 63;
- b = x[1];
- x[1] = (b >>> 1) | c;
- return b << 63;
- }
-
- static long shiftRight(long[] x, long[] z)
- {
- long b = x[0];
- z[0] = b >>> 1;
- long c = b << 63;
- b = x[1];
- z[1] = (b >>> 1) | c;
- return b << 63;
- }
-
- static int shiftRightN(int[] x, int n)
- {
-// int c = 0, nInv = 32 - n;
-// for (int i = 0; i < 4; ++i)
-// {
-// int b = x[i];
-// x[i] = (b >>> n) | c;
-// c = b << nInv;
-// }
-// return c;
-
- int b = x[0], nInv = 32 - n;
- x[0] = b >>> n;
- int c = b << nInv;
- b = x[1];
- x[1] = (b >>> n) | c;
- c = b << nInv;
- b = x[2];
- x[2] = (b >>> n) | c;
- c = b << nInv;
- b = x[3];
- x[3] = (b >>> n) | c;
- return b << nInv;
- }
-
- static int shiftRightN(int[] x, int n, int[] z)
- {
-// int c = 0, nInv = 32 - n;
-// for (int i = 0; i < 4; ++i)
-// {
-// int b = x[i];
-// z[i] = (b >>> n) | c;
-// c = b << nInv;
-// }
-// return c;
-
- int b = x[0], nInv = 32 - n;
- z[0] = b >>> n;
- int c = b << nInv;
- b = x[1];
- z[1] = (b >>> n) | c;
- c = b << nInv;
- b = x[2];
- z[2] = (b >>> n) | c;
- c = b << nInv;
- b = x[3];
- z[3] = (b >>> n) | c;
- return b << nInv;
+ int x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
+ int c = x3 << 24;
+ y[0] = (x0 >>> 8) ^ c ^ (c >>> 1) ^ (c >>> 2) ^ (c >>> 7);
+ y[1] = (x1 >>> 8) | (x0 << 24);
+ y[2] = (x2 >>> 8) | (x1 << 24);
+ y[3] = (x3 >>> 8) | (x2 << 24);
+ }
+
+ public static void multiplyP8(long[] x)
+ {
+ long x0 = x[0], x1 = x[1];
+ long c = x1 << 56;
+ x[0] = (x0 >>> 8) ^ c ^ (c >>> 1) ^ (c >>> 2) ^ (c >>> 7);
+ x[1] = (x1 >>> 8) | (x0 << 56);
+ }
+
+ public static void multiplyP8(long[] x, long[] y)
+ {
+ long x0 = x[0], x1 = x[1];
+ long c = x1 << 56;
+ y[0] = (x0 >>> 8) ^ c ^ (c >>> 1) ^ (c >>> 2) ^ (c >>> 7);
+ y[1] = (x1 >>> 8) | (x0 << 56);
+ }
+
+ public static long[] pAsLongs()
+ {
+ long[] tmp = new long[2];
+ tmp[0] = 1L << 62;
+ return tmp;
+ }
+
+ public static void square(long[] x, long[] z)
+ {
+ long[] t = new long[4];
+ Interleave.expand64To128Rev(x[0], t, 0);
+ Interleave.expand64To128Rev(x[1], t, 2);
+
+ long z0 = t[0], z1 = t[1], z2 = t[2], z3 = t[3];
+
+ z1 ^= z3 ^ (z3 >>> 1) ^ (z3 >>> 2) ^ (z3 >>> 7);
+ z2 ^= (z3 << 63) ^ (z3 << 62) ^ (z3 << 57);
+
+ z0 ^= z2 ^ (z2 >>> 1) ^ (z2 >>> 2) ^ (z2 >>> 7);
+ z1 ^= (z2 << 63) ^ (z2 << 62) ^ (z2 << 57);
+
+ z[0] = z0;
+ z[1] = z1;
}
public static void xor(byte[] x, byte[] y)
@@ -323,6 +300,32 @@ public abstract class GCMUtil
while (i < 16);
}
+ public static void xor(byte[] x, byte[] y, int yOff)
+ {
+ int i = 0;
+ do
+ {
+ x[i] ^= y[yOff + i]; ++i;
+ x[i] ^= y[yOff + i]; ++i;
+ x[i] ^= y[yOff + i]; ++i;
+ x[i] ^= y[yOff + i]; ++i;
+ }
+ while (i < 16);
+ }
+
+ public static void xor(byte[] x, int xOff, byte[] y, int yOff, byte[] z, int zOff)
+ {
+ int i = 0;
+ do
+ {
+ z[zOff + i] = (byte)(x[xOff + i] ^ y[yOff + i]); ++i;
+ z[zOff + i] = (byte)(x[xOff + i] ^ y[yOff + i]); ++i;
+ z[zOff + i] = (byte)(x[xOff + i] ^ y[yOff + i]); ++i;
+ z[zOff + i] = (byte)(x[xOff + i] ^ y[yOff + i]); ++i;
+ }
+ while (i < 16);
+ }
+
public static void xor(byte[] x, byte[] y, int yOff, int yLen)
{
while (--yLen >= 0)
@@ -331,6 +334,14 @@ public abstract class GCMUtil
}
}
+ public static void xor(byte[] x, int xOff, byte[] y, int yOff, int len)
+ {
+ while (--len >= 0)
+ {
+ x[xOff + len] ^= y[yOff + len];
+ }
+ }
+
public static void xor(byte[] x, byte[] y, byte[] z)
{
int i = 0;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
index 6eff4e3f..b8766bd7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
@@ -4,7 +4,8 @@ import java.util.Vector;
import org.bouncycastle.util.Arrays;
-public class Tables1kGCMExponentiator implements GCMExponentiator
+public class Tables1kGCMExponentiator
+ implements GCMExponentiator
{
// A lookup table of the power-of-two powers of 'x'
// - lookupPowX2[i] = x^(2^i)
@@ -12,8 +13,8 @@ public class Tables1kGCMExponentiator implements GCMExponentiator
public void init(byte[] x)
{
- int[] y = GCMUtil.asInts(x);
- if (lookupPowX2 != null && Arrays.areEqual(y, (int[])lookupPowX2.elementAt(0)))
+ long[] y = GCMUtil.asLongs(x);
+ if (lookupPowX2 != null && Arrays.areEqual(y, (long[])lookupPowX2.elementAt(0)))
{
return;
}
@@ -24,14 +25,14 @@ public class Tables1kGCMExponentiator implements GCMExponentiator
public void exponentiateX(long pow, byte[] output)
{
- int[] y = GCMUtil.oneAsInts();
+ long[] y = GCMUtil.oneAsLongs();
int bit = 0;
while (pow > 0)
{
if ((pow & 1L) != 0)
{
ensureAvailable(bit);
- GCMUtil.multiply(y, (int[])lookupPowX2.elementAt(bit));
+ GCMUtil.multiply(y, (long[])lookupPowX2.elementAt(bit));
}
++bit;
pow >>>= 1;
@@ -45,11 +46,11 @@ public class Tables1kGCMExponentiator implements GCMExponentiator
int count = lookupPowX2.size();
if (count <= bit)
{
- int[] tmp = (int[])lookupPowX2.elementAt(count - 1);
+ long[] tmp = (long[])lookupPowX2.elementAt(count - 1);
do
{
tmp = Arrays.clone(tmp);
- GCMUtil.multiply(tmp, tmp);
+ GCMUtil.square(tmp, tmp);
lookupPowX2.addElement(tmp);
}
while (++count <= bit);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables4kGCMMultiplier.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables4kGCMMultiplier.java
new file mode 100644
index 00000000..e5ea7483
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables4kGCMMultiplier.java
@@ -0,0 +1,67 @@
+package org.bouncycastle.crypto.modes.gcm;
+
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Pack;
+
+public class Tables4kGCMMultiplier
+ implements GCMMultiplier
+{
+ private byte[] H;
+ private long[][] T;
+
+ public void init(byte[] H)
+ {
+ if (T == null)
+ {
+ T = new long[256][2];
+ }
+ else if (Arrays.areEqual(this.H, H))
+ {
+ return;
+ }
+
+ this.H = Arrays.clone(H);
+
+ // T[0] = 0
+
+ // T[1] = H.p^7
+ GCMUtil.asLongs(this.H, T[1]);
+ GCMUtil.multiplyP7(T[1], T[1]);
+
+ for (int n = 2; n < 256; n += 2)
+ {
+ // T[2.n] = T[n].p^-1
+ GCMUtil.divideP(T[n >> 1], T[n]);
+
+ // T[2.n + 1] = T[2.n] + T[1]
+ GCMUtil.xor(T[n], T[1], T[n + 1]);
+ }
+ }
+
+ public void multiplyH(byte[] x)
+ {
+// long[] z = new long[2];
+// GCMUtil.copy(T[x[15] & 0xFF], z);
+// for (int i = 14; i >= 0; --i)
+// {
+// GCMUtil.multiplyP8(z);
+// GCMUtil.xor(z, T[x[i] & 0xFF]);
+// }
+// Pack.longToBigEndian(z, x, 0);
+
+ long[] t = T[x[15] & 0xFF];
+ long z0 = t[0], z1 = t[1];
+
+ for (int i = 14; i >= 0; --i)
+ {
+ t = T[x[i] & 0xFF];
+
+ long c = z1 << 56;
+ z1 = t[1] ^ ((z1 >>> 8) | (z0 << 56));
+ z0 = t[0] ^ (z0 >>> 8) ^ c ^ (c >>> 1) ^ (c >>> 2) ^ (c >>> 7);
+ }
+
+ Pack.longToBigEndian(z0, x, 0);
+ Pack.longToBigEndian(z1, x, 8);
+ }
+}
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 69c1dce8..6c3ae26c 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
@@ -3,16 +3,17 @@ package org.bouncycastle.crypto.modes.gcm;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Pack;
-public class Tables8kGCMMultiplier implements GCMMultiplier
+public class Tables8kGCMMultiplier
+ implements GCMMultiplier
{
private byte[] H;
- private int[][][] M;
+ private long[][][] T;
public void init(byte[] H)
{
- if (M == null)
+ if (T == null)
{
- M = new int[32][16][4];
+ T = new long[32][16][2];
}
else if (Arrays.areEqual(this.H, H))
{
@@ -21,70 +22,58 @@ public class Tables8kGCMMultiplier implements GCMMultiplier
this.H = Arrays.clone(H);
- // M[0][0] is ZEROES;
- // M[1][0] is ZEROES;
- GCMUtil.asInts(H, M[1][8]);
-
- for (int j = 4; j >= 1; j >>= 1)
+ for (int i = 0; i < 32; ++i)
{
- GCMUtil.multiplyP(M[1][j + j], M[1][j]);
- }
-
- GCMUtil.multiplyP(M[1][1], M[0][8]);
+ long[][] t = T[i];
- for (int j = 4; j >= 1; j >>= 1)
- {
- GCMUtil.multiplyP(M[0][j + j], M[0][j]);
- }
+ // t[0] = 0
- int i = 0;
- for (;;)
- {
- for (int j = 2; j < 16; j += j)
+ if (i == 0)
{
- for (int k = 1; k < j; ++k)
- {
- GCMUtil.xor(M[i][j], M[i][k], M[i][j + k]);
- }
+ // t[1] = H.p^3
+ GCMUtil.asLongs(this.H, t[1]);
+ GCMUtil.multiplyP3(t[1], t[1]);
}
-
- if (++i == 32)
+ else
{
- return;
+ // t[1] = T[i-1][1].p^4
+ GCMUtil.multiplyP4(T[i - 1][1], t[1]);
}
- if (i > 1)
+ for (int n = 2; n < 16; n += 2)
{
- // M[i][0] is ZEROES;
- for(int j = 8; j > 0; j >>= 1)
- {
- GCMUtil.multiplyP8(M[i - 2][j], M[i][j]);
- }
+ // t[2.n] = t[n].p^-1
+ GCMUtil.divideP(t[n >> 1], t[n]);
+
+ // t[2.n + 1] = t[2.n] + t[1]
+ GCMUtil.xor(t[n], t[1], t[n + 1]);
}
}
+
}
public void multiplyH(byte[] x)
{
-// assert x.Length == 16;
+// long[] z = new long[2];
+// for (int i = 15; i >= 0; --i)
+// {
+// GCMUtil.xor(z, T[i + i + 1][(x[i] & 0x0F)]);
+// GCMUtil.xor(z, T[i + i ][(x[i] & 0xF0) >>> 4]);
+// }
+// Pack.longToBigEndian(z, x, 0);
+
+ long z0 = 0, z1 = 0;
- int[] z = new int[4];
for (int i = 15; i >= 0; --i)
{
-// GCMUtil.xor(z, M[i + i][x[i] & 0x0f]);
- int[] m = M[i + i][x[i] & 0x0f];
- z[0] ^= m[0];
- z[1] ^= m[1];
- z[2] ^= m[2];
- z[3] ^= m[3];
-// GCMUtil.xor(z, M[i + i + 1][(x[i] & 0xf0) >>> 4]);
- m = M[i + i + 1][(x[i] & 0xf0) >>> 4];
- z[0] ^= m[0];
- z[1] ^= m[1];
- z[2] ^= m[2];
- z[3] ^= m[3];
+ long[] u = T[i + i + 1][(x[i] & 0x0F)];
+ long[] v = T[i + i ][(x[i] & 0xF0) >>> 4];
+
+ z0 ^= u[0] ^ v[0];
+ z1 ^= u[1] ^ v[1];
}
- Pack.intToBigEndian(z, x, 0);
- }
-} \ No newline at end of file
+ Pack.longToBigEndian(z0, x, 0);
+ Pack.longToBigEndian(z1, x, 8);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java
index 63e29d84..076ad588 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java
@@ -2,6 +2,7 @@ package org.bouncycastle.crypto.paddings;
import java.security.SecureRandom;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.InvalidCipherTextException;
/**
@@ -26,7 +27,7 @@ public class ISO10126d2Padding
}
else
{
- this.random = new SecureRandom();
+ this.random = CryptoServicesRegistrar.getSecureRandom();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java
index 9a9272ba..c0648159 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java
@@ -1,6 +1,7 @@
package org.bouncycastle.crypto.params;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.util.Arrays;
public class AEADParameters
implements CipherParameters
@@ -33,9 +34,9 @@ public class AEADParameters
public AEADParameters(KeyParameter key, int macSize, byte[] nonce, byte[] associatedText)
{
this.key = key;
- this.nonce = nonce;
+ this.nonce = Arrays.clone(nonce);
this.macSize = macSize;
- this.associatedText = associatedText;
+ this.associatedText = Arrays.clone(associatedText);
}
public KeyParameter getKey()
@@ -50,11 +51,11 @@ public class AEADParameters
public byte[] getAssociatedText()
{
- return associatedText;
+ return Arrays.clone(associatedText);
}
public byte[] getNonce()
{
- return nonce;
+ return Arrays.clone(nonce);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
index fec6dfdc..5bdb10a1 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
@@ -94,6 +94,11 @@ public class DHParameters
}
}
+ if (m > p.bitLength())
+ {
+ throw new IllegalArgumentException("unsafe p value so small specific l required");
+ }
+
this.g = g;
this.p = p;
this.q = q;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHValidationParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHValidationParameters.java
index b22f7a03..8c4b187d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHValidationParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHValidationParameters.java
@@ -11,7 +11,7 @@ public class DHValidationParameters
byte[] seed,
int counter)
{
- this.seed = seed;
+ this.seed = Arrays.clone(seed);
this.counter = counter;
}
@@ -22,7 +22,7 @@ public class DHValidationParameters
public byte[] getSeed()
{
- return seed;
+ return Arrays.clone(seed);
}
public boolean equals(
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java
index 07d93d07..11613e8e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java
@@ -20,7 +20,7 @@ public class DSAValidationParameters
int counter,
int usageIndex)
{
- this.seed = seed;
+ this.seed = Arrays.clone(seed);
this.counter = counter;
this.usageIndex = usageIndex;
}
@@ -32,7 +32,7 @@ public class DSAValidationParameters
public byte[] getSeed()
{
- return seed;
+ return Arrays.clone(seed);
}
public int getUsageIndex()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
index c97f2e76..1cead6f3 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
@@ -2,6 +2,7 @@ package org.bouncycastle.crypto.params;
import java.math.BigInteger;
+import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
@@ -15,6 +16,7 @@ public class ECDomainParameters
private ECPoint G;
private BigInteger n;
private BigInteger h;
+ private BigInteger hInv = null;
public ECDomainParameters(
ECCurve curve,
@@ -40,11 +42,21 @@ public class ECDomainParameters
BigInteger h,
byte[] seed)
{
+ if (curve == null)
+ {
+ throw new NullPointerException("curve");
+ }
+ if (n == null)
+ {
+ throw new NullPointerException("n");
+ }
+ // we can't check for h == null here as h is optional in X9.62 as it is not required for ECDSA
+
this.curve = curve;
- this.G = G.normalize();
+ this.G = validate(curve, G);
this.n = n;
this.h = h;
- this.seed = seed;
+ this.seed = Arrays.clone(seed);
}
public ECCurve getCurve()
@@ -67,6 +79,15 @@ public class ECDomainParameters
return h;
}
+ public synchronized BigInteger getHInv()
+ {
+ if (hInv == null)
+ {
+ hInv = h.modInverse(n);
+ }
+ return hInv;
+ }
+
public byte[] getSeed()
{
return Arrays.clone(seed);
@@ -101,4 +122,26 @@ public class ECDomainParameters
hc ^= h.hashCode();
return hc;
}
+
+ static ECPoint validate(ECCurve c, ECPoint q)
+ {
+ if (q == null)
+ {
+ throw new IllegalArgumentException("Point has null value");
+ }
+
+ q = ECAlgorithms.importPoint(c, q).normalize();
+
+ if (q.isInfinity())
+ {
+ throw new IllegalArgumentException("Point at infinity");
+ }
+
+ if (!q.isValid())
+ {
+ throw new IllegalArgumentException("Point not on curve");
+ }
+
+ return q;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java
index 5b694bec..ed89589f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECNamedDomainParameters.java
@@ -3,6 +3,7 @@ package org.bouncycastle.crypto.params;
import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
@@ -13,7 +14,7 @@ public class ECNamedDomainParameters
public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n)
{
- this(name, curve, G, n, null, null);
+ this(name, curve, G, n, ECConstants.ONE, null);
}
public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h)
@@ -28,6 +29,12 @@ public class ECNamedDomainParameters
this.name = name;
}
+ public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECDomainParameters domainParameters)
+ {
+ super(domainParameters.getCurve(), domainParameters.getG(), domainParameters.getN(), domainParameters.getH(), domainParameters.getSeed());
+ this.name = name;
+ }
+
public ASN1ObjectIdentifier getName()
{
return name;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
index 036bf4ae..6f097ad3 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
@@ -13,29 +13,7 @@ public class ECPublicKeyParameters
{
super(false, params);
- this.Q = validate(Q);
- }
-
- private ECPoint validate(ECPoint q)
- {
- if (q == null)
- {
- throw new IllegalArgumentException("point has null value");
- }
-
- if (q.isInfinity())
- {
- throw new IllegalArgumentException("point at infinity");
- }
-
- q = q.normalize();
-
- if (!q.isValid())
- {
- throw new IllegalArgumentException("point not on curve");
- }
-
- return q;
+ this.Q = ECDomainParameters.validate(params.getCurve(), Q);
}
public ECPoint getQ()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ParametersWithRandom.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ParametersWithRandom.java
index a7b18e51..9c6ed020 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ParametersWithRandom.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ParametersWithRandom.java
@@ -1,9 +1,10 @@
package org.bouncycastle.crypto.params;
-import org.bouncycastle.crypto.CipherParameters;
-
import java.security.SecureRandom;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
+
public class ParametersWithRandom
implements CipherParameters
{
@@ -21,7 +22,7 @@ public class ParametersWithRandom
public ParametersWithRandom(
CipherParameters parameters)
{
- this(parameters, new SecureRandom());
+ this(parameters, CryptoServicesRegistrar.getSecureRandom());
}
public SecureRandom getRandom()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAEncoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAEncoding.java
new file mode 100644
index 00000000..9ee166f9
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAEncoding.java
@@ -0,0 +1,31 @@
+package org.bouncycastle.crypto.signers;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+/**
+ * An interface for different encoding formats for DSA signatures.
+ */
+public interface DSAEncoding
+{
+ /**
+ * Decode the (r, s) pair of a DSA signature.
+ *
+ * @param n the order of the group that r, s belong to.
+ * @param encoding an encoding of the (r, s) pair of a DSA signature.
+ * @return the (r, s) of a DSA signature, stored in an array of exactly two elements, r followed by s.
+ * @throws IOException
+ */
+ BigInteger[] decode(BigInteger n, byte[] encoding) throws IOException;
+
+ /**
+ * Encode the (r, s) pair of a DSA signature.
+ *
+ * @param n the order of the group that r, s belong to.
+ * @param r the r value of a DSA signature.
+ * @param s the s value of a DSA signature.
+ * @return an encoding of the DSA signature given by the provided (r, s) pair.
+ * @throws IOException
+ */
+ byte[] encode(BigInteger n, BigInteger r, BigInteger s) throws IOException;
+}
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 920611bc..668ac276 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
@@ -4,19 +4,21 @@ import java.math.BigInteger;
import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
+import org.bouncycastle.crypto.DSAExt;
import org.bouncycastle.crypto.params.DSAKeyParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.util.BigIntegers;
/**
* The Digital Signature Algorithm - as described in "Handbook of Applied
* Cryptography", pages 452 - 453.
*/
public class DSASigner
- implements DSA
+ implements DSAExt
{
private final DSAKCalculator kCalculator;
@@ -69,6 +71,11 @@ public class DSASigner
this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom);
}
+ public BigInteger getOrder()
+ {
+ return key.getParameters().getQ();
+ }
+
/**
* generate a signature for the given message using the key we were
* initialised with. For conventional DSA the message should be a SHA-1
@@ -162,7 +169,7 @@ public class DSASigner
protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
{
- return !needed ? null : (provided != null) ? provided : new SecureRandom();
+ return !needed ? null : (provided != null) ? provided : CryptoServicesRegistrar.getSecureRandom();
}
private BigInteger getRandomizer(BigInteger q, SecureRandom provided)
@@ -170,6 +177,6 @@ public class DSASigner
// Calculate a random multiple of q to add to k. Note that g^q = 1 (mod p), so adding multiple of q to k does not change r.
int randomBits = 7;
- return new BigInteger(randomBits, provided != null ? provided : new SecureRandom()).add(BigInteger.valueOf(128)).multiply(q);
+ return BigIntegers.createRandomBigInteger(randomBits, provided != null ? provided : CryptoServicesRegistrar.getSecureRandom()).add(BigInteger.valueOf(128)).multiply(q);
}
}
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 adb2558a..057beed7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
@@ -4,7 +4,8 @@ import java.math.BigInteger;
import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
+import org.bouncycastle.crypto.DSAExt;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
@@ -22,7 +23,7 @@ import org.bouncycastle.math.ec.FixedPointCombMultiplier;
* EC-DSA as described in X9.62
*/
public class ECDSASigner
- implements ECConstants, DSA
+ implements ECConstants, DSAExt
{
private final DSAKCalculator kCalculator;
@@ -75,6 +76,11 @@ public class ECDSASigner
this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom);
}
+ public BigInteger getOrder()
+ {
+ return key.getParameters().getN();
+ }
+
// 5.3 pg 28
/**
* generate a signature for the given message using the key we were
@@ -247,6 +253,6 @@ public class ECDSASigner
protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
{
- return !needed ? null : (provided != null) ? provided : new SecureRandom();
+ return !needed ? null : (provided != null) ? provided : CryptoServicesRegistrar.getSecureRandom();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/PlainDSAEncoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/PlainDSAEncoding.java
new file mode 100644
index 00000000..9bb30dde
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/PlainDSAEncoding.java
@@ -0,0 +1,62 @@
+package org.bouncycastle.crypto.signers;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.BigIntegers;
+
+public class PlainDSAEncoding
+ implements DSAEncoding
+{
+ public static final PlainDSAEncoding INSTANCE = new PlainDSAEncoding();
+
+ public byte[] encode(BigInteger n, BigInteger r, BigInteger s)
+ {
+ int valueLength = BigIntegers.getUnsignedByteLength(n);
+ byte[] result = new byte[valueLength * 2];
+ encodeValue(n, r, result, 0, valueLength);
+ encodeValue(n, s, result, valueLength, valueLength);
+ return result;
+ }
+
+ public BigInteger[] decode(BigInteger n, byte[] encoding)
+ {
+ int valueLength = BigIntegers.getUnsignedByteLength(n);
+ if (encoding.length != valueLength * 2)
+ {
+ throw new IllegalArgumentException("Encoding has incorrect length");
+ }
+
+ return new BigInteger[] {
+ decodeValue(n, encoding, 0, valueLength),
+ decodeValue(n, encoding, valueLength, valueLength),
+ };
+ }
+
+ protected BigInteger checkValue(BigInteger n, BigInteger x)
+ {
+ if (x.signum() < 0 || x.compareTo(n) >= 0)
+ {
+ throw new IllegalArgumentException("Value out of range");
+ }
+
+ return x;
+ }
+
+ protected BigInteger decodeValue(BigInteger n, byte[] buf, int off, int len)
+ {
+ byte[] bs = Arrays.copyOfRange(buf, off, off + len);
+ return checkValue(n, new BigInteger(1, bs));
+ }
+
+ private void encodeValue(BigInteger n, BigInteger x, byte[] buf, int off, int len)
+ {
+ byte[] bs = checkValue(n, x).toByteArray();
+ int bsOff = Math.max(0, bs.length - len);
+ int bsLen = bs.length - bsOff;
+
+ int pos = len - bsLen;
+ Arrays.fill(buf, off, off + pos, (byte)0);
+ System.arraycopy(bs, bsOff, buf, off + pos, bsLen);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
index 6a693080..cf54b85c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
@@ -3,6 +3,8 @@ package org.bouncycastle.crypto.signers;
import java.math.BigInteger;
import java.security.SecureRandom;
+import org.bouncycastle.util.BigIntegers;
+
public class RandomDSAKCalculator
implements DSAKCalculator
{
@@ -34,7 +36,7 @@ public class RandomDSAKCalculator
BigInteger k;
do
{
- k = new BigInteger(qBitLength, random);
+ k = BigIntegers.createRandomBigInteger(qBitLength, random);
}
while (k.equals(ZERO) || k.compareTo(q) >= 0);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/StandardDSAEncoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/StandardDSAEncoding.java
new file mode 100644
index 00000000..c92b9769
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/StandardDSAEncoding.java
@@ -0,0 +1,64 @@
+package org.bouncycastle.crypto.signers;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.util.Arrays;
+
+public class StandardDSAEncoding
+ implements DSAEncoding
+{
+ public static final StandardDSAEncoding INSTANCE = new StandardDSAEncoding();
+
+ public byte[] encode(BigInteger n, BigInteger r, BigInteger s) throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ encodeValue(n, v, r);
+ encodeValue(n, v, s);
+ return new DERSequence(v).getEncoded(ASN1Encoding.DER);
+ }
+
+ public BigInteger[] decode(BigInteger n, byte[] encoding) throws IOException
+ {
+ ASN1Sequence seq = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
+ if (seq.size() == 2)
+ {
+ BigInteger r = decodeValue(n, seq, 0);
+ BigInteger s = decodeValue(n, seq, 1);
+
+ byte[] expectedEncoding = encode(n, r, s);
+ if (Arrays.areEqual(expectedEncoding, encoding))
+ {
+ return new BigInteger[]{ r, s };
+ }
+ }
+
+ throw new IllegalArgumentException("Malformed signature");
+ }
+
+ protected BigInteger checkValue(BigInteger n, BigInteger x)
+ {
+ if (x.signum() < 0 || (null != n && x.compareTo(n) >= 0))
+ {
+ throw new IllegalArgumentException("Value out of range");
+ }
+
+ return x;
+ }
+
+ protected BigInteger decodeValue(BigInteger n, ASN1Sequence s, int pos)
+ {
+ return checkValue(n, ((ASN1Integer)s.getObjectAt(pos)).getValue());
+ }
+
+ protected void encodeValue(BigInteger n, ASN1EncodableVector v, BigInteger x)
+ {
+ v.add(new ASN1Integer(checkValue(n, x)));
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNoCloseNotifyException.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNoCloseNotifyException.java
index a5c583b0..997d9907 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNoCloseNotifyException.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNoCloseNotifyException.java
@@ -12,4 +12,8 @@ import java.io.EOFException;
public class TlsNoCloseNotifyException
extends EOFException
{
+ public TlsNoCloseNotifyException()
+ {
+ super("No close_notify alert received before connection closed");
+ }
}
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 911f1dae..58c7871c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
@@ -8,17 +8,25 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
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;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.asn1.oiw.ElGamalParameter;
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
+// import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
+// import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
+// import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers;
import org.bouncycastle.asn1.sec.ECPrivateKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
+import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
@@ -30,12 +38,19 @@ import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.params.ECGOST3410Parameters;
import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.crypto.params.ElGamalParameters;
// import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
+// import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
+// import org.bouncycastle.crypto.params.Ed448PrivateKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.params.X25519PrivateKeyParameters;
+// import org.bouncycastle.crypto.params.X448PrivateKeyParameters;
/**
* Factory for creating private key objects from PKCS8 PrivateKeyInfo objects.
@@ -44,12 +59,13 @@ public class PrivateKeyFactory
{
/**
* Create a private key parameter from a PKCS8 PrivateKeyInfo encoding.
- *
+ *
* @param privateKeyInfoData the PrivateKeyInfo encoding
* @return a suitable private key parameter
* @throws IOException on an error decoding the key
*/
- public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) throws IOException
+ public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData)
+ throws IOException
{
return createKey(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(privateKeyInfoData)));
}
@@ -57,28 +73,33 @@ public class PrivateKeyFactory
/**
* Create a private key parameter from a PKCS8 PrivateKeyInfo encoding read from a
* stream.
- *
+ *
* @param inStr the stream to read the PrivateKeyInfo encoding from
* @return a suitable private key parameter
* @throws IOException on an error decoding the key
*/
- public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
+ public static AsymmetricKeyParameter createKey(InputStream inStr)
+ throws IOException
{
return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
}
/**
* Create a private key parameter from the passed in PKCS8 PrivateKeyInfo object.
- *
+ *
* @param keyInfo the PrivateKeyInfo object containing the key material
* @return a suitable private key parameter
* @throws IOException on an error decoding the key
*/
- public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) throws IOException
+ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo)
+ throws IOException
{
AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm();
+ ASN1ObjectIdentifier algOID = algId.getAlgorithm();
- if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption))
+ if (algOID.equals(PKCSObjectIdentifiers.rsaEncryption)
+ || algOID.equals(PKCSObjectIdentifiers.id_RSASSA_PSS)
+ || algOID.equals(X509ObjectIdentifiers.id_ea_rsa))
{
RSAPrivateKey keyStructure = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey());
@@ -88,8 +109,8 @@ public class PrivateKeyFactory
keyStructure.getExponent2(), keyStructure.getCoefficient());
}
// TODO?
-// else if (algId.getObjectId().equals(X9ObjectIdentifiers.dhpublicnumber))
- else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
+// else if (algOID.equals(X9ObjectIdentifiers.dhpublicnumber))
+ else if (algOID.equals(PKCSObjectIdentifiers.dhKeyAgreement))
{
DHParameter params = DHParameter.getInstance(algId.getParameters());
ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
@@ -102,7 +123,7 @@ public class PrivateKeyFactory
}
// BEGIN Android-removed: Unsupported algorithms
/*
- else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
+ else if (algOID.equals(OIWObjectIdentifiers.elGamalAlgorithm))
{
ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
@@ -112,7 +133,7 @@ public class PrivateKeyFactory
}
*/
// END Android-removed: Unsupported algorithms
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa))
+ else if (algOID.equals(X9ObjectIdentifiers.id_dsa))
{
ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
ASN1Encodable de = algId.getParameters();
@@ -126,7 +147,7 @@ public class PrivateKeyFactory
return new DSAPrivateKeyParameters(derX.getValue(), parameters);
}
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
+ else if (algOID.equals(X9ObjectIdentifiers.id_ecPublicKey))
{
X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters());
@@ -157,9 +178,151 @@ public class PrivateKeyFactory
return new ECPrivateKeyParameters(d, dParams);
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (algOID.equals(EdECObjectIdentifiers.id_X25519))
+ {
+ return new X25519PrivateKeyParameters(getRawKey(keyInfo, X25519PrivateKeyParameters.KEY_SIZE), 0);
+ }
+ else if (algOID.equals(EdECObjectIdentifiers.id_X448))
+ {
+ return new X448PrivateKeyParameters(getRawKey(keyInfo, X448PrivateKeyParameters.KEY_SIZE), 0);
+ }
+ else if (algOID.equals(EdECObjectIdentifiers.id_Ed25519))
+ {
+ return new Ed25519PrivateKeyParameters(getRawKey(keyInfo, Ed25519PrivateKeyParameters.KEY_SIZE), 0);
+ }
+ else if (algOID.equals(EdECObjectIdentifiers.id_Ed448))
+ {
+ return new Ed448PrivateKeyParameters(getRawKey(keyInfo, Ed448PrivateKeyParameters.KEY_SIZE), 0);
+ }
+ else if (
+ algOID.equals(CryptoProObjectIdentifiers.gostR3410_2001) ||
+ algOID.equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512) ||
+ algOID.equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256))
+ {
+ GOST3410PublicKeyAlgParameters gostParams = GOST3410PublicKeyAlgParameters.getInstance(keyInfo.getPrivateKeyAlgorithm().getParameters());
+ ECGOST3410Parameters ecSpec = null;
+ BigInteger d = null;
+ ASN1Primitive p = keyInfo.getPrivateKeyAlgorithm().getParameters().toASN1Primitive();
+ if (p instanceof ASN1Sequence && (ASN1Sequence.getInstance(p).size() == 2 || ASN1Sequence.getInstance(p).size() == 3))
+ {
+
+ ECDomainParameters ecP = ECGOST3410NamedCurves.getByOID(gostParams.getPublicKeyParamSet());
+
+ ecSpec = new ECGOST3410Parameters(
+ new ECNamedDomainParameters(
+ gostParams.getPublicKeyParamSet(), ecP),
+ gostParams.getPublicKeyParamSet(),
+ gostParams.getDigestParamSet(),
+ gostParams.getEncryptionParamSet());
+ ASN1Encodable privKey = keyInfo.parsePrivateKey();
+ if (privKey instanceof ASN1Integer)
+ {
+ d = ASN1Integer.getInstance(privKey).getPositiveValue();
+ }
+ else
+ {
+ byte[] encVal = ASN1OctetString.getInstance(privKey).getOctets();
+ byte[] dVal = new byte[encVal.length];
+
+ for (int i = 0; i != encVal.length; i++)
+ {
+ dVal[i] = encVal[encVal.length - 1 - i];
+ }
+
+ d = new BigInteger(1, dVal);
+ }
+
+
+ }
+ else
+ {
+ X962Parameters params = X962Parameters.getInstance(keyInfo.getPrivateKeyAlgorithm().getParameters());
+
+ if (params.isNamedCurve())
+ {
+ ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
+ X9ECParameters ecP = ECNamedCurveTable.getByOID(oid);
+ if (ecP == null)
+ {
+ ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid);
+ ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(
+ oid,
+ gParam.getCurve(),
+ gParam.getG(),
+ gParam.getN(),
+ gParam.getH(),
+ gParam.getSeed()), gostParams.getPublicKeyParamSet(), gostParams.getDigestParamSet(), gostParams.getEncryptionParamSet());
+ }
+ else
+ {
+ ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(
+ oid,
+ ecP.getCurve(),
+ ecP.getG(),
+ ecP.getN(),
+ ecP.getH(),
+ ecP.getSeed()), gostParams.getPublicKeyParamSet(), gostParams.getDigestParamSet(), gostParams.getEncryptionParamSet());
+ }
+ }
+ else if (params.isImplicitlyCA())
+ {
+ ecSpec = null;
+ }
+ else
+ {
+ X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters());
+ ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(
+ algOID,
+ ecP.getCurve(),
+ ecP.getG(),
+ ecP.getN(),
+ ecP.getH(),
+ ecP.getSeed()), gostParams.getPublicKeyParamSet(), gostParams.getDigestParamSet(), gostParams.getEncryptionParamSet());
+ }
+
+ ASN1Encodable privKey = keyInfo.parsePrivateKey();
+ if (privKey instanceof ASN1Integer)
+ {
+ ASN1Integer derD = ASN1Integer.getInstance(privKey);
+
+ d = derD.getValue();
+ }
+ else
+ {
+ org.bouncycastle.asn1.sec.ECPrivateKey ec = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(privKey);
+
+ d = ec.getKey();
+ }
+
+ }
+
+ return new ECPrivateKeyParameters(
+ d,
+ new ECGOST3410Parameters(
+ ecSpec,
+ gostParams.getPublicKeyParamSet(),
+ gostParams.getDigestParamSet(),
+ gostParams.getEncryptionParamSet()));
+
+ }
+ */
+ // END Android-removed: Unsupported algorithms
else
{
- throw new RuntimeException("algorithm identifier in key not recognised");
+ throw new RuntimeException("algorithm identifier in private key not recognised");
+ }
+ }
+
+ private static byte[] getRawKey(PrivateKeyInfo keyInfo, int expectedSize)
+ throws IOException
+ {
+ byte[] result = ASN1OctetString.getInstance(keyInfo.parsePrivateKey()).getOctets();
+ if (expectedSize != result.length)
+ {
+ throw new RuntimeException("private key encoding has incorrect length");
}
+ return result;
}
}
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 86028870..b64c6a2a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
@@ -3,6 +3,8 @@ package org.bouncycastle.crypto.util;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Map;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
@@ -10,13 +12,25 @@ import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DEROctetString;
-// Android-removed: Unsupported algorithm
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
+// import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
+// import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
// import org.bouncycastle.asn1.oiw.ElGamalParameter;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
+// import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers;
+// import org.bouncycastle.asn1.ua.DSTU4145BinaryField;
+// import org.bouncycastle.asn1.ua.DSTU4145ECBinary;
+// import org.bouncycastle.asn1.ua.DSTU4145NamedCurves;
+// import org.bouncycastle.asn1.ua.DSTU4145Params;
+// import org.bouncycastle.asn1.ua.DSTU4145PointEncoder;
+// import org.bouncycastle.asn1.ua.UAObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
@@ -28,6 +42,7 @@ import org.bouncycastle.asn1.x9.ValidationParams;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECPoint;
+import org.bouncycastle.asn1.x9.X9IntegerConverter;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
@@ -37,12 +52,19 @@ 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.ECGOST3410Parameters;
import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-// Android-removed: Unsupported algorithm
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
+// import org.bouncycastle.crypto.params.Ed448PublicKeyParameters;
// import org.bouncycastle.crypto.params.ElGamalParameters;
// import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.params.X25519PublicKeyParameters;
+// import org.bouncycastle.crypto.params.X448PublicKeyParameters;
+import org.bouncycastle.math.ec.ECCurve;
/**
* Factory to create asymmetric public key parameters for asymmetric ciphers from range of
@@ -50,55 +72,127 @@ import org.bouncycastle.crypto.params.RSAKeyParameters;
*/
public class PublicKeyFactory
{
+ private static Map converters = new HashMap();
+
+ static
+ {
+ converters.put(PKCSObjectIdentifiers.rsaEncryption, new RSAConverter());
+ converters.put(PKCSObjectIdentifiers.id_RSASSA_PSS, new RSAConverter());
+ converters.put(X509ObjectIdentifiers.id_ea_rsa, new RSAConverter());
+ converters.put(X9ObjectIdentifiers.dhpublicnumber, new DHPublicNumberConverter());
+ converters.put(PKCSObjectIdentifiers.dhKeyAgreement, new DHAgreementConverter());
+ converters.put(X9ObjectIdentifiers.id_dsa, new DSAConverter());
+ converters.put(OIWObjectIdentifiers.dsaWithSHA1, new DSAConverter());
+ // Android-removed: Unsupported algorithm
+ // converters.put(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalConverter());
+ converters.put(X9ObjectIdentifiers.id_ecPublicKey, new ECConverter());
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ converters.put(CryptoProObjectIdentifiers.gostR3410_2001, new GOST3410_2001Converter());
+ converters.put(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256, new GOST3410_2012Converter());
+ converters.put(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512, new GOST3410_2012Converter());
+ converters.put(UAObjectIdentifiers.dstu4145be, new DSTUConverter());
+ converters.put(UAObjectIdentifiers.dstu4145le, new DSTUConverter());
+ converters.put(EdECObjectIdentifiers.id_X25519, new X25519Converter());
+ converters.put(EdECObjectIdentifiers.id_X448, new X448Converter());
+ converters.put(EdECObjectIdentifiers.id_Ed25519, new Ed25519Converter());
+ converters.put(EdECObjectIdentifiers.id_Ed448, new Ed448Converter());
+ */
+ // END Android-removed: Unsupported algorithms
+ }
+
/**
* Create a public key from a SubjectPublicKeyInfo encoding
- *
+ *
* @param keyInfoData the SubjectPublicKeyInfo encoding
* @return the appropriate key parameter
* @throws IOException on an error decoding the key
*/
- public static AsymmetricKeyParameter createKey(byte[] keyInfoData) throws IOException
+ public static AsymmetricKeyParameter createKey(byte[] keyInfoData)
+ throws IOException
{
return createKey(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(keyInfoData)));
}
/**
* Create a public key from a SubjectPublicKeyInfo encoding read from a stream
- *
+ *
* @param inStr the stream to read the SubjectPublicKeyInfo encoding from
* @return the appropriate key parameter
* @throws IOException on an error decoding the key
*/
- public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
+ public static AsymmetricKeyParameter createKey(InputStream inStr)
+ throws IOException
{
return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
}
/**
* Create a public key from the passed in SubjectPublicKeyInfo
- *
+ *
* @param keyInfo the SubjectPublicKeyInfo containing the key data
* @return the appropriate key parameter
* @throws IOException on an error decoding the key
*/
- public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) throws IOException
+ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo)
+ throws IOException
+ {
+ return createKey(keyInfo, null);
+ }
+
+ /**
+ * Create a public key from the passed in SubjectPublicKeyInfo
+ *
+ * @param keyInfo the SubjectPublicKeyInfo containing the key data
+ * @param defaultParams default parameters that might be needed.
+ * @return the appropriate key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ throws IOException
{
AlgorithmIdentifier algId = keyInfo.getAlgorithm();
+ SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)converters.get(algId.getAlgorithm());
+
+ if (converter != null)
+ {
+ return converter.getPublicKeyParameters(keyInfo, defaultParams);
+ }
+ else
+ {
+ throw new IOException("algorithm identifier in public key not recognised: " + algId.getAlgorithm());
+ }
+ }
+
+ private static abstract class SubjectPublicKeyInfoConverter
+ {
+ abstract AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ throws IOException;
+ }
- if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)
- || algId.getAlgorithm().equals(X509ObjectIdentifiers.id_ea_rsa))
+ private static class RSAConverter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ throws IOException
{
RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey());
return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());
}
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.dhpublicnumber))
+ }
+
+ private static class DHPublicNumberConverter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ throws IOException
{
DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey());
BigInteger y = dhPublicKey.getY();
- DomainParameters dhParams = DomainParameters.getInstance(algId.getParameters());
+ DomainParameters dhParams = DomainParameters.getInstance(keyInfo.getAlgorithm().getParameters());
BigInteger p = dhParams.getP();
BigInteger g = dhParams.getG();
@@ -124,9 +218,15 @@ public class PublicKeyFactory
return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation));
}
- else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
+ }
+
+ private static class DHAgreementConverter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ throws IOException
{
- DHParameter params = DHParameter.getInstance(algId.getParameters());
+ DHParameter params = DHParameter.getInstance(keyInfo.getAlgorithm().getParameters());
ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
BigInteger lVal = params.getL();
@@ -135,23 +235,34 @@ public class PublicKeyFactory
return new DHPublicKeyParameters(derY.getValue(), dhParams);
}
- // BEGIN Android-removed: Unsupported algorithm
- /*
- else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
+ }
+
+ // BEGIN Android-removed: Unsupported algorithm
+ /*
+ private static class ElGamalConverter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ throws IOException
{
- ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
+ ElGamalParameter params = ElGamalParameter.getInstance(keyInfo.getAlgorithm().getParameters());
ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
params.getP(), params.getG()));
}
- */
- // END Android-removed: Unsupported algorithm
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)
- || algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1))
+ }
+ */
+ // END Android-removed: Unsupported algorithm
+
+ private static class DSAConverter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ throws IOException
{
ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
- ASN1Encodable de = algId.getParameters();
+ ASN1Encodable de = keyInfo.getAlgorithm().getParameters();
DSAParameters parameters = null;
if (de != null)
@@ -162,40 +273,282 @@ public class PublicKeyFactory
return new DSAPublicKeyParameters(derY.getValue(), parameters);
}
- else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
- {
- X962Parameters params = X962Parameters.getInstance(algId.getParameters());
+ }
- X9ECParameters x9;
+ private static class ECConverter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ {
+ X962Parameters params = X962Parameters.getInstance(keyInfo.getAlgorithm().getParameters());
ECDomainParameters dParams;
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
- x9 = CustomNamedCurves.getByOID(oid);
+ X9ECParameters 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());
+ oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+ }
+ else if (params.isImplicitlyCA())
+ {
+ dParams = (ECDomainParameters)defaultParams;
}
else
{
- x9 = X9ECParameters.getInstance(params.getParameters());
+ X9ECParameters x9 = X9ECParameters.getInstance(params.getParameters());
dParams = new ECDomainParameters(
- x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+ x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
}
- ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes());
- X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key);
+ DERBitString bits = keyInfo.getPublicKeyData();
+ byte[] data = bits.getBytes();
+ ASN1OctetString key = new DEROctetString(data);
+
+ //
+ // extra octet string - the old extra embedded octet string
+ //
+ if (data[0] == 0x04 && data[1] == data.length - 2
+ && (data[2] == 0x02 || data[2] == 0x03))
+ {
+ int qLength = new X9IntegerConverter().getByteLength(dParams.getCurve());
+
+ if (qLength >= data.length - 3)
+ {
+ try
+ {
+ key = (ASN1OctetString)ASN1Primitive.fromByteArray(data);
+ }
+ catch (IOException ex)
+ {
+ throw new IllegalArgumentException("error recovering public key");
+ }
+ }
+ }
+
+ X9ECPoint derQ = new X9ECPoint(dParams.getCurve(), key);
return new ECPublicKeyParameters(derQ.getPoint(), dParams);
}
- else
+ }
+
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ private static class GOST3410_2001Converter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ {
+ DERBitString bits = keyInfo.getPublicKeyData();
+ ASN1OctetString key;
+
+ try
+ {
+ key = (ASN1OctetString)ASN1Primitive.fromByteArray(bits.getBytes());
+ }
+ catch (IOException ex)
+ {
+ throw new IllegalArgumentException("error recovering public key");
+ }
+
+ byte[] keyEnc = key.getOctets();
+
+ byte[] x9Encoding = new byte[65];
+ x9Encoding[0] = 0x04;
+ for (int i = 1; i <= 32; ++i)
+ {
+ x9Encoding[i] = keyEnc[32 - i];
+ x9Encoding[i + 32] = keyEnc[64 - i];
+ }
+
+ GOST3410PublicKeyAlgParameters gostParams = GOST3410PublicKeyAlgParameters.getInstance(keyInfo.getAlgorithm().getParameters());
+
+ ECGOST3410Parameters ecDomainParameters =
+ new ECGOST3410Parameters(
+ new ECNamedDomainParameters(gostParams.getPublicKeyParamSet(), ECGOST3410NamedCurves.getByOID(gostParams.getPublicKeyParamSet())),
+ gostParams.getPublicKeyParamSet(),
+ gostParams.getDigestParamSet(),
+ gostParams.getEncryptionParamSet());
+
+
+ return new ECPublicKeyParameters(ecDomainParameters.getCurve().decodePoint(x9Encoding), ecDomainParameters);
+
+ }
+ }
+
+ private static class GOST3410_2012Converter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ {
+ ASN1ObjectIdentifier algOid = keyInfo.getAlgorithm().getAlgorithm();
+ DERBitString bits = keyInfo.getPublicKeyData();
+ ASN1OctetString key;
+
+ try
+ {
+ key = (ASN1OctetString)ASN1Primitive.fromByteArray(bits.getBytes());
+ }
+ catch (IOException ex)
+ {
+ throw new IllegalArgumentException("error recovering public key");
+ }
+
+ byte[] keyEnc = key.getOctets();
+
+ int fieldSize = 32;
+ if (algOid.equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512))
+ {
+ fieldSize = 64;
+ }
+
+ int keySize = 2 * fieldSize;
+
+ byte[] x9Encoding = new byte[1 + keySize];
+ x9Encoding[0] = 0x04;
+ for (int i = 1; i <= fieldSize; ++i)
+ {
+ x9Encoding[i] = keyEnc[fieldSize - i];
+ x9Encoding[i + fieldSize] = keyEnc[keySize - i];
+ }
+
+ GOST3410PublicKeyAlgParameters gostParams = GOST3410PublicKeyAlgParameters.getInstance(keyInfo.getAlgorithm().getParameters());
+
+ ECGOST3410Parameters ecDomainParameters =
+ new ECGOST3410Parameters(
+ new ECNamedDomainParameters(gostParams.getPublicKeyParamSet(), ECGOST3410NamedCurves.getByOID(gostParams.getPublicKeyParamSet())),
+ gostParams.getPublicKeyParamSet(),
+ gostParams.getDigestParamSet(),
+ gostParams.getEncryptionParamSet());
+
+
+ return new ECPublicKeyParameters(ecDomainParameters.getCurve().decodePoint(x9Encoding), ecDomainParameters);
+ }
+ }
+
+ private static class DSTUConverter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ throws IOException
+ {
+ DERBitString bits = keyInfo.getPublicKeyData();
+ ASN1OctetString key;
+
+ try
+ {
+ key = (ASN1OctetString)ASN1Primitive.fromByteArray(bits.getBytes());
+ }
+ catch (IOException ex)
+ {
+ throw new IllegalArgumentException("error recovering public key");
+ }
+
+ byte[] keyEnc = key.getOctets();
+
+ if (keyInfo.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
+ {
+ reverseBytes(keyEnc);
+ }
+
+ DSTU4145Params dstuParams = DSTU4145Params.getInstance(keyInfo.getAlgorithm().getParameters());
+
+ ECDomainParameters ecDomain;
+ if (dstuParams.isNamedCurve())
+ {
+ ASN1ObjectIdentifier curveOid = dstuParams.getNamedCurve();
+
+ ecDomain = DSTU4145NamedCurves.getByOID(curveOid);
+ }
+ else
+ {
+ DSTU4145ECBinary binary = dstuParams.getECBinary();
+ byte[] b_bytes = binary.getB();
+ if (keyInfo.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
+ {
+ reverseBytes(b_bytes);
+ }
+ DSTU4145BinaryField field = binary.getField();
+ ECCurve curve = new ECCurve.F2m(field.getM(), field.getK1(), field.getK2(), field.getK3(), binary.getA(), new BigInteger(1, b_bytes));
+ byte[] g_bytes = binary.getG();
+ if (keyInfo.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
+ {
+ reverseBytes(g_bytes);
+ }
+ ecDomain = new ECDomainParameters(curve, DSTU4145PointEncoder.decodePoint(curve, g_bytes), binary.getN());
+ }
+
+ return new ECPublicKeyParameters(DSTU4145PointEncoder.decodePoint(ecDomain.getCurve(), keyEnc), ecDomain);
+ }
+
+ private void reverseBytes(byte[] bytes)
+ {
+ byte tmp;
+
+ for (int i = 0; i < bytes.length / 2; i++)
+ {
+ tmp = bytes[i];
+ bytes[i] = bytes[bytes.length - 1 - i];
+ bytes[bytes.length - 1 - i] = tmp;
+ }
+ }
+ }
+
+ private static class X25519Converter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ {
+ return new X25519PublicKeyParameters(getRawKey(keyInfo, defaultParams, X25519PublicKeyParameters.KEY_SIZE), 0);
+ }
+ }
+
+ private static class X448Converter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ {
+ return new X448PublicKeyParameters(getRawKey(keyInfo, defaultParams, X448PublicKeyParameters.KEY_SIZE), 0);
+ }
+ }
+
+ private static class Ed25519Converter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ {
+ return new Ed25519PublicKeyParameters(getRawKey(keyInfo, defaultParams, Ed25519PublicKeyParameters.KEY_SIZE), 0);
+ }
+ }
+
+ private static class Ed448Converter
+ extends SubjectPublicKeyInfoConverter
+ {
+ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams)
+ {
+ return new Ed448PublicKeyParameters(getRawKey(keyInfo, defaultParams, Ed448PublicKeyParameters.KEY_SIZE), 0);
+ }
+ }
+ */
+ // END Android-removed: Unsupported algorithms
+
+ private static byte[] getRawKey(SubjectPublicKeyInfo keyInfo, Object defaultParams, int expectedSize)
+ {
+ /*
+ * TODO[RFC 8422]
+ * - Require defaultParams == null?
+ * - Require keyInfo.getAlgorithm().getParameters() == null?
+ */
+ byte[] result = keyInfo.getPublicKeyData().getOctets();
+ if (expectedSize != result.length)
{
- throw new RuntimeException("algorithm identifier in key not recognised");
+ throw new RuntimeException("public key encoding has incorrect length");
}
+ return result;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java
index cd24f069..34ac2b0a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java
@@ -41,7 +41,7 @@ public class PKIXExtendedParameters
* when the end certificate was signed. The CA (or Root CA) certificate must
* have been valid, when the CA certificate was signed and so on. So the
* {@link PKIXParameters#setDate(Date)} method sets the time, when
- * the <em>end certificate</em> must have been valid. <p/> It is used e.g.
+ * the <em>end certificate</em> must have been valid. It is used e.g.
* in the German signature law.
*/
public static final int CHAIN_VALIDITY_MODEL = 1;
@@ -337,4 +337,8 @@ public class PKIXExtendedParameters
return revocationEnabled;
}
+ public boolean getPolicyQualifiersRejected()
+ {
+ return baseParameters.getPolicyQualifiersRejected();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/io/DigestUpdatingOutputStream.java b/bcprov/src/main/java/org/bouncycastle/jcajce/io/DigestUpdatingOutputStream.java
new file mode 100644
index 00000000..3e3542da
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/io/DigestUpdatingOutputStream.java
@@ -0,0 +1,34 @@
+package org.bouncycastle.jcajce.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+
+class DigestUpdatingOutputStream
+ extends OutputStream
+{
+ private MessageDigest digest;
+
+ DigestUpdatingOutputStream(MessageDigest digest)
+ {
+ this.digest = digest;
+ }
+
+ public void write(byte[] bytes, int off, int len)
+ throws IOException
+ {
+ digest.update(bytes, off, len);
+ }
+
+ public void write(byte[] bytes)
+ throws IOException
+ {
+ digest.update(bytes);
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ digest.update((byte)b);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/io/MacUpdatingOutputStream.java b/bcprov/src/main/java/org/bouncycastle/jcajce/io/MacUpdatingOutputStream.java
new file mode 100644
index 00000000..88496e82
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/io/MacUpdatingOutputStream.java
@@ -0,0 +1,35 @@
+package org.bouncycastle.jcajce.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.crypto.Mac;
+
+class MacUpdatingOutputStream
+ extends OutputStream
+{
+ private Mac mac;
+
+ MacUpdatingOutputStream(Mac mac)
+ {
+ this.mac = mac;
+ }
+
+ public void write(byte[] bytes, int off, int len)
+ throws IOException
+ {
+ mac.update(bytes, off, len);
+ }
+
+ public void write(byte[] bytes)
+ throws IOException
+ {
+ mac.update(bytes);
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ mac.update((byte)b);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/io/OutputStreamFactory.java b/bcprov/src/main/java/org/bouncycastle/jcajce/io/OutputStreamFactory.java
new file mode 100644
index 00000000..92763281
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/io/OutputStreamFactory.java
@@ -0,0 +1,46 @@
+package org.bouncycastle.jcajce.io;
+
+import java.io.OutputStream;
+import java.security.MessageDigest;
+import java.security.Signature;
+
+import javax.crypto.Mac;
+
+/**
+ * Utility class for creating OutputStreams from different JCA/JCE operators.
+ */
+public class OutputStreamFactory
+{
+ /**
+ * Create an OutputStream that wraps a signature.
+ *
+ * @param signature the signature to be updated as the stream is written to.
+ * @return an OutputStream.
+ */
+ public static OutputStream createStream(Signature signature)
+ {
+ return new SignatureUpdatingOutputStream(signature);
+ }
+
+ /**
+ * Create an OutputStream that wraps a digest.
+ *
+ * @param digest the digest to be updated as the stream is written to.
+ * @return an OutputStream.
+ */
+ public static OutputStream createStream(MessageDigest digest)
+ {
+ return new DigestUpdatingOutputStream(digest);
+ }
+
+ /**
+ * Create an OutputStream that wraps a mac.
+ *
+ * @param mac the signature to be updated as the stream is written to.
+ * @return an OutputStream.
+ */
+ public static OutputStream createStream(Mac mac)
+ {
+ return new MacUpdatingOutputStream(mac);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/io/SignatureUpdatingOutputStream.java b/bcprov/src/main/java/org/bouncycastle/jcajce/io/SignatureUpdatingOutputStream.java
new file mode 100644
index 00000000..f092df1b
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/io/SignatureUpdatingOutputStream.java
@@ -0,0 +1,56 @@
+package org.bouncycastle.jcajce.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.Signature;
+import java.security.SignatureException;
+
+class SignatureUpdatingOutputStream
+ extends OutputStream
+{
+ private Signature sig;
+
+ SignatureUpdatingOutputStream(Signature sig)
+ {
+ this.sig = sig;
+ }
+
+ public void write(byte[] bytes, int off, int len)
+ throws IOException
+ {
+ try
+ {
+ sig.update(bytes, off, len);
+ }
+ catch (SignatureException e)
+ {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public void write(byte[] bytes)
+ throws IOException
+ {
+ try
+ {
+ sig.update(bytes);
+ }
+ catch (SignatureException e)
+ {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ try
+ {
+ sig.update((byte)b);
+ }
+ catch (SignatureException e)
+ {
+ throw new IOException(e.getMessage());
+ }
+ }
+}
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 dcc963cc..a0c2f84e 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
@@ -62,6 +62,36 @@ public class DH
provider.addAlgorithm("Cipher.DHIESwithAES-CBC", PREFIX + "IESCipher$IESwithAESCBC");
provider.addAlgorithm("Cipher.DHIESWITHAES-CBC", PREFIX + "IESCipher$IESwithAESCBC");
provider.addAlgorithm("Cipher.DHIESWITHDESEDE-CBC", PREFIX + "IESCipher$IESwithDESedeCBC");
+
+ provider.addAlgorithm("KeyAgreement.DHWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHwithSHA1KDF");
+ provider.addAlgorithm("KeyAgreement.DHWITHSHA224KDF", PREFIX + "KeyAgreementSpi$DHwithSHA224KDF");
+ provider.addAlgorithm("KeyAgreement.DHWITHSHA256KDF", PREFIX + "KeyAgreementSpi$DHwithSHA256KDF");
+ provider.addAlgorithm("KeyAgreement.DHWITHSHA384KDF", PREFIX + "KeyAgreementSpi$DHwithSHA384KDF");
+ provider.addAlgorithm("KeyAgreement.DHWITHSHA512KDF", PREFIX + "KeyAgreementSpi$DHwithSHA512KDF");
+
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA1KDF");
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA224KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA224KDF");
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA256KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA256KDF");
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA384KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA384KDF");
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA512KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA512KDF");
+
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA1CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA1CKDF");
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA224CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA224CKDF");
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA256CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA256CKDF");
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA384CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA384CKDF");
+ provider.addAlgorithm("KeyAgreement.DHUWITHSHA512CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA512CKDF");
+
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA1KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA1KDF");
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA224KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA224KDF");
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA256KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA256KDF");
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA384KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA384KDF");
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA512KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA512KDF");
+
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA1CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA1CKDF");
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA224CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA224CKDF");
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA256CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA256CKDF");
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA384CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA384CKDF");
+ provider.addAlgorithm("KeyAgreement.MQVWITHSHA512CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA512CKDF");
*/
// END Android-removed: Unsupported algorithms
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
index 44bf12ef..6323b75f 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
@@ -84,10 +84,6 @@ public class DSA
provider.addAlgorithm("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
// END Android-changed: Change primary ID from DSA to SHA1withDSA
- // BEGIN Android-removed: Unsupported algorithms
- // provider.addAlgorithm("Alg.Alias.Signature.1.2.840.10040.4.3", "DSA");
- // END Android-removed: Unsupported algorithms
-
AsymmetricKeyInfoConverter keyFact = new KeyFactorySpi();
for (int i = 0; i != DSAUtil.dsaOids.length; i++)
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 016b465f..b79b0c51 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
@@ -50,27 +50,70 @@ public class EC
provider.addAttributes("KeyAgreement.ECCDH", generalEcAttributes);
provider.addAlgorithm("KeyAgreement.ECCDH", PREFIX + "KeyAgreementSpi$DHC");
- provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA1KDFAndSharedInfo");
- provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_cofactorDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA1KDFAndSharedInfo");
+ provider.addAttributes("KeyAgreement.ECCDHU", generalEcAttributes);
+ provider.addAlgorithm("KeyAgreement.ECCDHU", PREFIX + "KeyAgreementSpi$DHUC");
- provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA224KDFAndSharedInfo");
- provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA224KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement.ECDHWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHwithSHA1KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA1KDF", PREFIX + "KeyAgreementSpi$CDHwithSHA1KDFAndSharedInfo");
- provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA256KDFAndSharedInfo");
- provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA256KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement.ECDHWITHSHA224KDF", PREFIX + "KeyAgreementSpi$DHwithSHA224KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA224KDF", PREFIX + "KeyAgreementSpi$CDHwithSHA224KDFAndSharedInfo");
- provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA384KDFAndSharedInfo");
- provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA384KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement.ECDHWITHSHA256KDF", PREFIX + "KeyAgreementSpi$DHwithSHA256KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA256KDF", PREFIX + "KeyAgreementSpi$CDHwithSHA256KDFAndSharedInfo");
- provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA512KDFAndSharedInfo");
- provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA512KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement.ECDHWITHSHA384KDF", PREFIX + "KeyAgreementSpi$DHwithSHA384KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA384KDF", PREFIX + "KeyAgreementSpi$CDHwithSHA384KDFAndSharedInfo");
- provider.addAlgorithm("KeyAgreement.ECDHWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHwithSHA1KDF");
+ provider.addAlgorithm("KeyAgreement.ECDHWITHSHA512KDF", PREFIX + "KeyAgreementSpi$DHwithSHA512KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA512KDF", PREFIX + "KeyAgreementSpi$CDHwithSHA512KDFAndSharedInfo");
+
+ provider.addAlgorithm("KeyAgreement", X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA1KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement", X9ObjectIdentifiers.dhSinglePass_cofactorDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA1KDFAndSharedInfo");
+
+ provider.addAlgorithm("KeyAgreement", SECObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA224KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement", SECObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA224KDFAndSharedInfo");
+
+ provider.addAlgorithm("KeyAgreement", SECObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA256KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement", SECObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA256KDFAndSharedInfo");
+
+ provider.addAlgorithm("KeyAgreement", SECObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA384KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement", SECObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA384KDFAndSharedInfo");
+
+ provider.addAlgorithm("KeyAgreement", SECObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA512KDFAndSharedInfo");
+ provider.addAlgorithm("KeyAgreement", SECObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme, PREFIX + "KeyAgreementSpi$CDHwithSHA512KDFAndSharedInfo");
provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA1CKDF", PREFIX + "KeyAgreementSpi$DHwithSHA1CKDF");
provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA256CKDF", PREFIX + "KeyAgreementSpi$DHwithSHA256CKDF");
provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA384CKDF", PREFIX + "KeyAgreementSpi$DHwithSHA384CKDF");
provider.addAlgorithm("KeyAgreement.ECCDHWITHSHA512CKDF", PREFIX + "KeyAgreementSpi$DHwithSHA512CKDF");
+
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA1CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA1CKDF");
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA224CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA224CKDF");
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA256CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA256CKDF");
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA384CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA384CKDF");
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA512CKDF", PREFIX + "KeyAgreementSpi$DHUwithSHA512CKDF");
+
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA1KDF");
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA224KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA224KDF");
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA256KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA256KDF");
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA384KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA384KDF");
+ provider.addAlgorithm("KeyAgreement.ECCDHUWITHSHA512KDF", PREFIX + "KeyAgreementSpi$DHUwithSHA512KDF");
+
+ provider.addAlgorithm("KeyAgreement.ECKAEGWITHSHA1KDF", PREFIX + "KeyAgreementSpi$ECKAEGwithSHA1KDF");
+ provider.addAlgorithm("KeyAgreement.ECKAEGWITHSHA224KDF", PREFIX + "KeyAgreementSpi$ECKAEGwithSHA224KDF");
+ provider.addAlgorithm("KeyAgreement.ECKAEGWITHSHA256KDF", PREFIX + "KeyAgreementSpi$ECKAEGwithSHA256KDF");
+ provider.addAlgorithm("KeyAgreement.ECKAEGWITHSHA384KDF", PREFIX + "KeyAgreementSpi$ECKAEGwithSHA384KDF");
+ provider.addAlgorithm("KeyAgreement.ECKAEGWITHSHA512KDF", PREFIX + "KeyAgreementSpi$ECKAEGwithSHA512KDF");
+
+ provider.addAlgorithm("KeyAgreement", BSIObjectIdentifiers.ecka_eg_X963kdf_SHA1, PREFIX + "KeyAgreementSpi$ECKAEGwithSHA1KDF");
+ provider.addAlgorithm("KeyAgreement", BSIObjectIdentifiers.ecka_eg_X963kdf_SHA224, PREFIX + "KeyAgreementSpi$ECKAEGwithSHA224KDF");
+ provider.addAlgorithm("KeyAgreement", BSIObjectIdentifiers.ecka_eg_X963kdf_SHA256, PREFIX + "KeyAgreementSpi$ECKAEGwithSHA256KDF");
+ provider.addAlgorithm("KeyAgreement", BSIObjectIdentifiers.ecka_eg_X963kdf_SHA384, PREFIX + "KeyAgreementSpi$ECKAEGwithSHA384KDF");
+ provider.addAlgorithm("KeyAgreement", BSIObjectIdentifiers.ecka_eg_X963kdf_SHA512, PREFIX + "KeyAgreementSpi$ECKAEGwithSHA512KDF");
+
+ provider.addAlgorithm("KeyAgreement", BSIObjectIdentifiers.ecka_eg_X963kdf_RIPEMD160, PREFIX + "KeyAgreementSpi$ECKAEGwithRIPEMD160KDF");
+ provider.addAlgorithm("KeyAgreement.ECKAEGWITHRIPEMD160KDF", PREFIX + "KeyAgreementSpi$ECKAEGwithRIPEMD160KDF");
*/
// END Android-removed: Unsupported algorithms
@@ -120,6 +163,12 @@ public class EC
provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA384CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA384CKDF");
provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA512CKDF", PREFIX + "KeyAgreementSpi$MQVwithSHA512CKDF");
+ provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA1KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA1KDF");
+ provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA224KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA224KDF");
+ provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA256KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA256KDF");
+ provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA384KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA384KDF");
+ provider.addAlgorithm("KeyAgreement.ECMQVWITHSHA512KDF", PREFIX + "KeyAgreementSpi$MQVwithSHA512KDF");
+
provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA1KDFAndSharedInfo");
provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.mqvSinglePass_sha224kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA224KDFAndSharedInfo");
provider.addAlgorithm("KeyAgreement." + SECObjectIdentifiers.mqvSinglePass_sha256kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA256KDFAndSharedInfo");
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParameterGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParameterGeneratorSpi.java
index bf6bfe71..b1ef7e5e 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParameterGeneratorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParameterGeneratorSpi.java
@@ -8,6 +8,7 @@ import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.DHGenParameterSpec;
import javax.crypto.spec.DHParameterSpec;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.generators.DHParametersGenerator;
import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAlgorithmParameterGeneratorSpi;
@@ -57,7 +58,7 @@ public class AlgorithmParameterGeneratorSpi
}
else
{
- pGen.init(strength, certainty, new SecureRandom());
+ pGen.init(strength, certainty, CryptoServicesRegistrar.getSecureRandom());
}
DHParameters p = pGen.generateParameters();
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPrivateKey.java
index 6fb54b67..21182ef1 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPrivateKey.java
@@ -19,11 +19,14 @@ import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x9.DHDomainParameters;
import org.bouncycastle.asn1.x9.DomainParameters;
+import org.bouncycastle.asn1.x9.ValidationParams;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import org.bouncycastle.crypto.params.DHValidationParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
+import org.bouncycastle.jcajce.spec.DHDomainParameterSpec;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
@@ -36,6 +39,7 @@ public class BCDHPrivateKey
private transient DHParameterSpec dhSpec;
private transient PrivateKeyInfo info;
+ private transient DHPrivateKeyParameters dhPrivateKey;
private transient PKCS12BagAttributeCarrierImpl attrCarrier = new PKCS12BagAttributeCarrierImpl();
@@ -75,29 +79,37 @@ public class BCDHPrivateKey
if (params.getL() != null)
{
this.dhSpec = new DHParameterSpec(params.getP(), params.getG(), params.getL().intValue());
+ this.dhPrivateKey = new DHPrivateKeyParameters(x,
+ new DHParameters(params.getP(), params.getG(), null, params.getL().intValue()));
}
else
{
this.dhSpec = new DHParameterSpec(params.getP(), params.getG());
+ this.dhPrivateKey = new DHPrivateKeyParameters(x,
+ new DHParameters(params.getP(), params.getG()));
}
}
else if (id.equals(X9ObjectIdentifiers.dhpublicnumber))
{
DomainParameters params = DomainParameters.getInstance(seq);
- this.dhSpec = new DHParameterSpec(params.getP(), params.getG());
+ this.dhSpec = new DHDomainParameterSpec(params.getP(), params.getQ(), params.getG(), params.getJ(), 0);
+ this.dhPrivateKey = new DHPrivateKeyParameters(x,
+ new DHParameters(params.getP(), params.getG(), params.getQ(), params.getJ(), null));
}
else
{
throw new IllegalArgumentException("unknown algorithm type: " + id);
}
+
+
}
BCDHPrivateKey(
DHPrivateKeyParameters params)
{
this.x = params.getX();
- this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), params.getParameters().getL());
+ this.dhSpec = new DHDomainParameterSpec(params.getParameters());
}
public String getAlgorithm()
@@ -130,16 +142,35 @@ public class BCDHPrivateKey
return info.getEncoded(ASN1Encoding.DER);
}
- PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL()).toASN1Primitive()), new ASN1Integer(getX()));
-
+ PrivateKeyInfo info;
+ if (dhSpec instanceof DHDomainParameterSpec && ((DHDomainParameterSpec)dhSpec).getQ() != null)
+ {
+ DHParameters params = ((DHDomainParameterSpec)dhSpec).getDomainParameters();
+ DHValidationParameters validationParameters = params.getValidationParameters();
+ ValidationParams vParams = null;
+ if (validationParameters != null)
+ {
+ vParams = new ValidationParams(validationParameters.getSeed(), validationParameters.getCounter());
+ }
+ info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.dhpublicnumber, new DomainParameters(params.getP(), params.getG(), params.getQ(), params.getJ(), vParams).toASN1Primitive()), new ASN1Integer(getX()));
+ }
+ else
+ {
+ info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL()).toASN1Primitive()), new ASN1Integer(getX()));
+ }
return info.getEncoded(ASN1Encoding.DER);
}
catch (Exception e)
- {
+ {
return null;
}
}
+ public String toString()
+ {
+ return DHUtil.privateKeyToString("DH", x, new DHParameters(dhSpec.getP(), dhSpec.getG()));
+ }
+
public DHParameterSpec getParams()
{
return dhSpec;
@@ -150,6 +181,20 @@ public class BCDHPrivateKey
return x;
}
+ DHPrivateKeyParameters engineGetKeyParameters()
+ {
+ if (dhPrivateKey != null)
+ {
+ return dhPrivateKey;
+ }
+
+ if (dhSpec instanceof DHDomainParameterSpec)
+ {
+ return new DHPrivateKeyParameters(x, ((DHDomainParameterSpec)dhSpec).getDomainParameters());
+ }
+ return new DHPrivateKeyParameters(x, new DHParameters(dhSpec.getP(), dhSpec.getG(), null, dhSpec.getL()));
+ }
+
public boolean equals(
Object o)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java
index 1462a38b..039b8d3d 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java
@@ -23,6 +23,7 @@ import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.crypto.params.DHPublicKeyParameters;
import org.bouncycastle.crypto.params.DHValidationParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
+import org.bouncycastle.jcajce.spec.DHDomainParameterSpec;
public class BCDHPublicKey
implements DHPublicKey
@@ -55,7 +56,7 @@ public class BCDHPublicKey
DHPublicKeyParameters params)
{
this.y = params.getY();
- this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), params.getParameters().getL());
+ this.dhSpec = new DHDomainParameterSpec(params.getParameters());
this.dhPublicKey = params;
}
@@ -65,7 +66,15 @@ public class BCDHPublicKey
{
this.y = y;
this.dhSpec = dhSpec;
- this.dhPublicKey = new DHPublicKeyParameters(y, new DHParameters(dhSpec.getP(), dhSpec.getG()));
+
+ if (dhSpec instanceof DHDomainParameterSpec)
+ {
+ this.dhPublicKey = new DHPublicKeyParameters(y, ((DHDomainParameterSpec)dhSpec).getDomainParameters());
+ }
+ else
+ {
+ this.dhPublicKey = new DHPublicKeyParameters(y, new DHParameters(dhSpec.getP(), dhSpec.getG()));
+ }
}
public BCDHPublicKey(
@@ -107,7 +116,6 @@ public class BCDHPublicKey
{
DomainParameters params = DomainParameters.getInstance(seq);
- this.dhSpec = new DHParameterSpec(params.getP(), params.getG());
ValidationParams validationParams = params.getValidationParams();
if (validationParams != null)
{
@@ -118,6 +126,7 @@ public class BCDHPublicKey
{
this.dhPublicKey = new DHPublicKeyParameters(y, new DHParameters(params.getP(), params.getG(), params.getQ(), params.getJ(), null));
}
+ this.dhSpec = new DHDomainParameterSpec(dhPublicKey.getParameters());
}
else
{
@@ -142,9 +151,25 @@ public class BCDHPublicKey
return KeyUtil.getEncodedSubjectPublicKeyInfo(info);
}
+ if (dhSpec instanceof DHDomainParameterSpec && ((DHDomainParameterSpec)dhSpec).getQ() != null)
+ {
+ DHParameters params = ((DHDomainParameterSpec)dhSpec).getDomainParameters();
+ DHValidationParameters validationParameters = params.getValidationParameters();
+ ValidationParams vParams = null;
+ if (validationParameters != null)
+ {
+ vParams = new ValidationParams(validationParameters.getSeed(), validationParameters.getCounter());
+ }
+ return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.dhpublicnumber, new DomainParameters(params.getP(), params.getG(), params.getQ(), params.getJ(), vParams).toASN1Primitive()), new ASN1Integer(y));
+ }
return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL()).toASN1Primitive()), new ASN1Integer(y));
}
+ public String toString()
+ {
+ return DHUtil.publicKeyToString("DH", y, new DHParameters(dhSpec.getP(), dhSpec.getG()));
+ }
+
public DHParameterSpec getParams()
{
return dhSpec;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/DHUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/DHUtil.java
new file mode 100644
index 00000000..f26b83bd
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/DHUtil.java
@@ -0,0 +1,45 @@
+package org.bouncycastle.jcajce.provider.asymmetric.dh;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.params.DHParameters;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Fingerprint;
+import org.bouncycastle.util.Strings;
+
+class DHUtil
+{
+ static String privateKeyToString(String algorithm, BigInteger x, DHParameters dhParams)
+ {
+ StringBuffer buf = new StringBuffer();
+ String nl = Strings.lineSeparator();
+
+ BigInteger y = dhParams.getG().modPow(x, dhParams.getP());
+
+ buf.append(algorithm);
+ buf.append(" Private Key [").append(generateKeyFingerprint(y, dhParams)).append("]").append(nl);
+ buf.append(" Y: ").append(y.toString(16)).append(nl);
+
+ return buf.toString();
+ }
+
+ static String publicKeyToString(String algorithm, BigInteger y, DHParameters dhParams)
+ {
+ StringBuffer buf = new StringBuffer();
+ String nl = Strings.lineSeparator();
+
+ buf.append(algorithm);
+ buf.append(" Public Key [").append(generateKeyFingerprint(y, dhParams)).append("]").append(nl);
+ buf.append(" Y: ").append(y.toString(16)).append(nl);
+
+ return buf.toString();
+ }
+
+ private static String generateKeyFingerprint(BigInteger y, DHParameters dhParams)
+ {
+ return new Fingerprint(
+ Arrays.concatenate(
+ y.toByteArray(),
+ dhParams.getP().toByteArray(), dhParams.getG().toByteArray())).toString();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java
index 890674ed..502854de 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java
@@ -5,6 +5,8 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
@@ -15,11 +17,28 @@ import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.SecretKeySpec;
+import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.DerivationFunction;
-// Android-removed: Unsupported algorithm
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.agreement.DHUnifiedAgreement;
+// import org.bouncycastle.crypto.agreement.MQVBasicAgreement;
+// import org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator;
// import org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator;
+// import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
+// import org.bouncycastle.crypto.params.DHMQVPrivateParameters;
+// import org.bouncycastle.crypto.params.DHMQVPublicParameters;
+import org.bouncycastle.crypto.params.DHParameters;
+import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import org.bouncycastle.crypto.params.DHPublicKeyParameters;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.params.DHUPrivateParameters;
+// import org.bouncycastle.crypto.params.DHUPublicParameters;
// import org.bouncycastle.crypto.util.DigestFactory;
import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi;
+import org.bouncycastle.jcajce.spec.DHDomainParameterSpec;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.jcajce.spec.DHUParameterSpec;
+// import org.bouncycastle.jcajce.spec.MQVParameterSpec;
import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec;
/**
@@ -33,22 +52,58 @@ public class KeyAgreementSpi
private static final BigInteger ONE = BigInteger.valueOf(1);
private static final BigInteger TWO = BigInteger.valueOf(2);
+ // Android-removed: Unsupported algorithms
+ // private final DHUnifiedAgreement unifiedAgreement;
+ private final BasicAgreement mqvAgreement;
+
+ // Android-removed: Unsupported algorithms
+ // private DHUParameterSpec dheParameters;
+ // private MQVParameterSpec mqvParameters;
+
private BigInteger x;
private BigInteger p;
private BigInteger g;
- private BigInteger result;
+ private byte[] result;
public KeyAgreementSpi()
{
- super("Diffie-Hellman", null);
+ this("Diffie-Hellman", null);
+ }
+
+ public KeyAgreementSpi(
+ String kaAlgorithm,
+ DerivationFunction kdf)
+ {
+ super(kaAlgorithm, kdf);
+ // Android-removed: Unsupported algorithm
+ // this.unifiedAgreement = null;
+ this.mqvAgreement = null;
+ }
+
+ // BEGIN Android-removed: Unsupported algorithm
+ /*
+ public KeyAgreementSpi(
+ String kaAlgorithm,
+ DHUnifiedAgreement unifiedAgreement,
+ DerivationFunction kdf)
+ {
+ super(kaAlgorithm, kdf);
+ this.unifiedAgreement = unifiedAgreement;
+ this.mqvAgreement = null;
}
+ */
+ // END Android-removed: Unsupported algorithm
public KeyAgreementSpi(
String kaAlgorithm,
+ BasicAgreement mqvAgreement,
DerivationFunction kdf)
{
super(kaAlgorithm, kdf);
+ // Android-removed: Unsupported algorithm
+ // this.unifiedAgreement = null;
+ this.mqvAgreement = mqvAgreement;
}
protected byte[] bigIntToBytes(
@@ -112,18 +167,61 @@ public class KeyAgreementSpi
throw new InvalidKeyException("Invalid DH PublicKey");
}
- result = peerY.modPow(x, p);
- if (result.compareTo(ONE) == 0)
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ if (unifiedAgreement != null)
{
- throw new InvalidKeyException("Shared key can't be 1");
- }
+ if (!lastPhase)
+ {
+ throw new IllegalStateException("unified Diffie-Hellman can use only two key pairs");
+ }
+
+ DHPublicKeyParameters staticKey = generatePublicKeyParameter((PublicKey)key);
+ DHPublicKeyParameters ephemKey = generatePublicKeyParameter(dheParameters.getOtherPartyEphemeralKey());
+
+ DHUPublicParameters pKey = new DHUPublicParameters(staticKey, ephemKey);
+
+ result = unifiedAgreement.calculateAgreement(pKey);
- if (lastPhase)
+ return null;
+ }
+ else if (mqvAgreement != null)
{
+ if (!lastPhase)
+ {
+ throw new IllegalStateException("MQV Diffie-Hellman can use only two key pairs");
+ }
+
+ DHPublicKeyParameters staticKey = generatePublicKeyParameter((PublicKey)key);
+ DHPublicKeyParameters ephemKey = generatePublicKeyParameter(mqvParameters.getOtherPartyEphemeralKey());
+
+ DHMQVPublicParameters pKey = new DHMQVPublicParameters(staticKey, ephemKey);
+
+ result = bigIntToBytes(mqvAgreement.calculateAgreement(pKey));
+
return null;
}
+ else
+ {
+ */
+ // END Android-removed: Unsupported algorithms
+ BigInteger res = peerY.modPow(x, p);
+ if (res.compareTo(ONE) == 0)
+ {
+ throw new InvalidKeyException("Shared key can't be 1");
+ }
+
+ result = bigIntToBytes(res);
- return new BCDHPublicKey(result, pubKey.getParams());
+ if (lastPhase)
+ {
+ return null;
+ }
+
+ return new BCDHPublicKey(res, pubKey.getParams());
+ /*
+ }
+ */
}
protected byte[] engineGenerateSecret()
@@ -159,12 +257,10 @@ public class KeyAgreementSpi
throw new IllegalStateException("Diffie-Hellman not initialised.");
}
- byte[] res = bigIntToBytes(result);
-
// for JSSE compatibility
if (algorithm.equals("TlsPremasterSecret"))
{
- return new SecretKeySpec(trimZeroes(res), algorithm);
+ return new SecretKeySpec(trimZeroes(result), algorithm);
}
return super.engineGenerateSecret(algorithm);
@@ -190,11 +286,70 @@ public class KeyAgreementSpi
this.p = p.getP();
this.g = p.getG();
+ // Android-removed: Unsupported algorithm
+ // this.dheParameters = null;
+ this.ukmParameters = null;
+ }
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (params instanceof DHUParameterSpec)
+ {
+ if (unifiedAgreement == null)
+ {
+ throw new InvalidAlgorithmParameterException("agreement algorithm not DHU based");
+ }
+ this.p = privKey.getParams().getP();
+ this.g = privKey.getParams().getG();
+ this.dheParameters = (DHUParameterSpec)params;
+ this.ukmParameters = ((DHUParameterSpec)params).getUserKeyingMaterial();
+
+ if (dheParameters.getEphemeralPublicKey() != null)
+ {
+ unifiedAgreement.init(new DHUPrivateParameters(generatePrivateKeyParameter(privKey),
+ generatePrivateKeyParameter(dheParameters.getEphemeralPrivateKey()),
+ generatePublicKeyParameter(dheParameters.getEphemeralPublicKey())));
+ }
+ else
+ {
+ unifiedAgreement.init(new DHUPrivateParameters(generatePrivateKeyParameter(privKey),
+ generatePrivateKeyParameter(dheParameters.getEphemeralPrivateKey())));
+ }
}
+ else if (params instanceof MQVParameterSpec)
+ {
+ if (mqvAgreement == null)
+ {
+ throw new InvalidAlgorithmParameterException("agreement algorithm not MQV based");
+ }
+ this.p = privKey.getParams().getP();
+ this.g = privKey.getParams().getG();
+ this.mqvParameters = (MQVParameterSpec)params;
+ this.ukmParameters = ((MQVParameterSpec)params).getUserKeyingMaterial();
+
+ if (mqvParameters.getEphemeralPublicKey() != null)
+ {
+ mqvAgreement.init(new DHMQVPrivateParameters(generatePrivateKeyParameter(privKey),
+ generatePrivateKeyParameter(mqvParameters.getEphemeralPrivateKey()),
+ generatePublicKeyParameter(mqvParameters.getEphemeralPublicKey())));
+ }
+ else
+ {
+ mqvAgreement.init(new DHMQVPrivateParameters(generatePrivateKeyParameter(privKey),
+ generatePrivateKeyParameter(mqvParameters.getEphemeralPrivateKey())));
+ }
+ }
+ */
+ // END Android-removed: Unsupported algorithms
else if (params instanceof UserKeyingMaterialSpec)
{
+ if (kdf == null)
+ {
+ throw new InvalidAlgorithmParameterException("no KDF specified for UserKeyingMaterialSpec");
+ }
this.p = privKey.getParams().getP();
this.g = privKey.getParams().getG();
+ // Android-removed: Unsupported algorithm
+ // this.dheParameters = null;
this.ukmParameters = ((UserKeyingMaterialSpec)params).getUserKeyingMaterial();
}
else
@@ -208,7 +363,8 @@ public class KeyAgreementSpi
this.g = privKey.getParams().getG();
}
- this.x = this.result = privKey.getX();
+ this.x = privKey.getX();
+ this.result = bigIntToBytes(x);
}
protected void engineInit(
@@ -225,15 +381,69 @@ public class KeyAgreementSpi
this.p = privKey.getParams().getP();
this.g = privKey.getParams().getG();
- this.x = this.result = privKey.getX();
+ this.x = privKey.getX();
+ this.result = bigIntToBytes(x);
}
protected byte[] calcSecret()
{
- return bigIntToBytes(result);
+ return result;
}
- // BEGIN Android-removed: Unsupported algorithm
+ private DHPrivateKeyParameters generatePrivateKeyParameter(PrivateKey privKey)
+ throws InvalidKeyException
+ {
+ if (privKey instanceof DHPrivateKey)
+ {
+ if (privKey instanceof BCDHPrivateKey)
+ {
+ return ((BCDHPrivateKey)privKey).engineGetKeyParameters();
+ }
+ else
+ {
+ DHPrivateKey pub = (DHPrivateKey)privKey;
+
+ DHParameterSpec params = pub.getParams();
+ return new DHPrivateKeyParameters(pub.getX(),
+ new DHParameters(params.getP(), params.getG(), null, params.getL()));
+ }
+ }
+ else
+ {
+ throw new InvalidKeyException("private key not a DHPrivateKey");
+ }
+ }
+
+ private DHPublicKeyParameters generatePublicKeyParameter(PublicKey pubKey)
+ throws InvalidKeyException
+ {
+ if (pubKey instanceof DHPublicKey)
+ {
+ if (pubKey instanceof BCDHPublicKey)
+ {
+ return ((BCDHPublicKey)pubKey).engineGetKeyParameters();
+ }
+ else
+ {
+ DHPublicKey pub = (DHPublicKey)pubKey;
+
+ DHParameterSpec params = pub.getParams();
+
+ if (params instanceof DHDomainParameterSpec)
+ {
+ return new DHPublicKeyParameters(pub.getY(), ((DHDomainParameterSpec)params).getDomainParameters());
+ }
+ return new DHPublicKeyParameters(pub.getY(),
+ new DHParameters(params.getP(), params.getG(), null, params.getL()));
+ }
+ }
+ else
+ {
+ throw new InvalidKeyException("public key not a DHPublicKey");
+ }
+ }
+
+ // BEGIN Android-removed: Unsupported algorithms
/*
public static class DHwithRFC2631KDF
extends KeyAgreementSpi
@@ -243,6 +453,276 @@ public class KeyAgreementSpi
super("DHwithRFC2631KDF", new DHKEKGenerator(DigestFactory.createSHA1()));
}
}
+
+ public static class DHwithSHA1KDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA1KDF()
+ {
+ super("DHwithSHA1CKDF", new KDF2BytesGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ public static class DHwithSHA224KDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA224KDF()
+ {
+ super("DHwithSHA224CKDF", new KDF2BytesGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ public static class DHwithSHA256KDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA256KDF()
+ {
+ super("DHwithSHA256CKDF", new KDF2BytesGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ public static class DHwithSHA384KDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA384KDF()
+ {
+ super("DHwithSHA384KDF", new KDF2BytesGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ public static class DHwithSHA512KDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA512KDF()
+ {
+ super("DHwithSHA512KDF", new KDF2BytesGenerator(DigestFactory.createSHA512()));
+ }
+ }
+
+ public static class DHwithSHA1CKDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA1CKDF()
+ {
+ super("DHwithSHA1CKDF", new ConcatenationKDFGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ public static class DHwithSHA224CKDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA224CKDF()
+ {
+ super("DHwithSHA224CKDF", new ConcatenationKDFGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ public static class DHwithSHA256CKDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA256CKDF()
+ {
+ super("DHwithSHA256CKDF", new ConcatenationKDFGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ public static class DHwithSHA384CKDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA384CKDF()
+ {
+ super("DHwithSHA384CKDF", new ConcatenationKDFGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ public static class DHwithSHA512CKDF
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA512CKDF()
+ {
+ super("DHwithSHA512CKDF", new ConcatenationKDFGenerator(DigestFactory.createSHA512()));
+ }
+ }
+
+ public static class DHUwithSHA1KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA1KDF()
+ {
+ super("DHUwithSHA1KDF", new DHUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ public static class DHUwithSHA224KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA224KDF()
+ {
+ super("DHUwithSHA224KDF", new DHUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ public static class DHUwithSHA256KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA256KDF()
+ {
+ super("DHUwithSHA256KDF", new DHUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ public static class DHUwithSHA384KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA384KDF()
+ {
+ super("DHUwithSHA384KDF", new DHUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ public static class DHUwithSHA512KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA512KDF()
+ {
+ super("DHUwithSHA512KDF", new DHUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
+ }
+ }
+
+ public static class DHUwithSHA1CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA1CKDF()
+ {
+ super("DHUwithSHA1CKDF", new DHUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ public static class DHUwithSHA224CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA224CKDF()
+ {
+ super("DHUwithSHA224CKDF", new DHUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ public static class DHUwithSHA256CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA256CKDF()
+ {
+ super("DHUwithSHA256CKDF", new DHUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ public static class DHUwithSHA384CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA384CKDF()
+ {
+ super("DHUwithSHA384CKDF", new DHUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ public static class DHUwithSHA512CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA512CKDF()
+ {
+ super("DHUwithSHA512CKDF", new DHUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA512()));
+ }
+ }
+
+ public static class MQVwithSHA1KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA1KDF()
+ {
+ super("MQVwithSHA1KDF", new MQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ public static class MQVwithSHA224KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA224KDF()
+ {
+ super("MQVwithSHA224KDF", new MQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ public static class MQVwithSHA256KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA256KDF()
+ {
+ super("MQVwithSHA256KDF", new MQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ public static class MQVwithSHA384KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA384KDF()
+ {
+ super("MQVwithSHA384KDF", new MQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ public static class MQVwithSHA512KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA512KDF()
+ {
+ super("MQVwithSHA512KDF", new MQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
+ }
+ }
+
+ public static class MQVwithSHA1CKDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA1CKDF()
+ {
+ super("MQVwithSHA1CKDF", new MQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ public static class MQVwithSHA224CKDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA224CKDF()
+ {
+ super("MQVwithSHA224CKDF", new MQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ public static class MQVwithSHA256CKDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA256CKDF()
+ {
+ super("MQVwithSHA256CKDF", new MQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ public static class MQVwithSHA384CKDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA384CKDF()
+ {
+ super("MQVwithSHA384CKDF", new MQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ public static class MQVwithSHA512CKDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA512CKDF()
+ {
+ super("MQVwithSHA512CKDF", new MQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA512()));
+ }
+ }
*/
- // END Android-removed: Unsupported algorithm
+ // END Android-removed: Unsupported algorithms
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyPairGeneratorSpi.java
index 864bf56f..1e426b12 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyPairGeneratorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyPairGeneratorSpi.java
@@ -9,6 +9,7 @@ import java.util.Hashtable;
import javax.crypto.spec.DHParameterSpec;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator;
import org.bouncycastle.crypto.generators.DHParametersGenerator;
import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
@@ -16,6 +17,7 @@ import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
import org.bouncycastle.crypto.params.DHPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator;
+import org.bouncycastle.jcajce.spec.DHDomainParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Integers;
@@ -28,7 +30,7 @@ public class KeyPairGeneratorSpi
DHKeyGenerationParameters param;
DHBasicKeyPairGenerator engine = new DHBasicKeyPairGenerator();
int strength = 2048;
- SecureRandom random = new SecureRandom();
+ SecureRandom random = CryptoServicesRegistrar.getSecureRandom();
boolean initialised = false;
public KeyPairGeneratorSpi()
@@ -56,12 +58,28 @@ public class KeyPairGeneratorSpi
}
DHParameterSpec dhParams = (DHParameterSpec)params;
- param = new DHKeyGenerationParameters(random, new DHParameters(dhParams.getP(), dhParams.getG(), null, dhParams.getL()));
-
+ try
+ {
+ param = convertParams(random, dhParams);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new InvalidAlgorithmParameterException(e.getMessage(), e);
+ }
+
engine.init(param);
initialised = true;
}
+ private DHKeyGenerationParameters convertParams(SecureRandom random, DHParameterSpec dhParams)
+ {
+ if (dhParams instanceof DHDomainParameterSpec)
+ {
+ return new DHKeyGenerationParameters(random, ((DHDomainParameterSpec)dhParams).getDomainParameters());
+ }
+ return new DHKeyGenerationParameters(random, new DHParameters(dhParams.getP(), dhParams.getG(), null, dhParams.getL()));
+ }
+
public KeyPair generateKeyPair()
{
if (!initialised)
@@ -77,8 +95,8 @@ public class KeyPairGeneratorSpi
DHParameterSpec dhParams = BouncyCastleProvider.CONFIGURATION.getDHDefaultParameters(strength);
if (dhParams != null)
- {
- param = new DHKeyGenerationParameters(random, new DHParameters(dhParams.getP(), dhParams.getG(), null, dhParams.getL()));
+ {
+ param = convertParams(random, dhParams);
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java
index 6a0dffa1..1cc7cb3c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java
@@ -7,6 +7,7 @@ import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.DSAParameterSpec;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.generators.DSAParametersGenerator;
import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
@@ -71,7 +72,7 @@ public class AlgorithmParameterGeneratorSpi
if (random == null)
{
- random = new SecureRandom();
+ random = CryptoServicesRegistrar.getSecureRandom();
}
int certainty = PrimeCertaintyCalculator.getDefaultCertainty(strength);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPrivateKey.java
index 0fb4bd9e..d19c90ed 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPrivateKey.java
@@ -21,6 +21,7 @@ import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
+import org.bouncycastle.util.Strings;
public class BCDSAPrivateKey
implements DSAPrivateKey, PKCS12BagAttributeCarrier
@@ -164,4 +165,17 @@ public class BCDSAPrivateKey
out.writeObject(dsaSpec.getQ());
out.writeObject(dsaSpec.getG());
}
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ String nl = Strings.lineSeparator();
+
+ BigInteger y = getParams().getG().modPow(x, getParams().getP());
+
+ buf.append("DSA Private Key [").append(DSAUtil.generateKeyFingerprint(y, getParams())).append("]").append(nl);
+ buf.append(" Y: ").append(y.toString(16)).append(nl);
+
+ return buf.toString();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java
index 13223cb6..601fddd6 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java
@@ -137,8 +137,8 @@ public class BCDSAPublicKey
StringBuffer buf = new StringBuffer();
String nl = Strings.lineSeparator();
- buf.append("DSA Public Key").append(nl);
- buf.append(" y: ").append(this.getY().toString(16)).append(nl);
+ buf.append("DSA Public Key [").append(DSAUtil.generateKeyFingerprint(y, getParams())).append("]").append(nl);
+ buf.append(" Y: ").append(this.getY().toString(16)).append(nl);
return buf.toString();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
index 0384b1c8..8d1653f1 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
@@ -1,6 +1,5 @@
package org.bouncycastle.jcajce.provider.asymmetric.dsa;
-import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
@@ -10,23 +9,20 @@ import java.security.SignatureException;
import java.security.SignatureSpi;
import java.security.spec.AlgorithmParameterSpec;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
+import org.bouncycastle.crypto.DSAExt;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.NullDigest;
// Android-added: Check DSA keys when generated
import org.bouncycastle.crypto.params.DSAKeyParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.crypto.signers.DSAEncoding;
// Android-removed: Unsupported algorithm
// import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
+import org.bouncycastle.crypto.signers.StandardDSAEncoding;
// Android-changed: Use Android digests
// import org.bouncycastle.crypto.util.DigestFactory;
import org.bouncycastle.crypto.digests.AndroidDigestFactory;
@@ -37,12 +33,13 @@ public class DSASigner
implements PKCSObjectIdentifiers, X509ObjectIdentifiers
{
private Digest digest;
- private DSA signer;
+ private DSAExt signer;
+ private DSAEncoding encoding = StandardDSAEncoding.INSTANCE;
private SecureRandom random;
protected DSASigner(
Digest digest,
- DSA signer)
+ DSAExt signer)
{
this.digest = digest;
this.signer = signer;
@@ -111,9 +108,9 @@ public class DSASigner
try
{
- BigInteger[] sig = signer.generateSignature(hash);
+ BigInteger[] sig = signer.generateSignature(hash);
- return derEncode(sig[0], sig[1]);
+ return encoding.encode(signer.getOrder(), sig[0], sig[1]);
}
catch (Exception e)
{
@@ -129,11 +126,11 @@ public class DSASigner
digest.doFinal(hash, 0);
- BigInteger[] sig;
+ BigInteger[] sig;
try
{
- sig = derDecode(sigBytes);
+ sig = encoding.decode(signer.getOrder(), sigBytes);
}
catch (Exception e)
{
@@ -172,7 +169,7 @@ public class DSASigner
// END Android-added: Check DSA keys when generated
/**
- * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
+ * @deprecated replaced with #engineSetParameter(java.security.spec.AlgorithmParameterSpec)
*/
protected void engineSetParameter(
String param,
@@ -187,36 +184,7 @@ public class DSASigner
protected Object engineGetParameter(
String param)
{
- throw new UnsupportedOperationException("engineSetParameter unsupported");
- }
-
- private byte[] derEncode(
- BigInteger r,
- BigInteger s)
- throws IOException
- {
- ASN1Integer[] rs = new ASN1Integer[]{ new ASN1Integer(r), new ASN1Integer(s) };
- return new DERSequence(rs).getEncoded(ASN1Encoding.DER);
- }
-
- private BigInteger[] derDecode(
- byte[] encoding)
- throws IOException
- {
- ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
- if (s.size() != 2)
- {
- throw new IOException("malformed signature");
- }
- if (!Arrays.areEqual(encoding, s.getEncoded(ASN1Encoding.DER)))
- {
- throw new IOException("malformed signature");
- }
-
- return new BigInteger[]{
- ((ASN1Integer)s.getObjectAt(0)).getValue(),
- ((ASN1Integer)s.getObjectAt(1)).getValue()
- };
+ throw new UnsupportedOperationException("engineGetParameter unsupported");
}
static public class stdDSA
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java
index d768ae6d..f7ebf959 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java
@@ -1,12 +1,12 @@
package org.bouncycastle.jcajce.provider.asymmetric.dsa;
+import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
-import java.security.spec.DSAParameterSpec;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
@@ -15,7 +15,8 @@ import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Fingerprint;
/**
* utility class for converting jce/jca DSA objects
@@ -26,11 +27,16 @@ public class DSAUtil
public static final ASN1ObjectIdentifier[] dsaOids =
{
X9ObjectIdentifiers.id_dsa,
- // Android-added: Add missing OID for DSA-with-SHA1
- X9ObjectIdentifiers.id_dsa_with_sha1,
- OIWObjectIdentifiers.dsaWithSHA1
+ OIWObjectIdentifiers.dsaWithSHA1,
+ X9ObjectIdentifiers.id_dsa_with_sha1
};
+ /**
+ * Return true if the passed in OID could be associated with a DSA key.
+ *
+ * @param algOid algorithm OID from a key.
+ * @return true if it's for a DSA key, false otherwise.
+ */
public static boolean isDsaOid(
ASN1ObjectIdentifier algOid)
{
@@ -97,4 +103,9 @@ public class DSAUtil
throw new InvalidKeyException("can't identify DSA private key.");
}
+
+ static String generateKeyFingerprint(BigInteger y, DSAParams params)
+ {
+ return new Fingerprint(Arrays.concatenate(y.toByteArray(), params.getP().toByteArray(), params.getQ().toByteArray(), params.getG().toByteArray())).toString();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java
index 7816320d..10b160f4 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java
@@ -15,7 +15,17 @@ import java.security.spec.KeySpec;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.params.DSAParameters;
+import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil;
+// import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.jce.spec.OpenSSHPrivateKeySpec;
+// import org.bouncycastle.jce.spec.OpenSSHPublicKeySpec;
public class KeyFactorySpi
extends BaseKeyFactorySpi
@@ -41,6 +51,34 @@ public class KeyFactorySpi
return new DSAPrivateKeySpec(k.getX(), k.getParams().getP(), k.getParams().getQ(), k.getParams().getG());
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (spec.isAssignableFrom(OpenSSHPublicKeySpec.class) && key instanceof java.security.interfaces.DSAPublicKey)
+ {
+ DSAPublicKey k = (DSAPublicKey)key;
+ try
+ {
+ return new OpenSSHPublicKeySpec(OpenSSHPublicKeyUtil.encodePublicKey(new DSAPublicKeyParameters(k.getY(), new DSAParameters(k.getParams().getP(), k.getParams().getQ(), k.getParams().getG()))));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to produce encoding: " + e.getMessage());
+ }
+ }
+ else if (spec.isAssignableFrom(OpenSSHPrivateKeySpec.class) && key instanceof java.security.interfaces.DSAPrivateKey)
+ {
+ DSAPrivateKey k = (DSAPrivateKey)key;
+ try
+ {
+ return new OpenSSHPrivateKeySpec(OpenSSHPrivateKeyUtil.encodePrivateKey(new DSAPrivateKeyParameters(k.getX(), new DSAParameters(k.getParams().getP(), k.getParams().getQ(), k.getParams().getG()))));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to produce encoding: " + e.getMessage());
+ }
+ }
+ */
+ // END Android-removed: Unsupported algorithms
return super.engineGetKeySpec(key, spec);
}
@@ -99,6 +137,28 @@ public class KeyFactorySpi
{
return new BCDSAPrivateKey((DSAPrivateKeySpec)keySpec);
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (keySpec instanceof OpenSSHPrivateKeySpec)
+ {
+ CipherParameters params = OpenSSHPrivateKeyUtil.parsePrivateKeyBlob(((OpenSSHPrivateKeySpec)keySpec).getEncoded());
+ if (params instanceof DSAPrivateKeyParameters)
+ {
+ return engineGeneratePrivate(
+ new DSAPrivateKeySpec(
+ ((DSAPrivateKeyParameters)params).getX(),
+ ((DSAPrivateKeyParameters)params).getParameters().getP(),
+ ((DSAPrivateKeyParameters)params).getParameters().getQ(),
+ ((DSAPrivateKeyParameters)params).getParameters().getG()));
+ }
+ else
+ {
+ throw new IllegalArgumentException("openssh private key is not dsa privare key");
+ }
+
+ }
+ */
+ // END Android-removed: Unsupported algorithms
return super.engineGeneratePrivate(keySpec);
}
@@ -118,12 +178,32 @@ public class KeyFactorySpi
throw new InvalidKeySpecException("invalid KeySpec: " + e.getMessage())
{
public Throwable getCause()
- {
- return e;
- }
+ {
+ return e;
+ }
};
}
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (keySpec instanceof OpenSSHPublicKeySpec)
+ {
+ CipherParameters parameters = OpenSSHPublicKeyUtil.parsePublicKey(((OpenSSHPublicKeySpec)keySpec).getEncoded());
+
+ if (parameters instanceof DSAPublicKeyParameters)
+ {
+ return engineGeneratePublic(
+ new DSAPublicKeySpec(((DSAPublicKeyParameters)parameters).getY(),
+ ((DSAPublicKeyParameters)parameters).getParameters().getP(),
+ ((DSAPublicKeyParameters)parameters).getParameters().getQ(),
+ ((DSAPublicKeyParameters)parameters).getParameters().getG()));
+ }
+
+ throw new IllegalArgumentException("openssh public key is not dsa public key");
+
+ }
+ */
+ // END Android-removed: Unsupported algorithms
return super.engineGeneratePublic(keySpec);
}
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 366e6dca..a7ed3e06 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
@@ -9,6 +9,7 @@ import java.security.spec.DSAParameterSpec;
import java.util.Hashtable;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.generators.DSAKeyPairGenerator;
import org.bouncycastle.crypto.generators.DSAParametersGenerator;
@@ -18,6 +19,7 @@ import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Integers;
import org.bouncycastle.util.Properties;
@@ -35,7 +37,7 @@ public class KeyPairGeneratorSpi
// a sufficiently long digest to work with 2048-bit keys.
int strength = 1024;
- SecureRandom random = new SecureRandom();
+ SecureRandom random = CryptoServicesRegistrar.getSecureRandom();
boolean initialised = false;
public KeyPairGeneratorSpi()
@@ -52,9 +54,26 @@ public class KeyPairGeneratorSpi
throw new InvalidParameterException("strength must be from 512 - 4096 and a multiple of 1024 above 1024");
}
- this.strength = strength;
- this.random = random;
- this.initialised = false;
+ // Android-added: Treat null SecureRandom as default
+ if (random == null) {
+ random = new SecureRandom();
+ }
+
+ DSAParameterSpec spec = BouncyCastleProvider.CONFIGURATION.getDSADefaultParameters(strength);
+
+ if (spec != null)
+ {
+ param = new DSAKeyGenerationParameters(random, new DSAParameters(spec.getP(), spec.getQ(), spec.getG()));
+
+ engine.init(param);
+ this.initialised = true;
+ }
+ else
+ {
+ this.strength = strength;
+ this.random = random;
+ this.initialised = false;
+ }
}
public void initialize(
@@ -68,6 +87,11 @@ public class KeyPairGeneratorSpi
}
DSAParameterSpec dsaParams = (DSAParameterSpec)params;
+ // Android-added: Treat null SecureRandom as default
+ if (random == null) {
+ random = new SecureRandom();
+ }
+
param = new DSAKeyGenerationParameters(random, new DSAParameters(dsaParams.getP(), dsaParams.getQ(), dsaParams.getG()));
engine.init(param);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java
index 9f56a55a..7851b256 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java
@@ -1,6 +1,7 @@
package org.bouncycastle.jcajce.provider.asymmetric.ec;
import java.io.IOException;
+import java.math.BigInteger;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
@@ -42,7 +43,9 @@ public class AlgorithmParametersSpi
throw new InvalidParameterSpecException("EC curve name not recognized: " + ecGenParameterSpec.getName());
}
curveName = ecGenParameterSpec.getName();
- ecParameterSpec = EC5Util.convertToSpec(params);
+ ECParameterSpec baseSpec = EC5Util.convertToSpec(params);
+ ecParameterSpec = new ECNamedCurveSpec(curveName,
+ baseSpec.getCurve(), baseSpec.getGenerator(), baseSpec.getOrder(), BigInteger.valueOf(baseSpec.getCofactor()));
}
else if (algorithmParameterSpec instanceof ECParameterSpec)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java
index 815bcac0..714f9100 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java
@@ -32,7 +32,6 @@ import org.bouncycastle.jce.interfaces.ECPointEncoder;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.util.Strings;
public class BCECPrivateKey
implements ECPrivateKey, org.bouncycastle.jce.interfaces.ECPrivateKey, PKCS12BagAttributeCarrier, ECPointEncoder
@@ -120,30 +119,27 @@ public class BCECPrivateKey
ECParameterSpec spec,
ProviderConfiguration configuration)
{
- ECDomainParameters dp = params.getParameters();
-
this.algorithm = algorithm;
this.d = params.getD();
this.configuration = configuration;
if (spec == null)
{
+ ECDomainParameters dp = params.getParameters();
EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getAffineXCoord().toBigInteger(),
- dp.getG().getAffineYCoord().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ EC5Util.convertPoint(dp.getG()),
+ dp.getN(),
+ dp.getH().intValue());
}
else
{
this.ecSpec = spec;
}
- publicKey = getPublicKeyDetails(pubKey);
+ this.publicKey = getPublicKeyDetails(pubKey);
}
public BCECPrivateKey(
@@ -153,23 +149,20 @@ public class BCECPrivateKey
org.bouncycastle.jce.spec.ECParameterSpec spec,
ProviderConfiguration configuration)
{
- ECDomainParameters dp = params.getParameters();
-
this.algorithm = algorithm;
this.d = params.getD();
this.configuration = configuration;
if (spec == null)
{
+ ECDomainParameters dp = params.getParameters();
EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getAffineXCoord().toBigInteger(),
- dp.getG().getAffineYCoord().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ EC5Util.convertPoint(dp.getG()),
+ dp.getN(),
+ dp.getH().intValue());
}
else
{
@@ -180,11 +173,11 @@ public class BCECPrivateKey
try
{
- publicKey = getPublicKeyDetails(pubKey);
+ this.publicKey = getPublicKeyDetails(pubKey);
}
catch (Exception e)
{
- publicKey = null; // not all curves are encodable
+ this.publicKey = null; // not all curves are encodable
}
}
@@ -370,14 +363,12 @@ public class BCECPrivateKey
public String toString()
{
- StringBuffer buf = new StringBuffer();
- String nl = Strings.lineSeparator();
-
- buf.append("EC Private Key").append(nl);
- buf.append(" S: ").append(this.d.toString(16)).append(nl);
-
- return buf.toString();
+ return ECUtil.privateKeyToString("EC", d, engineGetSpec());
+ }
+ private org.bouncycastle.math.ec.ECPoint calculateQ(org.bouncycastle.jce.spec.ECParameterSpec spec)
+ {
+ return spec.getG().multiply(d).normalize();
}
private DERBitString getPublicKeyDetails(BCECPublicKey pub)
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 443c5f63..9236787c 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
@@ -29,7 +29,6 @@ import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jce.interfaces.ECPointEncoder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.util.Strings;
public class BCECPublicKey
implements ECPublicKey, org.bouncycastle.jce.interfaces.ECPublicKey, ECPointEncoder
@@ -181,12 +180,10 @@ public class BCECPublicKey
private ECParameterSpec createSpec(EllipticCurve ellipticCurve, ECDomainParameters dp)
{
return new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getAffineXCoord().toBigInteger(),
- dp.getG().getAffineYCoord().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ EC5Util.convertPoint(dp.getG()),
+ dp.getN(),
+ dp.getH().intValue());
}
private void populateFromPubKeyInfo(SubjectPublicKeyInfo info)
@@ -263,9 +260,7 @@ public class BCECPublicKey
public ECPoint getW()
{
- org.bouncycastle.math.ec.ECPoint q = ecPublicKey.getQ();
-
- return new ECPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
+ return EC5Util.convertPoint(ecPublicKey.getQ());
}
public org.bouncycastle.math.ec.ECPoint getQ()
@@ -297,16 +292,7 @@ public class BCECPublicKey
public String toString()
{
- StringBuffer buf = new StringBuffer();
- String nl = Strings.lineSeparator();
- org.bouncycastle.math.ec.ECPoint q = ecPublicKey.getQ();
-
- buf.append("EC Public Key").append(nl);
- buf.append(" X: ").append(q.getAffineXCoord().toBigInteger().toString(16)).append(nl);
- buf.append(" Y: ").append(q.getAffineYCoord().toBigInteger().toString(16)).append(nl);
-
- return buf.toString();
-
+ return ECUtil.publicKeyToString("EC", ecPublicKey.getQ(), engineGetSpec());
}
public void setPointFormat(String style)
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 dd286312..7070df87 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
@@ -16,9 +16,13 @@ import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
// BEGIN Android-removed: Unsupported algorithms
// import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
+// import org.bouncycastle.crypto.agreement.ECDHCUnifiedAgreement;
// import org.bouncycastle.crypto.agreement.ECMQVBasicAgreement;
// import org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator;
+// import org.bouncycastle.crypto.digests.RIPEMD160Digest;
// import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
+// import org.bouncycastle.crypto.params.ECDHUPrivateParameters;
+// import org.bouncycastle.crypto.params.ECDHUPublicParameters;
// END Android-removed: Unsupported algorithms
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
@@ -31,6 +35,7 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
// BEGIN Android-removed: Unsupported algorithms
+// import org.bouncycastle.jcajce.spec.DHUParameterSpec;
// import org.bouncycastle.jcajce.spec.MQVParameterSpec;
// END Android-removed: Unsupported algorithms
import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec;
@@ -40,11 +45,12 @@ import org.bouncycastle.jce.interfaces.ECPublicKey;
// import org.bouncycastle.jce.interfaces.MQVPrivateKey;
// import org.bouncycastle.jce.interfaces.MQVPublicKey;
// END Android-removed: Unsupported algorithms
+import org.bouncycastle.util.Arrays;
/**
* Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363
* both the simple one, and the simple one with cofactors are supported.
- *
+ * <p>
* Also, MQV key agreement per SEC-1
*/
public class KeyAgreementSpi
@@ -52,14 +58,15 @@ public class KeyAgreementSpi
{
private static final X9IntegerConverter converter = new X9IntegerConverter();
- private String kaAlgorithm;
+ private String kaAlgorithm;
- private ECDomainParameters parameters;
- private BasicAgreement agreement;
+ private ECDomainParameters parameters;
+ private Object agreement;
// Android-removed: Unsupported algorithms
// private MQVParameterSpec mqvParameters;
- private BigInteger result;
+ // private DHUParameterSpec dheParameters;
+ private byte[] result;
protected KeyAgreementSpi(
String kaAlgorithm,
@@ -72,15 +79,30 @@ public class KeyAgreementSpi
this.agreement = agreement;
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ protected KeyAgreementSpi(
+ String kaAlgorithm,
+ ECDHCUnifiedAgreement agreement,
+ DerivationFunction kdf)
+ {
+ super(kaAlgorithm, kdf);
+
+ this.kaAlgorithm = kaAlgorithm;
+ this.agreement = agreement;
+ }
+ */
+ // END Android-removed: Unsupported algorithms
+
protected byte[] bigIntToBytes(
- BigInteger r)
+ BigInteger r)
{
return converter.integerToBytes(r, converter.getByteLength(parameters.getCurve()));
}
protected Key engineDoPhase(
- Key key,
- boolean lastPhase)
+ Key key,
+ boolean lastPhase)
throws InvalidKeyException, IllegalStateException
{
if (parameters == null)
@@ -93,7 +115,7 @@ public class KeyAgreementSpi
throw new IllegalStateException(kaAlgorithm + " can only be between two parties.");
}
- CipherParameters pubKey;
+ CipherParameters pubKey;
// BEGIN Android-removed: Unsupported algorithms
/*
if (agreement instanceof ECMQVBasicAgreement)
@@ -118,6 +140,15 @@ public class KeyAgreementSpi
pubKey = new MQVPublicParameters(staticKey, ephemKey);
}
}
+ else if (agreement instanceof ECDHCUnifiedAgreement)
+ {
+ ECPublicKeyParameters staticKey = (ECPublicKeyParameters)
+ ECUtils.generatePublicKeyParameter((PublicKey)key);
+ ECPublicKeyParameters ephemKey = (ECPublicKeyParameters)
+ ECUtils.generatePublicKeyParameter(dheParameters.getOtherPartyEphemeralKey());
+
+ pubKey = new ECDHUPublicParameters(staticKey, ephemKey);
+ }
else
*/
// END Android-removed: Unsupported algorithms
@@ -133,16 +164,31 @@ public class KeyAgreementSpi
try
{
- result = agreement.calculateAgreement(pubKey);
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ if (agreement instanceof BasicAgreement)
+ {
+ */
+ // END Android-removed: Unsupported algorithms
+ result = bigIntToBytes(((BasicAgreement)agreement).calculateAgreement(pubKey));
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ }
+ else
+ {
+ result = ((ECDHCUnifiedAgreement)agreement).calculateAgreement(pubKey);
+ }
+ */
+ // END Android-removed: Unsupported algorithms
}
catch (final Exception e)
{
throw new InvalidKeyException("calculation failed: " + e.getMessage())
{
public Throwable getCause()
- {
- return e;
- }
+ {
+ return e;
+ }
};
}
@@ -150,13 +196,14 @@ public class KeyAgreementSpi
}
protected void engineInit(
- Key key,
- AlgorithmParameterSpec params,
- SecureRandom random)
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
// Android-removed: Unsupported algorithms
- // if (params != null && !(params instanceof MQVParameterSpec || params instanceof UserKeyingMaterialSpec))
+ // if (params != null &&
+ // !(params instanceof MQVParameterSpec || params instanceof UserKeyingMaterialSpec || params instanceof DHUParameterSpec))
if (params != null && !(params instanceof UserKeyingMaterialSpec))
{
throw new InvalidAlgorithmParameterException("No algorithm parameters supported");
@@ -166,15 +213,23 @@ public class KeyAgreementSpi
}
protected void engineInit(
- Key key,
- SecureRandom random)
+ Key key,
+ SecureRandom random)
throws InvalidKeyException
{
- initFromKey(key, null);
+ try
+ {
+ initFromKey(key, null);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ // this should never occur.
+ throw new InvalidKeyException(e.getMessage());
+ }
}
private void initFromKey(Key key, AlgorithmParameterSpec parameterSpec)
- throws InvalidKeyException
+ throws InvalidKeyException, InvalidAlgorithmParameterException
{
// BEGIN Android-removed: Unsupported algorithms
/*
@@ -183,7 +238,7 @@ public class KeyAgreementSpi
mqvParameters = null;
if (!(key instanceof MQVPrivateKey) && !(parameterSpec instanceof MQVParameterSpec))
{
- throw new InvalidKeyException(kaAlgorithm + " key agreement requires "
+ throw new InvalidAlgorithmParameterException(kaAlgorithm + " key agreement requires "
+ getSimpleName(MQVParameterSpec.class) + " for initialisation");
}
@@ -229,7 +284,38 @@ public class KeyAgreementSpi
// TODO Validate that all the keys are using the same parameters?
- agreement.init(localParams);
+ ((ECMQVBasicAgreement)agreement).init(localParams);
+ }
+ else if (parameterSpec instanceof DHUParameterSpec)
+ {
+ if (!(agreement instanceof ECDHCUnifiedAgreement))
+ {
+ throw new InvalidAlgorithmParameterException(kaAlgorithm + " key agreement cannot be used with "
+ + getSimpleName(DHUParameterSpec.class));
+ }
+ DHUParameterSpec dheParameterSpec = (DHUParameterSpec)parameterSpec;
+ ECPrivateKeyParameters staticPrivKey;
+ ECPrivateKeyParameters ephemPrivKey;
+ ECPublicKeyParameters ephemPubKey;
+
+ staticPrivKey = (ECPrivateKeyParameters)
+ ECUtil.generatePrivateKeyParameter((PrivateKey)key);
+ ephemPrivKey = (ECPrivateKeyParameters)
+ ECUtil.generatePrivateKeyParameter(dheParameterSpec.getEphemeralPrivateKey());
+
+ ephemPubKey = null;
+ if (dheParameterSpec.getEphemeralPublicKey() != null)
+ {
+ ephemPubKey = (ECPublicKeyParameters)
+ ECUtils.generatePublicKeyParameter(dheParameterSpec.getEphemeralPublicKey());
+ }
+ dheParameters = dheParameterSpec;
+ ukmParameters = dheParameterSpec.getUserKeyingMaterial();
+
+ ECDHUPrivateParameters localParams = new ECDHUPrivateParameters(staticPrivKey, ephemPrivKey, ephemPubKey);
+ this.parameters = staticPrivKey.getParameters();
+
+ ((ECDHCUnifiedAgreement)agreement).init(localParams);
}
else
*/
@@ -240,11 +326,14 @@ public class KeyAgreementSpi
throw new InvalidKeyException(kaAlgorithm + " key agreement requires "
+ getSimpleName(ECPrivateKey.class) + " for initialisation");
}
-
+ if (kdf == null && parameterSpec instanceof UserKeyingMaterialSpec)
+ {
+ throw new InvalidAlgorithmParameterException("no KDF specified for UserKeyingMaterialSpec");
+ }
ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)ECUtil.generatePrivateKeyParameter((PrivateKey)key);
this.parameters = privKey.getParameters();
ukmParameters = (parameterSpec instanceof UserKeyingMaterialSpec) ? ((UserKeyingMaterialSpec)parameterSpec).getUserKeyingMaterial() : null;
- agreement.init(privKey);
+ ((BasicAgreement)agreement).init(privKey);
}
}
@@ -254,11 +343,10 @@ public class KeyAgreementSpi
return fullName.substring(fullName.lastIndexOf('.') + 1);
}
-
-
+
protected byte[] calcSecret()
{
- return bigIntToBytes(result);
+ return Arrays.clone(result);
}
public static class DH
@@ -290,6 +378,15 @@ public class KeyAgreementSpi
}
}
+ public static class DHUC
+ extends KeyAgreementSpi
+ {
+ public DHUC()
+ {
+ super("ECCDHU", new ECDHCUnifiedAgreement(), null);
+ }
+ }
+
public static class DHwithSHA1KDF
extends KeyAgreementSpi
{
@@ -372,22 +469,22 @@ public class KeyAgreementSpi
}
public static class DHwithSHA512KDFAndSharedInfo
- extends KeyAgreementSpi
- {
- public DHwithSHA512KDFAndSharedInfo()
- {
- super("ECDHwithSHA512KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
- }
- }
-
- public static class CDHwithSHA512KDFAndSharedInfo
- extends KeyAgreementSpi
- {
- public CDHwithSHA512KDFAndSharedInfo()
- {
- super("ECCDHwithSHA512KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
- }
- }
+ extends KeyAgreementSpi
+ {
+ public DHwithSHA512KDFAndSharedInfo()
+ {
+ super("ECDHwithSHA512KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
+ }
+ }
+
+ public static class CDHwithSHA512KDFAndSharedInfo
+ extends KeyAgreementSpi
+ {
+ public CDHwithSHA512KDFAndSharedInfo()
+ {
+ super("ECCDHwithSHA512KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
+ }
+ }
public static class MQVwithSHA1KDFAndSharedInfo
extends KeyAgreementSpi
@@ -514,6 +611,219 @@ public class KeyAgreementSpi
super("ECMQVwithSHA512CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA512()));
}
}
- */
- // END Android-removed: Unsupported algorithms
+
+ public static class MQVwithSHA1KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA1KDF()
+ {
+ super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ public static class MQVwithSHA224KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA224KDF()
+ {
+ super("ECMQVwithSHA224KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ public static class MQVwithSHA256KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA256KDF()
+ {
+ super("ECMQVwithSHA256KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ public static class MQVwithSHA384KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA384KDF()
+ {
+ super("ECMQVwithSHA384KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ public static class MQVwithSHA512KDF
+ extends KeyAgreementSpi
+ {
+ public MQVwithSHA512KDF()
+ {
+ super("ECMQVwithSHA512KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
+ }
+ }
+
+ public static class DHUwithSHA1CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA1CKDF()
+ {
+ super("ECCDHUwithSHA1CKDF", new ECDHCUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ public static class DHUwithSHA224CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA224CKDF()
+ {
+ super("ECCDHUwithSHA224CKDF", new ECDHCUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ public static class DHUwithSHA256CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA256CKDF()
+ {
+ super("ECCDHUwithSHA256CKDF", new ECDHCUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ public static class DHUwithSHA384CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA384CKDF()
+ {
+ super("ECCDHUwithSHA384CKDF", new ECDHCUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ public static class DHUwithSHA512CKDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA512CKDF()
+ {
+ super("ECCDHUwithSHA512CKDF", new ECDHCUnifiedAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA512()));
+ }
+ }
+
+ public static class DHUwithSHA1KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA1KDF()
+ {
+ super("ECCDHUwithSHA1KDF", new ECDHCUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ public static class DHUwithSHA224KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA224KDF()
+ {
+ super("ECCDHUwithSHA224KDF", new ECDHCUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ public static class DHUwithSHA256KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA256KDF()
+ {
+ super("ECCDHUwithSHA256KDF", new ECDHCUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ public static class DHUwithSHA384KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA384KDF()
+ {
+ super("ECCDHUwithSHA384KDF", new ECDHCUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ public static class DHUwithSHA512KDF
+ extends KeyAgreementSpi
+ {
+ public DHUwithSHA512KDF()
+ {
+ super("ECCDHUwithSHA512KDF", new ECDHCUnifiedAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
+ }
+ }
+
+ /**
+ * KeyAgreement according to BSI TR-03111 chapter 4.3.1
+ *
+ public static class ECKAEGwithSHA1KDF
+ extends KeyAgreementSpi
+ {
+ public ECKAEGwithSHA1KDF()
+ {
+ super("ECKAEGwithSHA1KDF", new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(DigestFactory.createSHA1()));
+ }
+ }
+
+ /**
+ * KeyAgreement according to BSI TR-03111 chapter 4.3.1
+ *
+ public static class ECKAEGwithRIPEMD160KDF
+ extends KeyAgreementSpi
+ {
+ public ECKAEGwithRIPEMD160KDF()
+ {
+ super("ECKAEGwithRIPEMD160KDF", new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(new RIPEMD160Digest()));
+ }
+ }
+
+ /**
+ * KeyAgreement according to BSI TR-03111 chapter 4.3.1
+ *
+ public static class ECKAEGwithSHA224KDF
+ extends KeyAgreementSpi
+ {
+ public ECKAEGwithSHA224KDF()
+ {
+ super("ECKAEGwithSHA224KDF", new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(DigestFactory.createSHA224()));
+ }
+ }
+
+ /**
+ * KeyAgreement according to BSI TR-03111 chapter 4.3.1
+ *
+ public static class ECKAEGwithSHA256KDF
+ extends KeyAgreementSpi
+ {
+ public ECKAEGwithSHA256KDF()
+ {
+ super("ECKAEGwithSHA256KDF", new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(DigestFactory.createSHA256()));
+ }
+ }
+
+ /**
+ * KeyAgreement according to BSI TR-03111 chapter 4.3.1
+ *
+ public static class ECKAEGwithSHA384KDF
+ extends KeyAgreementSpi
+ {
+ public ECKAEGwithSHA384KDF()
+ {
+ super("ECKAEGwithSHA384KDF", new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(DigestFactory.createSHA384()));
+ }
+ }
+
+ /**
+ * KeyAgreement according to BSI TR-03111 chapter 4.3.1
+ *
+ public static class ECKAEGwithSHA512KDF
+ extends KeyAgreementSpi
+ {
+ public ECKAEGwithSHA512KDF()
+ {
+ super("ECKAEGwithSHA512KDF", new ECDHBasicAgreement(),
+ new KDF2BytesGenerator(DigestFactory.createSHA512()));
+ }
+ }
+ */
+ // END Android-removed: Unsupported algorithms
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java
index 431b6bd3..19b538a8 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java
@@ -12,8 +12,14 @@ import java.security.spec.KeySpec;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
@@ -22,6 +28,9 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.jce.spec.OpenSSHPrivateKeySpec;
+// import org.bouncycastle.jce.spec.OpenSSHPublicKeySpec;
public class KeyFactorySpi
extends BaseKeyFactorySpi
@@ -39,7 +48,7 @@ public class KeyFactorySpi
}
protected Key engineTranslateKey(
- Key key)
+ Key key)
throws InvalidKeyException
{
if (key instanceof ECPublicKey)
@@ -55,70 +64,115 @@ public class KeyFactorySpi
}
protected KeySpec engineGetKeySpec(
- Key key,
- Class spec)
- throws InvalidKeySpecException
+ Key key,
+ Class spec)
+ throws InvalidKeySpecException
{
- if (spec.isAssignableFrom(java.security.spec.ECPublicKeySpec.class) && key instanceof ECPublicKey)
- {
- ECPublicKey k = (ECPublicKey)key;
- if (k.getParams() != null)
- {
- return new java.security.spec.ECPublicKeySpec(k.getW(), k.getParams());
- }
- else
- {
- ECParameterSpec implicitSpec = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
-
- return new java.security.spec.ECPublicKeySpec(k.getW(), EC5Util.convertSpec(EC5Util.convertCurve(implicitSpec.getCurve(), implicitSpec.getSeed()), implicitSpec));
- }
- }
- else if (spec.isAssignableFrom(java.security.spec.ECPrivateKeySpec.class) && key instanceof ECPrivateKey)
- {
- ECPrivateKey k = (ECPrivateKey)key;
-
- if (k.getParams() != null)
- {
- return new java.security.spec.ECPrivateKeySpec(k.getS(), k.getParams());
- }
- else
- {
- ECParameterSpec implicitSpec = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
-
- return new java.security.spec.ECPrivateKeySpec(k.getS(), EC5Util.convertSpec(EC5Util.convertCurve(implicitSpec.getCurve(), implicitSpec.getSeed()), implicitSpec));
- }
- }
- else if (spec.isAssignableFrom(org.bouncycastle.jce.spec.ECPublicKeySpec.class) && key instanceof ECPublicKey)
- {
- ECPublicKey k = (ECPublicKey)key;
- if (k.getParams() != null)
- {
- return new org.bouncycastle.jce.spec.ECPublicKeySpec(EC5Util.convertPoint(k.getParams(), k.getW(), false), EC5Util.convertSpec(k.getParams(), false));
- }
- else
- {
- ECParameterSpec implicitSpec = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
-
- return new org.bouncycastle.jce.spec.ECPublicKeySpec(EC5Util.convertPoint(k.getParams(), k.getW(), false), implicitSpec);
- }
- }
- else if (spec.isAssignableFrom(org.bouncycastle.jce.spec.ECPrivateKeySpec.class) && key instanceof ECPrivateKey)
- {
- ECPrivateKey k = (ECPrivateKey)key;
-
- if (k.getParams() != null)
- {
- return new org.bouncycastle.jce.spec.ECPrivateKeySpec(k.getS(), EC5Util.convertSpec(k.getParams(), false));
- }
- else
- {
- ECParameterSpec implicitSpec = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
-
- return new org.bouncycastle.jce.spec.ECPrivateKeySpec(k.getS(), implicitSpec);
- }
- }
-
- return super.engineGetKeySpec(key, spec);
+ if (spec.isAssignableFrom(java.security.spec.ECPublicKeySpec.class) && key instanceof ECPublicKey)
+ {
+ ECPublicKey k = (ECPublicKey)key;
+ if (k.getParams() != null)
+ {
+ return new java.security.spec.ECPublicKeySpec(k.getW(), k.getParams());
+ }
+ else
+ {
+ ECParameterSpec implicitSpec = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
+
+ return new java.security.spec.ECPublicKeySpec(k.getW(), EC5Util.convertSpec(EC5Util.convertCurve(implicitSpec.getCurve(), implicitSpec.getSeed()), implicitSpec));
+ }
+ }
+ else if (spec.isAssignableFrom(java.security.spec.ECPrivateKeySpec.class) && key instanceof ECPrivateKey)
+ {
+ ECPrivateKey k = (ECPrivateKey)key;
+
+ if (k.getParams() != null)
+ {
+ return new java.security.spec.ECPrivateKeySpec(k.getS(), k.getParams());
+ }
+ else
+ {
+ ECParameterSpec implicitSpec = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
+
+ return new java.security.spec.ECPrivateKeySpec(k.getS(), EC5Util.convertSpec(EC5Util.convertCurve(implicitSpec.getCurve(), implicitSpec.getSeed()), implicitSpec));
+ }
+ }
+ else if (spec.isAssignableFrom(org.bouncycastle.jce.spec.ECPublicKeySpec.class) && key instanceof ECPublicKey)
+ {
+ ECPublicKey k = (ECPublicKey)key;
+ if (k.getParams() != null)
+ {
+ return new org.bouncycastle.jce.spec.ECPublicKeySpec(EC5Util.convertPoint(k.getParams(), k.getW(), false), EC5Util.convertSpec(k.getParams(), false));
+ }
+ else
+ {
+ ECParameterSpec implicitSpec = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
+
+ return new org.bouncycastle.jce.spec.ECPublicKeySpec(EC5Util.convertPoint(k.getParams(), k.getW(), false), implicitSpec);
+ }
+ }
+ else if (spec.isAssignableFrom(org.bouncycastle.jce.spec.ECPrivateKeySpec.class) && key instanceof ECPrivateKey)
+ {
+ ECPrivateKey k = (ECPrivateKey)key;
+
+ if (k.getParams() != null)
+ {
+ return new org.bouncycastle.jce.spec.ECPrivateKeySpec(k.getS(), EC5Util.convertSpec(k.getParams(), false));
+ }
+ else
+ {
+ ECParameterSpec implicitSpec = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
+
+ return new org.bouncycastle.jce.spec.ECPrivateKeySpec(k.getS(), implicitSpec);
+ }
+ }
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (spec.isAssignableFrom(OpenSSHPublicKeySpec.class) && key instanceof ECPublicKey)
+ {
+ if (key instanceof BCECPublicKey)
+ {
+ BCECPublicKey bcPk = (BCECPublicKey)key;
+ ECParameterSpec sc = bcPk.getParameters();
+ try
+ {
+ return new OpenSSHPublicKeySpec(
+ OpenSSHPublicKeyUtil.encodePublicKey(
+ new ECPublicKeyParameters(bcPk.getQ(), new ECDomainParameters(sc.getCurve(), sc.getG(), sc.getN(), sc.getH(), sc.getSeed()))));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to produce encoding: " + e.getMessage());
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid key type: " + key.getClass().getName());
+ }
+ }
+ else if (spec.isAssignableFrom(OpenSSHPrivateKeySpec.class) && key instanceof ECPrivateKey)
+ {
+ if (key instanceof BCECPrivateKey)
+ {
+ try
+ {
+ return new OpenSSHPrivateKeySpec(PrivateKeyInfo.getInstance(key.getEncoded()).parsePrivateKey().toASN1Primitive().getEncoded());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("cannot encoded key: " + e.getMessage());
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid key type: " + key.getClass().getName());
+ }
+
+ }
+ */
+ // END Android-removed: Unsupported algorithms
+
+ return super.engineGetKeySpec(key, spec);
}
protected PrivateKey engineGeneratePrivate(
@@ -133,6 +187,23 @@ public class KeyFactorySpi
{
return new BCECPrivateKey(algorithm, (java.security.spec.ECPrivateKeySpec)keySpec, configuration);
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (keySpec instanceof OpenSSHPrivateKeySpec)
+ {
+ org.bouncycastle.asn1.sec.ECPrivateKey ecKey = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(((OpenSSHPrivateKeySpec)keySpec).getEncoded());
+
+ try
+ {
+ return new BCECPrivateKey(algorithm, new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, ecKey.getParameters()), ecKey), configuration);
+ }
+ catch (IOException e)
+ {
+ throw new InvalidKeySpecException("bad encoding: " + e.getMessage());
+ }
+ }
+ */
+ // END Android-removed: Unsupported algorithms
return super.engineGeneratePrivate(keySpec);
}
@@ -151,6 +222,26 @@ public class KeyFactorySpi
{
return new BCECPublicKey(algorithm, (java.security.spec.ECPublicKeySpec)keySpec, configuration);
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (keySpec instanceof OpenSSHPublicKeySpec)
+ {
+ CipherParameters params = OpenSSHPublicKeyUtil.parsePublicKey(((OpenSSHPublicKeySpec)keySpec).getEncoded());
+ if (params instanceof ECPublicKeyParameters)
+ {
+ ECDomainParameters parameters = ((ECPublicKeyParameters)params).getParameters();
+ return engineGeneratePublic(
+ new ECPublicKeySpec(((ECPublicKeyParameters)params).getQ(),
+ new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH(), parameters.getSeed())
+ ));
+ }
+ else
+ {
+ throw new IllegalArgumentException("openssh key is not ec public key");
+ }
+ }
+ */
+ // END Android-removed: Unsupported algorithms
}
catch (Exception e)
{
@@ -218,6 +309,15 @@ public class KeyFactorySpi
super("ECGOST3410", BouncyCastleProvider.CONFIGURATION);
}
}
+
+ public static class ECGOST3410_2012
+ extends KeyFactorySpi
+ {
+ public ECGOST3410_2012()
+ {
+ super("ECGOST3410-2012", BouncyCastleProvider.CONFIGURATION);
+ }
+ }
*/
// END Android-removed: Unsupported algorithm
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 794ca971..17a2e1d6 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
@@ -14,6 +14,7 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
@@ -47,8 +48,7 @@ public abstract class KeyPairGeneratorSpi
// 239-bit keys (the Bouncy Castle default) are less widely-supported than 256-bit ones,
// so we've changed the default strength to 256 for increased compatibility
int strength = 256;
- int certainty = 50;
- SecureRandom random = new SecureRandom();
+ SecureRandom random = CryptoServicesRegistrar.getSecureRandom();
boolean initialised = false;
String algorithm;
ProviderConfiguration configuration;
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 93f9d162..271f774c 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
@@ -1,44 +1,37 @@
package org.bouncycastle.jcajce.provider.asymmetric.ec;
-import java.io.IOException;
-import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.PublicKey;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
+import org.bouncycastle.crypto.DSAExt;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.NullDigest;
// BEGIN Android-removed: Unsupported algorithms
// import org.bouncycastle.crypto.digests.RIPEMD160Digest;
// END Android-removed: Unsupported algorithms
import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.crypto.signers.DSAEncoding;
import org.bouncycastle.crypto.signers.ECDSASigner;
// BEGIN Android-removed: Unsupported algorithms
// import org.bouncycastle.crypto.signers.ECNRSigner;
// import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
// END Android-removed: Unsupported algorithms
+import org.bouncycastle.crypto.signers.PlainDSAEncoding;
+import org.bouncycastle.crypto.signers.StandardDSAEncoding;
// BEGIN Android-changed: Use Android digests
// import org.bouncycastle.crypto.util.DigestFactory;
import org.bouncycastle.crypto.digests.AndroidDigestFactory;
import org.bouncycastle.jcajce.provider.asymmetric.util.DSABase;
-import org.bouncycastle.jcajce.provider.asymmetric.util.DSAEncoder;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
-import org.bouncycastle.util.Arrays;
public class SignatureSpi
extends DSABase
{
- SignatureSpi(Digest digest, DSA signer, DSAEncoder encoder)
+ SignatureSpi(Digest digest, DSAExt signer, DSAEncoding encoding)
{
- super(digest, signer, encoder);
+ super(digest, signer, encoding);
}
protected void engineInitVerify(PublicKey publicKey)
@@ -74,8 +67,8 @@ public class SignatureSpi
public ecDSA()
{
// Android-changed: Use Android digests
- // super(DigestFactory.createSHA1(), new ECDSASigner(), new StdDSAEncoder());
- super(AndroidDigestFactory.getSHA1(), new ECDSASigner(), new StdDSAEncoder());
+ // super(DigestFactory.createSHA1(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
+ super(AndroidDigestFactory.getSHA1(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -86,7 +79,7 @@ public class SignatureSpi
{
public ecDetDSA()
{
- super(DigestFactory.createSHA1(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA1())), new StdDSAEncoder());
+ super(DigestFactory.createSHA1(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA1())), StandardDSAEncoding.INSTANCE);
}
}
*/
@@ -97,7 +90,7 @@ public class SignatureSpi
{
public ecDSAnone()
{
- super(new NullDigest(), new ECDSASigner(), new StdDSAEncoder());
+ super(new NullDigest(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -107,8 +100,8 @@ public class SignatureSpi
public ecDSA224()
{
// Android-changed: Use Android digests
- // super(DigestFactory.createSHA224(), new ECDSASigner(), new StdDSAEncoder());
- super(AndroidDigestFactory.getSHA224(), new ECDSASigner(), new StdDSAEncoder());
+ // super(DigestFactory.createSHA224(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
+ super(AndroidDigestFactory.getSHA224(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -119,7 +112,7 @@ public class SignatureSpi
{
public ecDetDSA224()
{
- super(DigestFactory.createSHA224(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA224())), new StdDSAEncoder());
+ super(DigestFactory.createSHA224(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA224())), StandardDSAEncoding.INSTANCE);
}
}
*/
@@ -131,8 +124,8 @@ public class SignatureSpi
public ecDSA256()
{
// Android-changed: Use Android digests
- // super(DigestFactory.createSHA256(), new ECDSASigner(), new StdDSAEncoder());
- super(AndroidDigestFactory.getSHA256(), new ECDSASigner(), new StdDSAEncoder());
+ // super(DigestFactory.createSHA256(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
+ super(AndroidDigestFactory.getSHA256(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -143,7 +136,7 @@ public class SignatureSpi
{
public ecDetDSA256()
{
- super(DigestFactory.createSHA256(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA256())), new StdDSAEncoder());
+ super(DigestFactory.createSHA256(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA256())), StandardDSAEncoding.INSTANCE);
}
}
*/
@@ -155,8 +148,8 @@ public class SignatureSpi
public ecDSA384()
{
// Android-changed: Use Android digests
- // super(DigestFactory.createSHA384(), new ECDSASigner(), new StdDSAEncoder());
- super(AndroidDigestFactory.getSHA384(), new ECDSASigner(), new StdDSAEncoder());
+ // super(DigestFactory.createSHA384(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
+ super(AndroidDigestFactory.getSHA384(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -167,7 +160,7 @@ public class SignatureSpi
{
public ecDetDSA384()
{
- super(DigestFactory.createSHA384(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA384())), new StdDSAEncoder());
+ super(DigestFactory.createSHA384(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA384())), StandardDSAEncoding.INSTANCE);
}
}
*/
@@ -179,8 +172,8 @@ public class SignatureSpi
public ecDSA512()
{
// Android-changed: Use Android digests
- // super(DigestFactory.createSHA512(), new ECDSASigner(), new StdDSAEncoder());
- super(AndroidDigestFactory.getSHA512(), new ECDSASigner(), new StdDSAEncoder());
+ // super(DigestFactory.createSHA512(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
+ super(AndroidDigestFactory.getSHA512(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -191,7 +184,7 @@ public class SignatureSpi
{
public ecDetDSA512()
{
- super(DigestFactory.createSHA512(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA512())), new StdDSAEncoder());
+ super(DigestFactory.createSHA512(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA512())), StandardDSAEncoding.INSTANCE);
}
}
@@ -200,7 +193,7 @@ public class SignatureSpi
{
public ecDSASha3_224()
{
- super(DigestFactory.createSHA3_224(), new ECDSASigner(), new StdDSAEncoder());
+ super(DigestFactory.createSHA3_224(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -209,7 +202,7 @@ public class SignatureSpi
{
public ecDetDSASha3_224()
{
- super(DigestFactory.createSHA3_224(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_224())), new StdDSAEncoder());
+ super(DigestFactory.createSHA3_224(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_224())), StandardDSAEncoding.INSTANCE);
}
}
@@ -218,7 +211,7 @@ public class SignatureSpi
{
public ecDSASha3_256()
{
- super(DigestFactory.createSHA3_256(), new ECDSASigner(), new StdDSAEncoder());
+ super(DigestFactory.createSHA3_256(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -227,7 +220,7 @@ public class SignatureSpi
{
public ecDetDSASha3_256()
{
- super(DigestFactory.createSHA3_256(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_256())), new StdDSAEncoder());
+ super(DigestFactory.createSHA3_256(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_256())), StandardDSAEncoding.INSTANCE);
}
}
@@ -236,7 +229,7 @@ public class SignatureSpi
{
public ecDSASha3_384()
{
- super(DigestFactory.createSHA3_384(), new ECDSASigner(), new StdDSAEncoder());
+ super(DigestFactory.createSHA3_384(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -245,7 +238,7 @@ public class SignatureSpi
{
public ecDetDSASha3_384()
{
- super(DigestFactory.createSHA3_384(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_384())), new StdDSAEncoder());
+ super(DigestFactory.createSHA3_384(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_384())), StandardDSAEncoding.INSTANCE);
}
}
@@ -254,7 +247,7 @@ public class SignatureSpi
{
public ecDSASha3_512()
{
- super(DigestFactory.createSHA3_512(), new ECDSASigner(), new StdDSAEncoder());
+ super(DigestFactory.createSHA3_512(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -263,7 +256,7 @@ public class SignatureSpi
{
public ecDetDSASha3_512()
{
- super(DigestFactory.createSHA3_512(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_512())), new StdDSAEncoder());
+ super(DigestFactory.createSHA3_512(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_512())), StandardDSAEncoding.INSTANCE);
}
}
@@ -272,7 +265,7 @@ public class SignatureSpi
{
public ecDSARipeMD160()
{
- super(new RIPEMD160Digest(), new ECDSASigner(), new StdDSAEncoder());
+ super(new RIPEMD160Digest(), new ECDSASigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -281,7 +274,7 @@ public class SignatureSpi
{
public ecNR()
{
- super(DigestFactory.createSHA1(), new ECNRSigner(), new StdDSAEncoder());
+ super(DigestFactory.createSHA1(), new ECNRSigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -290,7 +283,7 @@ public class SignatureSpi
{
public ecNR224()
{
- super(DigestFactory.createSHA224(), new ECNRSigner(), new StdDSAEncoder());
+ super(DigestFactory.createSHA224(), new ECNRSigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -299,7 +292,7 @@ public class SignatureSpi
{
public ecNR256()
{
- super(DigestFactory.createSHA256(), new ECNRSigner(), new StdDSAEncoder());
+ super(DigestFactory.createSHA256(), new ECNRSigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -308,7 +301,7 @@ public class SignatureSpi
{
public ecNR384()
{
- super(DigestFactory.createSHA384(), new ECNRSigner(), new StdDSAEncoder());
+ super(DigestFactory.createSHA384(), new ECNRSigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -317,7 +310,7 @@ public class SignatureSpi
{
public ecNR512()
{
- super(DigestFactory.createSHA512(), new ECNRSigner(), new StdDSAEncoder());
+ super(DigestFactory.createSHA512(), new ECNRSigner(), StandardDSAEncoding.INSTANCE);
}
}
@@ -326,7 +319,7 @@ public class SignatureSpi
{
public ecCVCDSA()
{
- super(DigestFactory.createSHA1(), new ECDSASigner(), new PlainDSAEncoder());
+ super(DigestFactory.createSHA1(), new ECDSASigner(), PlainDSAEncoding.INSTANCE);
}
}
@@ -335,7 +328,7 @@ public class SignatureSpi
{
public ecCVCDSA224()
{
- super(DigestFactory.createSHA224(), new ECDSASigner(), new PlainDSAEncoder());
+ super(DigestFactory.createSHA224(), new ECDSASigner(), PlainDSAEncoding.INSTANCE);
}
}
@@ -344,7 +337,7 @@ public class SignatureSpi
{
public ecCVCDSA256()
{
- super(DigestFactory.createSHA256(), new ECDSASigner(), new PlainDSAEncoder());
+ super(DigestFactory.createSHA256(), new ECDSASigner(), PlainDSAEncoding.INSTANCE);
}
}
@@ -353,7 +346,7 @@ public class SignatureSpi
{
public ecCVCDSA384()
{
- super(DigestFactory.createSHA384(), new ECDSASigner(), new PlainDSAEncoder());
+ super(DigestFactory.createSHA384(), new ECDSASigner(), PlainDSAEncoding.INSTANCE);
}
}
@@ -362,7 +355,7 @@ public class SignatureSpi
{
public ecCVCDSA512()
{
- super(DigestFactory.createSHA512(), new ECDSASigner(), new PlainDSAEncoder());
+ super(DigestFactory.createSHA512(), new ECDSASigner(), PlainDSAEncoding.INSTANCE);
}
}
@@ -371,115 +364,9 @@ public class SignatureSpi
{
public ecPlainDSARP160()
{
- super(new RIPEMD160Digest(), new ECDSASigner(), new PlainDSAEncoder());
+ super(new RIPEMD160Digest(), new ECDSASigner(), PlainDSAEncoding.INSTANCE);
}
}
*/
// END Android-removed: Unsupported algorithms
-
- private static class StdDSAEncoder
- implements DSAEncoder
- {
- public byte[] encode(
- BigInteger r,
- BigInteger s)
- throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new ASN1Integer(r));
- v.add(new ASN1Integer(s));
-
- return new DERSequence(v).getEncoded(ASN1Encoding.DER);
- }
-
- public BigInteger[] decode(
- byte[] encoding)
- throws IOException
- {
- ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
- if (s.size() != 2)
- {
- throw new IOException("malformed signature");
- }
- if (!Arrays.areEqual(encoding, s.getEncoded(ASN1Encoding.DER)))
- {
- throw new IOException("malformed signature");
- }
-
- BigInteger[] sig = new BigInteger[2];
-
- sig[0] = ASN1Integer.getInstance(s.getObjectAt(0)).getValue();
- sig[1] = ASN1Integer.getInstance(s.getObjectAt(1)).getValue();
-
- return sig;
- }
- }
-
- // BEGIN Android-removed: Unsupported algorithms
- /*
- 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: Unsupported algorithms
-} \ No newline at end of file
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java
index e60c36ae..fc37d6ef 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java
@@ -95,7 +95,7 @@ public abstract class AlgorithmParametersSpi
{
return currentSpec;
}
-
+
throw new InvalidParameterSpecException("unknown parameter spec passed to OAEP parameters object.");
}
@@ -203,11 +203,11 @@ public abstract class AlgorithmParametersSpi
Class paramSpec)
throws InvalidParameterSpecException
{
- if (paramSpec == PSSParameterSpec.class && currentSpec != null)
+ if (paramSpec == PSSParameterSpec.class || paramSpec == AlgorithmParameterSpec.class)
{
return currentSpec;
}
-
+
throw new InvalidParameterSpecException("unknown parameter spec passed to PSS parameters object.");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateCrtKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateCrtKey.java
index d81d1976..0ac494fb 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateCrtKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateCrtKey.java
@@ -227,16 +227,15 @@ public class BCRSAPrivateCrtKey
StringBuffer buf = new StringBuffer();
String nl = Strings.lineSeparator();
- buf.append("RSA Private CRT Key").append(nl);
- buf.append(" modulus: ").append(this.getModulus().toString(16)).append(nl);
- buf.append(" public exponent: ").append(this.getPublicExponent().toString(16)).append(nl);
- buf.append(" private exponent: ").append(this.getPrivateExponent().toString(16)).append(nl);
- buf.append(" primeP: ").append(this.getPrimeP().toString(16)).append(nl);
- buf.append(" primeQ: ").append(this.getPrimeQ().toString(16)).append(nl);
- buf.append(" primeExponentP: ").append(this.getPrimeExponentP().toString(16)).append(nl);
- buf.append(" primeExponentQ: ").append(this.getPrimeExponentQ().toString(16)).append(nl);
- buf.append(" crtCoefficient: ").append(this.getCrtCoefficient().toString(16)).append(nl);
-
+ buf.append("RSA Private CRT Key [").append(
+ RSAUtil.generateKeyFingerprint(this.getModulus())).append("]")
+ .append(",[")
+ .append(RSAUtil.generateExponentFingerprint(this.getPublicExponent()))
+ .append("]")
+ .append(nl);
+ buf.append(" modulus: ").append(this.getModulus().toString(16)).append(nl);
+ buf.append(" public exponent: ").append(this.getPublicExponent().toString(16)).append(nl);
+
return buf.toString();
}
}
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 b82c5f80..f529d9b8 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
@@ -17,6 +17,7 @@ import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
+import org.bouncycastle.util.Strings;
public class BCRSAPrivateKey
implements RSAPrivateKey, PKCS12BagAttributeCarrier
@@ -142,4 +143,16 @@ public class BCRSAPrivateKey
{
out.defaultWriteObject();
}
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ String nl = Strings.lineSeparator();
+
+ buf.append("RSA Private Key [").append(
+ RSAUtil.generateKeyFingerprint(this.getModulus())).append("],[]").append(nl);
+ buf.append(" modulus: ").append(this.getModulus().toString(16)).append(nl);
+
+ return buf.toString();
+ }
}
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 669cf2ba..dd53dce6 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,10 +1,8 @@
package org.bouncycastle.jcajce.provider.asymmetric.rsa;
-import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.io.OptionalDataException;
import java.math.BigInteger;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
@@ -137,10 +135,14 @@ public class BCRSAPublicKey
StringBuffer buf = new StringBuffer();
String nl = Strings.lineSeparator();
- buf.append("RSA Public Key").append(nl);
- buf.append(" modulus: ").append(this.getModulus().toString(16)).append(nl);
- buf.append(" public exponent: ").append(this.getPublicExponent().toString(16)).append(nl);
-
+ buf.append("RSA Public Key [").append(RSAUtil.generateKeyFingerprint(this.getModulus())).append("]")
+ .append(",[")
+ .append(RSAUtil.generateExponentFingerprint(this.getPublicExponent()))
+ .append("]")
+ .append(nl);
+ buf.append(" modulus: ").append(this.getModulus().toString(16)).append(nl);
+ buf.append("public exponent: ").append(this.getPublicExponent().toString(16)).append(nl);
+
return buf.toString();
}
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 5154a201..274f6fac 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
@@ -1,6 +1,5 @@
package org.bouncycastle.jcajce.provider.asymmetric.rsa;
-import java.io.ByteArrayOutputStream;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -25,6 +24,7 @@ import javax.crypto.spec.PSource;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.InvalidCipherTextException;
// Android-removed: Unsupported algorithm
@@ -49,12 +49,12 @@ public class CipherSpi
// Was: private final JcaJceHelper helper = new BCJcaJceHelper();
private final JcaJceHelper helper = new DefaultJcaJceHelper();
- private AsymmetricBlockCipher cipher;
- private AlgorithmParameterSpec paramSpec;
- private AlgorithmParameters engineParams;
+ private AsymmetricBlockCipher cipher;
+ private AlgorithmParameterSpec paramSpec;
+ private AlgorithmParameters engineParams;
private boolean publicKeyOnly = false;
private boolean privateKeyOnly = false;
- private ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ private ErasableOutputStream bOut = new ErasableOutputStream();
public CipherSpi(
AsymmetricBlockCipher engine)
@@ -350,7 +350,7 @@ public class CipherSpi
}
else
{
- param = new ParametersWithRandom(param, new SecureRandom());
+ param = new ParametersWithRandom(param, CryptoServicesRegistrar.getSecureRandom());
}
}
@@ -502,12 +502,11 @@ public class CipherSpi
int outputOffset)
throws IllegalBlockSizeException, BadPaddingException, ShortBufferException
{
- // BEGIN Android-added: Throw ShortBufferException when given a short buffer.
- if (engineGetOutputSize(inputLen) > output.length - outputOffset)
+ if (outputOffset + engineGetOutputSize(inputLen) > output.length)
{
throw new ShortBufferException("output buffer too short for input.");
}
- // END Android-added: Throw ShortBufferException when given a short buffer.
+
if (input != null)
{
bOut.write(input, inputOffset, inputLen);
@@ -543,9 +542,7 @@ public class CipherSpi
{
try
{
- byte[] bytes = bOut.toByteArray();
-
- return cipher.processBlock(bytes, 0, bytes.length);
+ return cipher.processBlock(bOut.getBuf(), 0, bOut.size());
}
catch (InvalidCipherTextException e)
{
@@ -557,7 +554,7 @@ public class CipherSpi
}
finally
{
- bOut.reset();
+ bOut.erase();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
index 5c2f1df7..8688f7e3 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
@@ -175,15 +175,14 @@ public class DigestSignatureSpi
}
else if (sig.length == expected.length - 2) // NULL left out
{
- int sigOffset = sig.length - hash.length - 2;
- int expectedOffset = expected.length - hash.length - 2;
-
expected[1] -= 2; // adjust lengths
expected[3] -= 2;
+ int sigOffset = 4 + expected[3];
+ int expectedOffset = sigOffset + 2;
int nonEqual = 0;
- for (int i = 0; i < hash.length; i++)
+ for (int i = 0; i < expected.length - expectedOffset; i++)
{
nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
}
@@ -210,7 +209,7 @@ public class DigestSignatureSpi
}
/**
- * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
+ * @deprecated replaced with #engineSetParameter(java.security.spec.AlgorithmParameterSpec)
*/
protected void engineSetParameter(
String param,
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 80690f7c..89afe5ce 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
@@ -18,8 +18,17 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil;
+// import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi;
import org.bouncycastle.jcajce.provider.asymmetric.util.ExtendedInvalidKeySpecException;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.jce.spec.OpenSSHPrivateKeySpec;
+// import org.bouncycastle.jce.spec.OpenSSHPublicKeySpec;
public class KeyFactorySpi
extends BaseKeyFactorySpi
@@ -56,6 +65,48 @@ public class KeyFactorySpi
k.getPrimeExponentP(), k.getPrimeExponentQ(),
k.getCrtCoefficient());
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (spec.isAssignableFrom(OpenSSHPublicKeySpec.class) && key instanceof RSAPublicKey)
+ {
+ try
+ {
+ return new OpenSSHPublicKeySpec(
+ OpenSSHPublicKeyUtil.encodePublicKey(
+ new RSAKeyParameters(
+ false,
+ ((RSAPublicKey)key).getModulus(),
+ ((RSAPublicKey)key).getPublicExponent())
+ )
+ );
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to produce encoding: " + e.getMessage());
+ }
+ }
+ else if (spec.isAssignableFrom(OpenSSHPrivateKeySpec.class) && key instanceof RSAPrivateCrtKey)
+ {
+ try
+ {
+ return new OpenSSHPrivateKeySpec(OpenSSHPrivateKeyUtil.encodePrivateKey(new RSAPrivateCrtKeyParameters(
+ ((RSAPrivateCrtKey)key).getModulus(),
+ ((RSAPrivateCrtKey)key).getPublicExponent(),
+ ((RSAPrivateCrtKey)key).getPrivateExponent(),
+ ((RSAPrivateCrtKey)key).getPrimeP(),
+ ((RSAPrivateCrtKey)key).getPrimeQ(),
+ ((RSAPrivateCrtKey)key).getPrimeExponentP(),
+ ((RSAPrivateCrtKey)key).getPrimeExponentQ(),
+ ((RSAPrivateCrtKey)key).getCrtCoefficient()
+ )));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to produce encoding: " + e.getMessage());
+ }
+ }
+ */
+ // END Android-removed: Unsupported algorithms
return super.engineGetKeySpec(key, spec);
}
@@ -114,8 +165,23 @@ public class KeyFactorySpi
{
return new BCRSAPrivateKey((RSAPrivateKeySpec)keySpec);
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (keySpec instanceof OpenSSHPrivateKeySpec)
+ {
+ CipherParameters parameters = OpenSSHPrivateKeyUtil.parsePrivateKeyBlob(((OpenSSHPrivateKeySpec)keySpec).getEncoded());
+
+ if (parameters instanceof RSAPrivateCrtKeyParameters)
+ {
+ return new BCRSAPrivateCrtKey((RSAPrivateCrtKeyParameters)parameters);
+ }
- throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName());
+ throw new InvalidKeySpecException("open SSH public key is not RSA private key");
+ }
+ */
+ // END Android-removed: Unsupported algorithms
+
+ throw new InvalidKeySpecException("unknown KeySpec type: " + keySpec.getClass().getName());
}
protected PublicKey engineGeneratePublic(
@@ -126,6 +192,22 @@ public class KeyFactorySpi
{
return new BCRSAPublicKey((RSAPublicKeySpec)keySpec);
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ else if (keySpec instanceof OpenSSHPublicKeySpec)
+ {
+
+ CipherParameters parameters = OpenSSHPublicKeyUtil.parsePublicKey(((OpenSSHPublicKeySpec)keySpec).getEncoded());
+ if (parameters instanceof RSAKeyParameters)
+ {
+ return new BCRSAPublicKey((RSAKeyParameters)parameters);
+ }
+
+ throw new InvalidKeySpecException("Open SSH public key is not RSA public key");
+
+ }
+ */
+ // END Android-removed: Unsupported algorithms
return super.engineGeneratePublic(keySpec);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java
index a2c96662..3b9d7abc 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java
@@ -8,6 +8,7 @@ import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
@@ -34,7 +35,7 @@ public class KeyPairGeneratorSpi
engine = new RSAKeyPairGenerator();
param = new RSAKeyGenerationParameters(defaultPublicExponent,
- new SecureRandom(), 2048, PrimeCertaintyCalculator.getDefaultCertainty(2048));
+ CryptoServicesRegistrar.getSecureRandom(), 2048, PrimeCertaintyCalculator.getDefaultCertainty(2048));
engine.init(param);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/RSAUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/RSAUtil.java
index 4943a99b..4d046b8a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/RSAUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/RSAUtil.java
@@ -1,5 +1,6 @@
package org.bouncycastle.jcajce.provider.asymmetric.rsa;
+import java.math.BigInteger;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
@@ -9,6 +10,7 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.bouncycastle.util.Fingerprint;
/**
* utility class for converting java.security RSA objects into their
@@ -63,4 +65,14 @@ public class RSAUtil
return new RSAKeyParameters(true, k.getModulus(), k.getPrivateExponent());
}
}
+
+ static String generateKeyFingerprint(BigInteger modulus)
+ {
+ return new Fingerprint(modulus.toByteArray()).toString();
+ }
+
+ static String generateExponentFingerprint(BigInteger exponent)
+ {
+ return new Fingerprint(exponent.toByteArray(), 32).toString();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java
index f285ac55..b449dc59 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java
@@ -26,6 +26,7 @@ import org.bouncycastle.crypto.DerivationFunction;
// import org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator;
import org.bouncycastle.crypto.params.DESParameters;
import org.bouncycastle.crypto.params.KDFParameters;
+import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Integers;
import org.bouncycastle.util.Strings;
@@ -81,6 +82,11 @@ public abstract class BaseAgreementSpi
keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), i192);
keySizes.put(OIWObjectIdentifiers.desCBC.getId(), i64);
+ // Android-removed: Unsupported algorithms
+ // keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb.getId(), i256);
+ // keySizes.put(CryptoProObjectIdentifiers.id_Gost28147_89_None_KeyWrap.getId(), i256);
+ // keySizes.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_KeyWrap.getId(), i256);
+
keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA1.getId(), Integers.valueOf(160));
keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA256.getId(), i256);
keySizes.put(PKCSObjectIdentifiers.id_hmacWithSHA384.getId(), Integers.valueOf(384));
@@ -138,8 +144,8 @@ public abstract class BaseAgreementSpi
des.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DES");
}
- private final String kaAlgorithm;
- private final DerivationFunction kdf;
+ protected final String kaAlgorithm;
+ protected final DerivationFunction kdf;
protected byte[] ukmParameters;
@@ -220,8 +226,15 @@ public abstract class BaseAgreementSpi
{
if (kdf != null)
{
- throw new UnsupportedOperationException(
- "KDF can only be used when algorithm is known");
+ byte[] secret = calcSecret();
+ try
+ {
+ return getSharedSecretBytes(secret, null, secret.length * 8);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new IllegalStateException(e.getMessage());
+ }
}
return calcSecret();
@@ -248,7 +261,6 @@ public abstract class BaseAgreementSpi
String algorithm)
throws NoSuchAlgorithmException
{
- byte[] secret = calcSecret();
String algKey = Strings.toUpperCase(algorithm);
String oidAlgorithm = algorithm;
@@ -259,6 +271,21 @@ public abstract class BaseAgreementSpi
int keySize = getKeySize(oidAlgorithm);
+ byte[] secret = getSharedSecretBytes(calcSecret(), oidAlgorithm, keySize);
+
+ String algName = getAlgorithm(algorithm);
+
+ if (des.containsKey(algName))
+ {
+ DESParameters.setOddParity(secret);
+ }
+
+ return new SecretKeySpec(secret, algName);
+ }
+
+ private byte[] getSharedSecretBytes(byte[] secret, String oidAlgorithm, int keySize)
+ throws NoSuchAlgorithmException
+ {
if (kdf != null)
{
if (keySize < 0)
@@ -271,6 +298,10 @@ public abstract class BaseAgreementSpi
/*
if (kdf instanceof DHKEKGenerator)
{
+ if (oidAlgorithm == null)
+ {
+ throw new NoSuchAlgorithmException("algorithm OID is null");
+ }
ASN1ObjectIdentifier oid;
try
{
@@ -295,7 +326,9 @@ public abstract class BaseAgreementSpi
kdf.generateBytes(keyBytes, 0, keyBytes.length);
- secret = keyBytes;
+ Arrays.clear(secret);
+
+ return keyBytes;
}
else
{
@@ -305,18 +338,13 @@ public abstract class BaseAgreementSpi
System.arraycopy(secret, 0, keyBytes, 0, keyBytes.length);
- secret = keyBytes;
- }
- }
+ Arrays.clear(secret);
- String algName = getAlgorithm(algorithm);
+ return keyBytes;
+ }
- if (des.containsKey(algName))
- {
- DESParameters.setOddParity(secret);
+ return secret;
}
-
- return new SecretKeySpec(secret, algName);
}
protected abstract byte[] calcSecret();
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
index 961e2632..978eef85 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
@@ -1,5 +1,6 @@
package org.bouncycastle.jcajce.provider.asymmetric.util;
+import java.io.ByteArrayOutputStream;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -29,6 +30,7 @@ import org.bouncycastle.crypto.Wrapper;
import org.bouncycastle.jcajce.util.BCJcaJceHelper;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.Arrays;
public abstract class BaseCipherSpi
extends CipherSpi
@@ -230,4 +232,23 @@ public abstract class BaseCipherSpi
throw new InvalidKeyException("Unknown key type " + wrappedKeyType);
}
}
+
+ protected static final class ErasableOutputStream
+ extends ByteArrayOutputStream
+ {
+ public ErasableOutputStream()
+ {
+ }
+
+ public byte[] getBuf()
+ {
+ return buf;
+ }
+
+ public void erase()
+ {
+ Arrays.fill(this.buf, (byte)0);
+ reset();
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSABase.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSABase.java
index 463de890..28538fdd 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSABase.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSABase.java
@@ -7,25 +7,26 @@ import java.security.spec.AlgorithmParameterSpec;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-import org.bouncycastle.crypto.DSA;
+import org.bouncycastle.crypto.DSAExt;
import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.signers.DSAEncoding;
public abstract class DSABase
extends SignatureSpi
implements PKCSObjectIdentifiers, X509ObjectIdentifiers
{
- protected Digest digest;
- protected DSA signer;
- protected DSAEncoder encoder;
+ protected Digest digest;
+ protected DSAExt signer;
+ protected DSAEncoding encoding;
protected DSABase(
Digest digest,
- DSA signer,
- DSAEncoder encoder)
+ DSAExt signer,
+ DSAEncoding encoding)
{
this.digest = digest;
this.signer = signer;
- this.encoder = encoder;
+ this.encoding = encoding;
}
protected void engineUpdate(
@@ -47,15 +48,14 @@ public abstract class DSABase
protected byte[] engineSign()
throws SignatureException
{
- byte[] hash = new byte[digest.getDigestSize()];
-
+ byte[] hash = new byte[digest.getDigestSize()];
digest.doFinal(hash, 0);
try
{
- BigInteger[] sig = signer.generateSignature(hash);
+ BigInteger[] sig = signer.generateSignature(hash);
- return encoder.encode(sig[0], sig[1]);
+ return encoding.encode(signer.getOrder(), sig[0], sig[1]);
}
catch (Exception e)
{
@@ -67,15 +67,13 @@ public abstract class DSABase
byte[] sigBytes)
throws SignatureException
{
- byte[] hash = new byte[digest.getDigestSize()];
-
+ byte[] hash = new byte[digest.getDigestSize()];
digest.doFinal(hash, 0);
- BigInteger[] sig;
-
+ BigInteger[] sig;
try
{
- sig = encoder.decode(sigBytes);
+ sig = encoding.decode(signer.getOrder(), sigBytes);
}
catch (Exception e)
{
@@ -92,7 +90,7 @@ public abstract class DSABase
}
/**
- * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
+ * @deprecated replaced with "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)"
*/
protected void engineSetParameter(
String param,
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSAEncoder.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSAEncoder.java
index 4ea0ff93..a4d62415 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSAEncoder.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DSAEncoder.java
@@ -3,6 +3,9 @@ package org.bouncycastle.jcajce.provider.asymmetric.util;
import java.io.IOException;
import java.math.BigInteger;
+/**
+ * @deprecated No longer used
+ */
public interface DSAEncoder
{
byte[] encode(BigInteger r, BigInteger s)
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 d67974b8..91e15b7b 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
@@ -48,12 +48,18 @@ public class EC5Util
}
// BEGIN Android-removed: Unsupported curves
- // X9ECParameters c25519 = CustomNamedCurves.getByName("Curve25519");
-
- // customCurves.put(new ECCurve.Fp(
- // c25519.getCurve().getField().getCharacteristic(),
- // c25519.getCurve().getA().toBigInteger(),
- // c25519.getCurve().getB().toBigInteger()), c25519.getCurve());
+ /*
+ X9ECParameters x9_25519 = CustomNamedCurves.getByName("Curve25519");
+ ECCurve c_25519 = x9_25519.getCurve();
+
+ customCurves.put(new ECCurve.Fp(
+ c_25519.getField().getCharacteristic(),
+ c_25519.getA().toBigInteger(),
+ c_25519.getB().toBigInteger(),
+ c_25519.getOrder(),
+ c_25519.getCofactor()
+ ), c_25519);
+ */
// END Android-removed: Unsupported curves
}
@@ -146,9 +152,7 @@ public class EC5Util
ecSpec = new ECNamedCurveSpec(
ECUtil.getCurveName(oid),
ellipticCurve,
- new ECPoint(
- ecP.getG().getAffineXCoord().toBigInteger(),
- ecP.getG().getAffineYCoord().toBigInteger()),
+ convertPoint(ecP.getG()),
ecP.getN(),
ecP.getH());
}
@@ -166,9 +170,7 @@ public class EC5Util
{
ecSpec = new ECParameterSpec(
ellipticCurve,
- new ECPoint(
- ecP.getG().getAffineXCoord().toBigInteger(),
- ecP.getG().getAffineYCoord().toBigInteger()),
+ convertPoint(ecP.getG()),
ecP.getN(),
ecP.getH().intValue());
}
@@ -176,10 +178,9 @@ public class EC5Util
{
ecSpec = new ECParameterSpec(
ellipticCurve,
- new ECPoint(
- ecP.getG().getAffineXCoord().toBigInteger(),
- ecP.getG().getAffineYCoord().toBigInteger()),
- ecP.getN(), 1); // TODO: not strictly correct... need to fix the test data...
+ convertPoint(ecP.getG()),
+ ecP.getN(),
+ 1); // TODO: not strictly correct... need to fix the test data...
}
}
@@ -191,9 +192,17 @@ public class EC5Util
{
return new ECParameterSpec(
convertCurve(domainParameters.getCurve(), null), // JDK 1.5 has trouble with this if it's not null...
- new ECPoint(
- domainParameters.getG().getAffineXCoord().toBigInteger(),
- domainParameters.getG().getAffineYCoord().toBigInteger()),
+ EC5Util.convertPoint(domainParameters.getG()),
+ domainParameters.getN(),
+ domainParameters.getH().intValue());
+ }
+
+ public static ECParameterSpec convertToSpec(
+ ECDomainParameters domainParameters)
+ {
+ return new ECParameterSpec(
+ convertCurve(domainParameters.getCurve(), null), // JDK 1.5 has trouble with this if it's not null...
+ EC5Util.convertPoint(domainParameters.getG()),
domainParameters.getN(),
domainParameters.getH().intValue());
}
@@ -261,9 +270,7 @@ public class EC5Util
return new ECNamedCurveSpec(
((ECNamedCurveParameterSpec)spec).getName(),
ellipticCurve,
- new ECPoint(
- spec.getG().getAffineXCoord().toBigInteger(),
- spec.getG().getAffineYCoord().toBigInteger()),
+ convertPoint(spec.getG()),
spec.getN(),
spec.getH());
}
@@ -271,9 +278,7 @@ public class EC5Util
{
return new ECParameterSpec(
ellipticCurve,
- new ECPoint(
- spec.getG().getAffineXCoord().toBigInteger(),
- spec.getG().getAffineYCoord().toBigInteger()),
+ convertPoint(spec.getG()),
spec.getN(),
spec.getH().intValue());
}
@@ -285,12 +290,25 @@ public class EC5Util
{
ECCurve curve = convertCurve(ecSpec.getCurve());
- return new org.bouncycastle.jce.spec.ECParameterSpec(
- curve,
- convertPoint(curve, ecSpec.getGenerator(), withCompression),
- ecSpec.getOrder(),
- BigInteger.valueOf(ecSpec.getCofactor()),
- ecSpec.getCurve().getSeed());
+ if (ecSpec instanceof ECNamedCurveSpec)
+ {
+ return new org.bouncycastle.jce.spec.ECNamedCurveParameterSpec(
+ ((ECNamedCurveSpec)ecSpec).getName(),
+ curve,
+ convertPoint(curve, ecSpec.getGenerator(), withCompression),
+ ecSpec.getOrder(),
+ BigInteger.valueOf(ecSpec.getCofactor()),
+ ecSpec.getCurve().getSeed());
+ }
+ else
+ {
+ return new org.bouncycastle.jce.spec.ECParameterSpec(
+ curve,
+ convertPoint(curve, ecSpec.getGenerator(), withCompression),
+ ecSpec.getOrder(),
+ BigInteger.valueOf(ecSpec.getCofactor()),
+ ecSpec.getCurve().getSeed());
+ }
}
public static org.bouncycastle.math.ec.ECPoint convertPoint(
@@ -308,4 +326,13 @@ public class EC5Util
{
return curve.createPoint(point.getAffineX(), point.getAffineY());
}
+
+ public static ECPoint convertPoint(org.bouncycastle.math.ec.ECPoint point)
+ {
+ point = point.normalize();
+
+ return new ECPoint(
+ point.getAffineXCoord().toBigInteger(),
+ point.getAffineYCoord().toBigInteger());
+ }
}
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 39ff397c..f0511a6a 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
@@ -8,18 +8,9 @@ import java.util.Enumeration;
import java.util.Map;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-// Android-removed: Unsupported algorithms
-// import org.bouncycastle.asn1.anssi.ANSSINamedCurves;
-// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
-// import org.bouncycastle.asn1.gm.GMNamedCurves;
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-// Android-removed: Unsupported algorithms
-// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
@@ -34,6 +25,11 @@ import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Fingerprint;
+import org.bouncycastle.util.Strings;
/**
* utility class for converting jce/jca ECDSA, ECDH, and ECDHC
@@ -235,9 +231,20 @@ public class ECUtil
s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
}
- return new ECPrivateKeyParameters(
- k.getD(),
- new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
+ if (k.getParameters() instanceof ECNamedCurveParameterSpec)
+ {
+ String name = ((ECNamedCurveParameterSpec)k.getParameters()).getName();
+ return new ECPrivateKeyParameters(
+ k.getD(),
+ new ECNamedDomainParameters(ECNamedCurveTable.getOID(name),
+ s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
+ }
+ else
+ {
+ return new ECPrivateKeyParameters(
+ k.getD(),
+ new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
+ }
}
else if (key instanceof java.security.interfaces.ECPrivateKey)
{
@@ -297,15 +304,12 @@ public class ECUtil
public static ASN1ObjectIdentifier getNamedCurveOid(
String curveName)
{
- String name;
+ String name = curveName;
- if (curveName.indexOf(' ') > 0)
- {
- name = curveName.substring(curveName.indexOf(' ') + 1);
- }
- else
+ int spacePos = name.indexOf(' ');
+ if (spacePos > 0)
{
- name = curveName;
+ name = name.substring(spacePos + 1);
}
try
@@ -314,51 +318,12 @@ public class ECUtil
{
return new ASN1ObjectIdentifier(name);
}
- else
- {
- return lookupOidByName(name);
- }
}
catch (IllegalArgumentException ex)
{
- return lookupOidByName(name);
}
- }
- private static ASN1ObjectIdentifier lookupOidByName(String name)
- {
- ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name);
-
- if (oid == null)
- {
- oid = SECNamedCurves.getOID(name);
- if (oid == null)
- {
- oid = NISTNamedCurves.getOID(name);
- }
- // BEGIN Android-removed: Unsupported algorithms
- /*
- if (oid == null)
- {
- oid = TeleTrusTNamedCurves.getOID(name);
- }
- if (oid == null)
- {
- oid = ECGOST3410NamedCurves.getOID(name);
- }
- if (oid == null)
- {
- oid = ANSSINamedCurves.getOID(name);
- }
- if (oid == null)
- {
- oid = GMNamedCurves.getOID(name);
- }
- */
- // END Android-removed: Unsupported algorithms
- }
-
- return oid;
+ return ECNamedCurveTable.getOID(name);
}
public static ASN1ObjectIdentifier getNamedCurveOid(
@@ -389,27 +354,7 @@ public class ECUtil
if (params == null)
{
- params = X962NamedCurves.getByOID(oid);
- if (params == null)
- {
- params = SECNamedCurves.getByOID(oid);
- }
- if (params == null)
- {
- params = NISTNamedCurves.getByOID(oid);
- }
- // BEGIN Android-removed: Unsupported algorithms
- /*
- if (params == null)
- {
- params = TeleTrusTNamedCurves.getByOID(oid);
- }
- if (params == null)
- {
- params = GMNamedCurves.getByOID(oid);
- }
- */
- // END Android-removed: Unsupported algorithms
+ params = ECNamedCurveTable.getByOID(oid);
}
return params;
@@ -422,27 +367,7 @@ public class ECUtil
if (params == null)
{
- params = X962NamedCurves.getByName(curveName);
- if (params == null)
- {
- params = SECNamedCurves.getByName(curveName);
- }
- if (params == null)
- {
- params = NISTNamedCurves.getByName(curveName);
- }
- // BEGIN Android-removed: Unsupported algorithms
- /*
- if (params == null)
- {
- params = TeleTrusTNamedCurves.getByName(curveName);
- }
- if (params == null)
- {
- params = GMNamedCurves.getByName(curveName);
- }
- */
- // END Android-removed: Unsupported algorithms
+ params = ECNamedCurveTable.getByName(curveName);
}
return params;
@@ -451,29 +376,52 @@ public class ECUtil
public static String getCurveName(
ASN1ObjectIdentifier oid)
{
- String name = X962NamedCurves.getName(oid);
-
- if (name == null)
+ return ECNamedCurveTable.getName(oid);
+ }
+
+ public static String privateKeyToString(String algorithm, BigInteger d, org.bouncycastle.jce.spec.ECParameterSpec spec)
+ {
+ StringBuffer buf = new StringBuffer();
+ String nl = Strings.lineSeparator();
+
+ org.bouncycastle.math.ec.ECPoint q = calculateQ(d, spec);
+
+ buf.append(algorithm);
+ buf.append(" Private Key [").append(ECUtil.generateKeyFingerprint(q, spec)).append("]").append(nl);
+ buf.append(" X: ").append(q.getAffineXCoord().toBigInteger().toString(16)).append(nl);
+ buf.append(" Y: ").append(q.getAffineYCoord().toBigInteger().toString(16)).append(nl);
+
+ return buf.toString();
+ }
+
+ private static org.bouncycastle.math.ec.ECPoint calculateQ(BigInteger d, org.bouncycastle.jce.spec.ECParameterSpec spec)
+ {
+ return spec.getG().multiply(d).normalize();
+ }
+
+ public static String publicKeyToString(String algorithm, org.bouncycastle.math.ec.ECPoint q, org.bouncycastle.jce.spec.ECParameterSpec spec)
+ {
+ StringBuffer buf = new StringBuffer();
+ String nl = Strings.lineSeparator();
+
+ buf.append(algorithm);
+ buf.append(" Public Key [").append(ECUtil.generateKeyFingerprint(q, spec)).append("]").append(nl);
+ buf.append(" X: ").append(q.getAffineXCoord().toBigInteger().toString(16)).append(nl);
+ buf.append(" Y: ").append(q.getAffineYCoord().toBigInteger().toString(16)).append(nl);
+
+ return buf.toString();
+ }
+
+ public static String generateKeyFingerprint(ECPoint publicPoint, org.bouncycastle.jce.spec.ECParameterSpec spec)
+ {
+ ECCurve curve = spec.getCurve();
+ ECPoint g = spec.getG();
+
+ if (curve != null)
{
- name = SECNamedCurves.getName(oid);
- if (name == null)
- {
- name = NISTNamedCurves.getName(oid);
- }
- // BEGIN Android-removed: Unsupported algorithms
- /*
- if (name == null)
- {
- name = TeleTrusTNamedCurves.getName(oid);
- }
- if (name == null)
- {
- name = ECGOST3410NamedCurves.getName(oid);
- }
- */
- // END Android-removed: Unsupported algorithms
+ return new Fingerprint(Arrays.concatenate(publicPoint.getEncoded(false), curve.getA().getEncoded(), curve.getB().getEncoded(), g.getEncoded(false))).toString();
}
- return name;
+ return new Fingerprint(publicPoint.getEncoded(false)).toString();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java
index d5608b9e..4b84ddd6 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java
@@ -261,7 +261,7 @@ public class CertificateFactory
}
catch (Exception e)
{
- throw new ExCertificateException(e);
+ throw new ExCertificateException("parsing issue: " + e.getMessage(), e);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
index b72de4cb..98b3a05c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
@@ -42,8 +42,7 @@ import org.bouncycastle.util.io.pem.PemObject;
/**
* CertPath implementation for X.509 certificates.
- * <br />
- **/
+ */
public class PKIXCertPath
extends CertPath
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java
index dc8930b3..4870cdb0 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java
@@ -31,6 +31,7 @@ import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.util.ASN1Dump;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.CRLDistPoint;
@@ -269,6 +270,19 @@ class X509CRLObject
throw new CRLException("Signature algorithm on CertificateList does not match TBSCertList.");
}
+ if (sigAlgParams != null)
+ {
+ try
+ {
+ // needs to be called before initVerify().
+ X509SignatureUtil.setSignatureParameters(sig, ASN1Primitive.fromByteArray(sigAlgParams));
+ }
+ catch (IOException e)
+ {
+ throw new SignatureException("cannot decode signature parameters: " + e.getMessage());
+ }
+ }
+
sig.initVerify(key);
sig.update(this.getTBSCertList());
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfiguration.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfiguration.java
index e293d9f7..e5b05b61 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfiguration.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfiguration.java
@@ -1,5 +1,6 @@
package org.bouncycastle.jcajce.provider.config;
+import java.security.spec.DSAParameterSpec;
import java.util.Map;
import java.util.Set;
@@ -13,6 +14,8 @@ public interface ProviderConfiguration
DHParameterSpec getDHDefaultParameters(int keySize);
+ DSAParameterSpec getDSADefaultParameters(int keySize);
+
Set getAcceptableNamedCurves();
Map getAdditionalECParameters();
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java
index 85365b7d..f9ba6df4 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java
@@ -8,16 +8,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
-import java.security.KeyFactory;
import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
-import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
-import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
@@ -38,7 +35,10 @@ import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.SecretKeySpec;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.PBEParametersGenerator;
import org.bouncycastle.crypto.digests.SHA1Digest;
@@ -90,7 +90,7 @@ public class BcKeyStoreSpi
protected Hashtable table = new Hashtable();
- protected SecureRandom random = new SecureRandom();
+ protected SecureRandom random = CryptoServicesRegistrar.getSecureRandom();
protected int version;
@@ -446,9 +446,9 @@ public class BcKeyStoreSpi
switch (keyType)
{
case KEY_PRIVATE:
- return helper.createKeyFactory(algorithm).generatePrivate(spec);
+ return BouncyCastleProvider.getPrivateKey(PrivateKeyInfo.getInstance(enc));
case KEY_PUBLIC:
- return helper.createKeyFactory(algorithm).generatePublic(spec);
+ return BouncyCastleProvider.getPublicKey(SubjectPublicKeyInfo.getInstance(enc));
case KEY_SECRET:
return helper.createSecretKeyFactory(algorithm).generateSecret(spec);
default:
@@ -734,7 +734,7 @@ public class BcKeyStoreSpi
table.put(alias, new StoreEntry(alias, date, type, b, chain));
break;
default:
- throw new RuntimeException("Unknown object type in store.");
+ throw new IOException("Unknown object type in store.");
}
type = dIn.read();
@@ -786,7 +786,7 @@ public class BcKeyStoreSpi
dOut.write(b);
break;
default:
- throw new RuntimeException("Unknown object type in store.");
+ throw new IOException("Unknown object type in store.");
}
}
@@ -982,7 +982,7 @@ public class BcKeyStoreSpi
int iterationCount = dIn.readInt();
- if ((iterationCount < 0) || (iterationCount > 4 * MIN_ITERATIONS))
+ if ((iterationCount < 0) || (iterationCount > (MIN_ITERATIONS << 6)))
{
throw new IOException("Key store corrupted.");
}
@@ -1051,18 +1051,6 @@ public class BcKeyStoreSpi
}
}
- static Provider getBouncyCastleProvider()
- {
- if (Security.getProvider("BC") != null)
- {
- return Security.getProvider("BC");
- }
- else
- {
- return new BouncyCastleProvider();
- }
- }
-
public static class Std
extends BcKeyStoreSpi
{
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 efeaa9ae..1251ff24 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
@@ -6,6 +6,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -18,7 +19,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PrivateKey;
-import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
@@ -68,7 +68,8 @@ import org.bouncycastle.asn1.DERSet;
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
// import org.bouncycastle.asn1.cryptopro.GOST28147Parameters;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
-import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
+// import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.AuthenticatedSafe;
import org.bouncycastle.asn1.pkcs.CertBag;
import org.bouncycastle.asn1.pkcs.ContentInfo;
@@ -88,6 +89,7 @@ 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.CryptoServicesRegistrar;
import org.bouncycastle.crypto.Digest;
// Android-changed: Use Android digests
// import org.bouncycastle.crypto.util.DigestFactory;
@@ -97,8 +99,7 @@ import org.bouncycastle.jcajce.PKCS12StoreParameter;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
-// Android-changed: Use default provider for JCA algorithms instead of BC
-// Was: import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.jce.interfaces.BCKeyStore;
@@ -107,6 +108,7 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.JDKPKCS12StoreParameter;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Integers;
+import org.bouncycastle.util.Properties;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex;
@@ -114,12 +116,14 @@ public class PKCS12KeyStoreSpi
extends KeyStoreSpi
implements PKCSObjectIdentifiers, X509ObjectIdentifiers, BCKeyStore
{
+ static final String PKCS12_MAX_IT_COUNT_PROPERTY = "org.bouncycastle.pkcs12.max_it_count";
+
// Android-changed: Use default provider for JCA algorithms instead of BC
// Was: private final JcaJceHelper helper = new BCJcaJceHelper();
private final JcaJceHelper helper = new DefaultJcaJceHelper();
private static final int SALT_SIZE = 20;
- private static final int MIN_ITERATIONS = 1024;
+ private static final int MIN_ITERATIONS = 50 * 1024;
private static final DefaultSecretKeyProvider keySizeProvider = new DefaultSecretKeyProvider();
@@ -145,13 +149,17 @@ public class PKCS12KeyStoreSpi
static final int KEY_PUBLIC = 1;
static final int KEY_SECRET = 2;
- protected SecureRandom random = new SecureRandom();
+ protected SecureRandom random = CryptoServicesRegistrar.getSecureRandom();
// use of final causes problems with JDK 1.2 compiler
private CertificateFactory certFact;
private ASN1ObjectIdentifier keyAlgorithm;
private ASN1ObjectIdentifier certAlgorithm;
+ private AlgorithmIdentifier macAlgorithm = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
+ private int itCount = 2 * MIN_ITERATIONS;
+ private int saltLength = 20;
+
private class CertId
{
byte[] id;
@@ -193,7 +201,7 @@ public class PKCS12KeyStoreSpi
}
public PKCS12KeyStoreSpi(
- Provider provider,
+ JcaJceHelper helper,
ASN1ObjectIdentifier keyAlgorithm,
ASN1ObjectIdentifier certAlgorithm)
{
@@ -202,14 +210,7 @@ public class PKCS12KeyStoreSpi
try
{
- if (provider != null)
- {
- certFact = CertificateFactory.getInstance("X.509", provider);
- }
- else
- {
- certFact = CertificateFactory.getInstance("X.509");
- }
+ certFact = helper.createCertificateFactory("X.509");
}
catch (Exception e)
{
@@ -622,7 +623,7 @@ public class PKCS12KeyStoreSpi
PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
PBEParameterSpec defParams = new PBEParameterSpec(
pbeParams.getIV(),
- pbeParams.getIterations().intValue());
+ validateIterationCount(pbeParams.getIterations()));
Cipher cipher = helper.createCipher(algorithm.getId());
@@ -695,8 +696,6 @@ public class PKCS12KeyStoreSpi
if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds))
{
PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
- PBEKeySpec pbeSpec = new PBEKeySpec(password);
-
try
{
PBEParameterSpec defParams = new PBEParameterSpec(
@@ -745,17 +744,15 @@ public class PKCS12KeyStoreSpi
if (func.isDefaultPrf())
{
- key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme)));
+ key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), validateIterationCount(func.getIterationCount()), keySizeProvider.getKeySize(encScheme)));
}
else
{
- key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme), func.getPrf()));
+ key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), validateIterationCount(func.getIterationCount()), keySizeProvider.getKeySize(encScheme), func.getPrf()));
}
Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId());
- AlgorithmIdentifier encryptionAlg = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
-
ASN1Encodable encParams = alg.getEncryptionScheme().getParameters();
if (encParams instanceof ASN1OctetString)
{
@@ -804,8 +801,17 @@ public class PKCS12KeyStoreSpi
bufIn.reset();
ASN1InputStream bIn = new ASN1InputStream(bufIn);
- ASN1Sequence obj = (ASN1Sequence)bIn.readObject();
- Pfx bag = Pfx.getInstance(obj);
+
+ Pfx bag;
+ try
+ {
+ bag = Pfx.getInstance(bIn.readObject());
+ }
+ catch (Exception e)
+ {
+ throw new IOException(e.getMessage());
+ }
+
ContentInfo info = bag.getAuthSafe();
Vector chain = new Vector();
boolean unmarkedKey = false;
@@ -815,15 +821,16 @@ public class PKCS12KeyStoreSpi
{
MacData mData = bag.getMacData();
DigestInfo dInfo = mData.getMac();
- AlgorithmIdentifier algId = dInfo.getAlgorithmId();
+ macAlgorithm = dInfo.getAlgorithmId();
byte[] salt = mData.getSalt();
- int itCount = mData.getIterationCount().intValue();
+ itCount = validateIterationCount(mData.getIterationCount());
+ saltLength = salt.length;
byte[] data = ((ASN1OctetString)info.getContent()).getOctets();
try
{
- byte[] res = calculatePbeMac(algId.getAlgorithm(), salt, itCount, password, false, data);
+ byte[] res = calculatePbeMac(macAlgorithm.getAlgorithm(), salt, itCount, password, false, data);
byte[] dig = dInfo.getDigest();
if (!Arrays.constantTimeAreEqual(res, dig))
@@ -834,7 +841,7 @@ public class PKCS12KeyStoreSpi
}
// Try with incorrect zero length password
- res = calculatePbeMac(algId.getAlgorithm(), salt, itCount, password, true, data);
+ res = calculatePbeMac(macAlgorithm.getAlgorithm(), salt, itCount, password, true, data);
if (!Arrays.constantTimeAreEqual(res, dig))
{
@@ -882,7 +889,6 @@ public class PKCS12KeyStoreSpi
//
// set the attributes on the key
//
- PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey;
String alias = null;
ASN1OctetString localId = null;
@@ -900,19 +906,23 @@ public class PKCS12KeyStoreSpi
{
attr = (ASN1Primitive)attrSet.getObjectAt(0);
- ASN1Encodable existing = bagAttr.getBagAttribute(aOid);
- if (existing != null)
+ if (privKey instanceof PKCS12BagAttributeCarrier)
{
- // OK, but the value has to be the same
- if (!existing.toASN1Primitive().equals(attr))
+ PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey;
+ ASN1Encodable existing = bagAttr.getBagAttribute(aOid);
+ if (existing != null)
{
- throw new IOException(
- "attempt to add existing attribute with different value");
+ // 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
+ {
+ bagAttr.setBagAttribute(aOid, attr);
}
- }
- else
- {
- bagAttr.setBagAttribute(aOid, attr);
}
}
@@ -1222,6 +1232,27 @@ public class PKCS12KeyStoreSpi
}
}
+ private int validateIterationCount(BigInteger i)
+ {
+ int count = i.intValue();
+
+ if (count < 0)
+ {
+ throw new IllegalStateException("negative iteration count found");
+ }
+
+ BigInteger maxValue = Properties.asBigInteger(PKCS12_MAX_IT_COUNT_PROPERTY);
+ if (maxValue != null)
+ {
+ if (maxValue.intValue() < count)
+ {
+ throw new IllegalStateException("iteration count " + count + " greater than " + maxValue.intValue());
+ }
+ }
+
+ return count;
+ }
+
public void engineStore(LoadStoreParameter param)
throws IOException,
NoSuchAlgorithmException, CertificateException
@@ -1629,8 +1660,7 @@ public class PKCS12KeyStoreSpi
//
// create the mac
//
- byte[] mSalt = new byte[20];
- int itCount = MIN_ITERATIONS;
+ byte[] mSalt = new byte[saltLength];
random.nextBytes(mSalt);
@@ -1640,10 +1670,9 @@ public class PKCS12KeyStoreSpi
try
{
- byte[] res = calculatePbeMac(id_SHA1, mSalt, itCount, password, false, data);
+ byte[] res = calculatePbeMac(macAlgorithm.getAlgorithm(), mSalt, itCount, password, false, data);
- AlgorithmIdentifier algId = new AlgorithmIdentifier(id_SHA1, DERNull.INSTANCE);
- DigestInfo dInfo = new DigestInfo(algId, res);
+ DigestInfo dInfo = new DigestInfo(macAlgorithm, res);
mData = new MacData(dInfo, mSalt, itCount);
}
@@ -1720,7 +1749,9 @@ public class PKCS12KeyStoreSpi
{
public BCPKCS12KeyStore()
{
- super(new BouncyCastleProvider(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
+ // Android-changed: Use default provider for JCA algorithms instead of BC
+ // Was: super(new BCJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
+ super(new DefaultJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
}
}
@@ -1731,7 +1762,7 @@ public class PKCS12KeyStoreSpi
{
public BCPKCS12KeyStore3DES()
{
- super(new BouncyCastleProvider(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
+ super(new BCJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
}
}
@@ -1740,7 +1771,7 @@ public class PKCS12KeyStoreSpi
{
public DefPKCS12KeyStore()
{
- super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
+ super(new DefaultJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
}
}
@@ -1749,7 +1780,7 @@ public class PKCS12KeyStoreSpi
{
public DefPKCS12KeyStore3DES()
{
- super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
+ super(new DefaultJcaJceHelper(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
}
}
*/
@@ -1822,12 +1853,15 @@ public class PKCS12KeyStoreSpi
keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192));
keySizes.put(NISTObjectIdentifiers.id_aes256_CBC, Integers.valueOf(256));
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
keySizes.put(NTTObjectIdentifiers.id_camellia128_cbc, Integers.valueOf(128));
keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192));
keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256));
- // Android-removed: Unsupported algorithms
- // keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256));
+ keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256));
+ */
+ // END Android-removed: Unsupported algorithms
KEY_SIZES = Collections.unmodifiableMap(keySizes);
}
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 e0669d2c..0615fffe 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
@@ -61,8 +61,6 @@ import org.bouncycastle.jcajce.spec.AEADParameterSpec;
public final class AES
{
- private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
-
private static final Map<String, String> generalAesAttributes = new HashMap<String, String>();
static
@@ -1096,18 +1094,4 @@ public final class AES
// END Android-removed: Unsupported algorithms
}
}
-
- private static Class lookup(String className)
- {
- try
- {
- Class def = AES.class.getClassLoader().loadClass(className);
-
- return def;
- }
- catch (Exception e)
- {
- return null;
- }
- }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java
index de2e548c..cf7e4188 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java
@@ -17,7 +17,10 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.KeyGenerationParameters;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.PasswordConverter;
import org.bouncycastle.crypto.engines.DESEngine;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
@@ -32,6 +35,8 @@ import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
import org.bouncycastle.crypto.params.DESParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.jcajce.PBKDF1Key;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator;
@@ -177,7 +182,7 @@ public final class DES
if (random == null)
{
- random = new SecureRandom();
+ random = CryptoServicesRegistrar.getSecureRandom();
}
random.nextBytes(iv);
@@ -226,7 +231,7 @@ public final class DES
{
if (uninitialised)
{
- engine.init(new KeyGenerationParameters(new SecureRandom(), defaultKeySize));
+ engine.init(new KeyGenerationParameters(CryptoServicesRegistrar.getSecureRandom(), defaultKeySize));
uninitialised = false;
}
@@ -329,7 +334,21 @@ public final class DES
if (pbeSpec.getSalt() == null)
{
- return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, null);
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ if (scheme == PKCS5S1 || scheme == PKCS5S1_UTF8)
+ {
+ return new PBKDF1Key(pbeSpec.getPassword(),
+ scheme == PKCS5S1 ? PasswordConverter.ASCII : PasswordConverter.UTF8);
+ }
+ else
+ {
+ */
+ // END Android-removed: Unsupported algorithms
+ return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, null);
+ /*
+ }
+ */
}
if (forCipher)
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java
index 9b2e57b4..24785a43 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java
@@ -17,6 +17,7 @@ import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.engines.DESedeEngine;
import org.bouncycastle.crypto.engines.DESedeWrapEngine;
@@ -176,7 +177,7 @@ public final class DESede
{
if (uninitialised)
{
- engine.init(new KeyGenerationParameters(new SecureRandom(), defaultKeySize));
+ engine.init(new KeyGenerationParameters(CryptoServicesRegistrar.getSecureRandom(), defaultKeySize));
uninitialised = false;
}
@@ -278,7 +279,7 @@ public final class DESede
if (random == null)
{
- random = new SecureRandom();
+ random = CryptoServicesRegistrar.getSecureRandom();
}
random.nextBytes(iv);
@@ -463,6 +464,7 @@ public final class DESede
provider.addAlgorithm("SecretKeyFactory.PBEWITHSHAAND3-KEYTRIPLEDES-CBC", PREFIX + "$PBEWithSHAAndDES3KeyFactory");
provider.addAlgorithm("SecretKeyFactory.PBEWITHSHAAND2-KEYTRIPLEDES-CBC", PREFIX + "$PBEWithSHAAndDES2KeyFactory");
+ provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHSHA1ANDDESEDE", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND3-KEYTRIPLEDES", "PKCS12PBE");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND2-KEYTRIPLEDES", "PKCS12PBE");
@@ -471,6 +473,7 @@ public final class DESede
provider.addAlgorithm("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDDES3KEY-CBC", "PKCS12PBE");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDDES2KEY-CBC", "PKCS12PBE");
+ provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBE", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC");
provider.addAlgorithm("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.3", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC");
provider.addAlgorithm("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.4", "PBEWITHSHAAND2-KEYTRIPLEDES-CBC");
provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWithSHAAnd3KeyTripleDES", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC");
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java
index 5ccc8ff0..a28cf3eb 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GcmSpecUtil.java
@@ -7,11 +7,12 @@ import java.security.spec.InvalidParameterSpecException;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.cms.GCMParameters;
+import org.bouncycastle.jcajce.provider.symmetric.util.ClassUtil;
import org.bouncycastle.util.Integers;
class GcmSpecUtil
{
- static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
+ static final Class gcmSpecClass = ClassUtil.loadClass(GcmSpecUtil.class, "javax.crypto.spec.GCMParameterSpec");
static boolean gcmSpecExists()
{
@@ -63,16 +64,4 @@ class GcmSpecUtil
throw new InvalidParameterSpecException("Cannot process GCMParameterSpec");
}
}
-
- private static Class lookup(String className)
- {
- try
- {
- return GcmSpecUtil.class.getClassLoader().loadClass(className);
- }
- catch (Exception e)
- {
- return null;
- }
- }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java
index 31c9bda1..8474f869 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java
@@ -5,6 +5,8 @@ import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
+import java.util.HashMap;
+import java.util.Map;
import javax.crypto.SecretKey;
import javax.crypto.spec.PBEKeySpec;
@@ -15,9 +17,13 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.crypto.CipherParameters;
+// Android-removed: Unneeded imports of files we don't include
+// import org.bouncycastle.crypto.PasswordConverter;
+// import org.bouncycastle.jcajce.PBKDF2Key;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameters;
@@ -25,9 +31,28 @@ import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory;
import org.bouncycastle.jcajce.provider.symmetric.util.PBE;
import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
+import org.bouncycastle.util.Integers;
public class PBEPBKDF2
{
+ private static final Map prfCodes = new HashMap();
+
+ static
+ {
+ // Android-removed: Unsupported algorithm
+ // prfCodes.put(CryptoProObjectIdentifiers.gostR3411Hmac, Integers.valueOf(PBE.GOST3411));
+ prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA1, Integers.valueOf(PBE.SHA1));
+ prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA256, Integers.valueOf(PBE.SHA256));
+ prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA224, Integers.valueOf(PBE.SHA224));
+ prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA384, Integers.valueOf(PBE.SHA384));
+ prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA512, Integers.valueOf(PBE.SHA512));
+ // Android-remove: Unsupported algorithms
+ // prfCodes.put(NISTObjectIdentifiers.id_hmacWithSHA3_256, Integers.valueOf(PBE.SHA3_256));
+ // prfCodes.put(NISTObjectIdentifiers.id_hmacWithSHA3_224, Integers.valueOf(PBE.SHA3_224));
+ // prfCodes.put(NISTObjectIdentifiers.id_hmacWithSHA3_384, Integers.valueOf(PBE.SHA3_384));
+ // prfCodes.put(NISTObjectIdentifiers.id_hmacWithSHA3_512, Integers.valueOf(PBE.SHA3_512));
+ }
+
private PBEPBKDF2()
{
@@ -70,7 +95,7 @@ public class PBEPBKDF2
if (paramSpec == PBEParameterSpec.class)
{
return new PBEParameterSpec(params.getSalt(),
- params.getIterationCount().intValue());
+ params.getIterationCount().intValue());
}
throw new InvalidParameterSpecException("unknown parameter spec passed to PBKDF2 PBE parameters object.");
@@ -85,10 +110,10 @@ public class PBEPBKDF2
throw new InvalidParameterSpecException("PBEParameterSpec required to initialise a PBKDF2 PBE parameters algorithm parameters object");
}
- PBEParameterSpec pbeSpec = (PBEParameterSpec)paramSpec;
+ PBEParameterSpec pbeSpec = (PBEParameterSpec)paramSpec;
this.params = new PBKDF2Params(pbeSpec.getSalt(),
- pbeSpec.getIterationCount());
+ pbeSpec.getIterationCount());
}
protected void engineInit(
@@ -182,6 +207,9 @@ public class PBEPBKDF2
if (pbeSpec.getSalt() == null)
{
+ // Android-changed: Throw an exception if the salt is missing
+ // return new PBKDF2Key(((PBEKeySpec)keySpec).getPassword(),
+ // scheme == PKCS5S2 ? PasswordConverter.ASCII : PasswordConverter.UTF8);
throw new InvalidKeySpecException("missing required salt");
}
@@ -231,36 +259,12 @@ public class PBEPBKDF2
private int getDigestCode(ASN1ObjectIdentifier algorithm)
throws InvalidKeySpecException
{
- // BEGIN Android-removed: Unsupported algorithms
- /*
- if (algorithm.equals(CryptoProObjectIdentifiers.gostR3411Hmac))
- {
- return GOST3411;
- }
- else
- */
- // END Android-removed: Unsupported algorithms
- if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA1))
- {
- return SHA1;
- }
- else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA256))
- {
- return SHA256;
- }
- else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA224))
+ Integer code = (Integer)prfCodes.get(algorithm);
+ if (code != null)
{
- return SHA224;
+ return code.intValue();
}
- else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA384))
- {
- return SHA384;
- }
- else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA512))
- {
- return SHA512;
- }
-
+
throw new InvalidKeySpecException("Invalid KeySpec: unknown PRF algorithm " + algorithm);
}
}
@@ -302,6 +306,7 @@ public class PBEPBKDF2
super("PBKDF2", PKCS5S2_UTF8, SHA384);
}
}
+
public static class PBKDF2withSHA512
extends BasePBKDF2
{
@@ -311,6 +316,51 @@ public class PBEPBKDF2
}
}
+ public static class PBKDF2withGOST3411
+ extends BasePBKDF2
+ {
+ public PBKDF2withGOST3411()
+ {
+ super("PBKDF2", PKCS5S2_UTF8, GOST3411);
+ }
+ }
+
+ public static class PBKDF2withSHA3_224
+ extends BasePBKDF2
+ {
+ public PBKDF2withSHA3_224()
+ {
+ super("PBKDF2", PKCS5S2_UTF8, SHA3_224);
+ }
+ }
+
+ public static class PBKDF2withSHA3_256
+ extends BasePBKDF2
+ {
+ public PBKDF2withSHA3_256()
+ {
+ super("PBKDF2", PKCS5S2_UTF8, SHA3_256);
+ }
+ }
+
+ public static class PBKDF2withSHA3_384
+ extends BasePBKDF2
+ {
+ public PBKDF2withSHA3_384()
+ {
+ super("PBKDF2", PKCS5S2_UTF8, SHA3_384);
+ }
+ }
+
+ public static class PBKDF2withSHA3_512
+ extends BasePBKDF2
+ {
+ public PBKDF2withSHA3_512()
+ {
+ super("PBKDF2", PKCS5S2_UTF8, SHA3_512);
+ }
+ }
+
public static class PBKDF2with8BIT
extends BasePBKDF2
{
@@ -519,6 +569,11 @@ public class PBEPBKDF2
provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA256", PREFIX + "$PBKDF2withSHA256");
provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA384", PREFIX + "$PBKDF2withSHA384");
provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA512", PREFIX + "$PBKDF2withSHA512");
+ provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA3-224", PREFIX + "$PBKDF2withSHA3_224");
+ provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA3-256", PREFIX + "$PBKDF2withSHA3_256");
+ provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA3-384", PREFIX + "$PBKDF2withSHA3_384");
+ provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA3-512", PREFIX + "$PBKDF2withSHA3_512");
+ provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACGOST3411", PREFIX + "$PBKDF2withGOST3411");
*/
// END Android-removed: Bouncy Castle versions of algorithms.
// BEGIN Android-added: Android versions of algorithms.
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java
index 06693a25..c4248907 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java
@@ -15,6 +15,7 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.asn1.pkcs.RC2CBCParameter;
// import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.engines.RC2Engine;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.crypto.engines.RC2WrapEngine;
@@ -241,7 +242,7 @@ public final class RC2
if (random == null)
{
- random = new SecureRandom();
+ random = CryptoServicesRegistrar.getSecureRandom();
}
random.nextBytes(iv);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey.java
index a4719729..85113e12 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BCPBEKey.java
@@ -1,5 +1,7 @@
package org.bouncycastle.jcajce.provider.symmetric.util;
+import java.security.spec.KeySpec;
+
import javax.crypto.interfaces.PBEKey;
import javax.crypto.spec.PBEKeySpec;
@@ -45,6 +47,13 @@ public class BCPBEKey
this.param = param;
}
+ public BCPBEKey(String algName,
+ KeySpec pbeSpec, CipherParameters param)
+ {
+ this.algorithm = algName;
+ this.param = param;
+ }
+
public String getAlgorithm()
{
return algorithm;
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 9e3dafa7..db2f66ce 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
@@ -32,9 +32,12 @@ import org.bouncycastle.asn1.cms.GCMParameters;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.OutputLengthException;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.engines.DSTU7624Engine;
import org.bouncycastle.crypto.modes.AEADBlockCipher;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.modes.CCMBlockCipher;
@@ -46,6 +49,9 @@ import org.bouncycastle.crypto.modes.CTSBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.crypto.modes.GOFBBlockCipher;
+// import org.bouncycastle.crypto.modes.KCCMBlockCipher;
+// import org.bouncycastle.crypto.modes.KCTRBlockCipher;
+// import org.bouncycastle.crypto.modes.KGCMBlockCipher;
// import org.bouncycastle.crypto.modes.OCBBlockCipher;
import org.bouncycastle.crypto.modes.OFBBlockCipher;
// Android-removed: Unsupported algorithms
@@ -82,7 +88,7 @@ public class BaseBlockCipher
extends BaseWrapCipher
implements PBE
{
- private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
+ private static final Class gcmSpecClass = ClassUtil.loadClass(BaseBlockCipher.class, "javax.crypto.spec.GCMParameterSpec");
//
// specs we can handle.
@@ -93,10 +99,10 @@ public class BaseBlockCipher
// RC2ParameterSpec.class,
// RC5ParameterSpec.class,
gcmSpecClass,
- IvParameterSpec.class,
- PBEParameterSpec.class,
// Android-removed: Unsupported algorithms
// GOST28147ParameterSpec.class
+ IvParameterSpec.class,
+ PBEParameterSpec.class
};
private BlockCipher baseEngine;
@@ -118,20 +124,6 @@ public class BaseBlockCipher
private String modeName = null;
- private static Class lookup(String className)
- {
- try
- {
- Class def = BaseBlockCipher.class.getClassLoader().loadClass(className);
-
- return def;
- }
- catch (Exception e)
- {
- return null;
- }
- }
-
protected BaseBlockCipher(
BlockCipher engine)
{
@@ -189,8 +181,17 @@ public class BaseBlockCipher
org.bouncycastle.crypto.BlockCipher engine,
int ivLength)
{
+ this(engine, true, ivLength);
+ }
+
+ protected BaseBlockCipher(
+ org.bouncycastle.crypto.BlockCipher engine,
+ boolean fixedIv,
+ int ivLength)
+ {
baseEngine = engine;
+ this.fixedIv = fixedIv;
this.cipher = new BufferedGenericBlockCipher(engine);
this.ivLength = ivLength / 8;
}
@@ -199,9 +200,18 @@ public class BaseBlockCipher
BufferedBlockCipher engine,
int ivLength)
{
+ this(engine, true, ivLength);
+ }
+
+ protected BaseBlockCipher(
+ BufferedBlockCipher engine,
+ boolean fixedIv,
+ int ivLength)
+ {
baseEngine = engine.getUnderlyingCipher();
this.cipher = new BufferedGenericBlockCipher(engine);
+ this.fixedIv = fixedIv;
this.ivLength = ivLength / 8;
}
@@ -272,11 +282,6 @@ public class BaseBlockCipher
try
{
engineParams = createParametersInstance(name);
- // Android-changed: Use IvParameterSpec instead of passing raw bytes.
- // The documentation of init() says that a byte array should be decoded
- // as ASN.1, and Conscrypt's implementations follow that requirement,
- // even though Bouncy Castle's implementations don't. Wrapping it in
- // an IvParameterSpec makes the interpretation unambiguous to both.
engineParams.init(new IvParameterSpec(ivParam.getIV()));
}
catch (Exception e)
@@ -371,8 +376,21 @@ public class BaseBlockCipher
{
ivLength = baseEngine.getBlockSize();
fixedIv = false;
- cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
- new SICBlockCipher(baseEngine)));
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ if (baseEngine instanceof DSTU7624Engine)
+ {
+ cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
+ new KCTRBlockCipher(baseEngine)));
+ }
+ else
+ {
+ */
+ cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
+ new SICBlockCipher(baseEngine)));
+ /*
+ }
+ */
}
// BEGIN Android-removed: Unsupported modes
/*
@@ -397,8 +415,20 @@ public class BaseBlockCipher
}
else if (modeName.startsWith("CCM"))
{
- ivLength = 13; // CCM nonce 7..13 bytes
- cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine));
+ ivLength = 12; // CCM nonce 7..13 bytes
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ if (baseEngine instanceof DSTU7624Engine)
+ {
+ cipher = new AEADGenericBlockCipher(new KCCMBlockCipher(baseEngine));
+ }
+ else
+ {
+ */
+ cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine));
+ /*
+ }
+ */
}
// BEGIN Android-removed: Unsupported modes
/*
@@ -427,7 +457,19 @@ public class BaseBlockCipher
else if (modeName.startsWith("GCM"))
{
ivLength = baseEngine.getBlockSize();
- cipher = new AEADGenericBlockCipher(new GCMBlockCipher(baseEngine));
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ if (baseEngine instanceof DSTU7624Engine)
+ {
+ cipher = new AEADGenericBlockCipher(new KGCMBlockCipher(baseEngine));
+ }
+ else
+ {
+ */
+ cipher = new AEADGenericBlockCipher(new GCMBlockCipher(baseEngine));
+ /*
+ }
+ */
}
else
{
@@ -448,7 +490,7 @@ public class BaseBlockCipher
cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(cipher.getUnderlyingCipher()));
}
}
- else if (paddingName.equals("WITHCTS"))
+ else if (paddingName.equals("WITHCTS") || paddingName.equals("CTSPADDING") || paddingName.equals("CS3PADDING"))
{
cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(cipher.getUnderlyingCipher()));
}
@@ -868,7 +910,7 @@ public class BaseBlockCipher
if (ivRandom == null)
{
- ivRandom = new SecureRandom();
+ ivRandom = CryptoServicesRegistrar.getSecureRandom();
}
if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE))
@@ -1345,7 +1387,7 @@ public class BaseBlockCipher
private static final Constructor aeadBadTagConstructor;
static {
- Class aeadBadTagClass = lookup("javax.crypto.AEADBadTagException");
+ Class aeadBadTagClass = ClassUtil.loadClass(BaseBlockCipher.class, "javax.crypto.AEADBadTagException");
if (aeadBadTagClass != null)
{
aeadBadTagConstructor = findExceptionConstructor(aeadBadTagClass);
@@ -1450,21 +1492,4 @@ public class BaseBlockCipher
}
}
}
-
- private static class InvalidKeyOrParametersException
- extends InvalidKeyException
- {
- private final Throwable cause;
-
- InvalidKeyOrParametersException(String msg, Throwable cause)
- {
- super(msg);
- this.cause = cause;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
- }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseKeyGenerator.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseKeyGenerator.java
index 12d2b851..07b330cf 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseKeyGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseKeyGenerator.java
@@ -10,6 +10,7 @@ import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.KeyGenerationParameters;
public class BaseKeyGenerator
@@ -58,7 +59,7 @@ public class BaseKeyGenerator
{
if (random == null)
{
- random = new SecureRandom();
+ random = CryptoServicesRegistrar.getSecureRandom();
}
engine.init(new KeyGenerationParameters(random, keySize));
uninitialised = false;
@@ -73,7 +74,7 @@ public class BaseKeyGenerator
{
if (uninitialised)
{
- engine.init(new KeyGenerationParameters(new SecureRandom(), defaultKeySize));
+ engine.init(new KeyGenerationParameters(CryptoServicesRegistrar.getSecureRandom(), defaultKeySize));
uninitialised = false;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
index 45b24bff..29bd6a58 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
@@ -33,7 +33,7 @@ import org.bouncycastle.jcajce.spec.AEADParameterSpec;
public class BaseMac
extends MacSpi implements PBE
{
- private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
+ private static final Class gcmSpecClass = ClassUtil.loadClass(BaseMac.class, "javax.crypto.spec.GCMParameterSpec");
private Mac macEngine;
@@ -287,18 +287,4 @@ public class BaseMac
return newTable;
}
-
- private static Class lookup(String className)
- {
- try
- {
- Class def = BaseBlockCipher.class.getClassLoader().loadClass(className);
-
- return def;
- }
- catch (Exception e)
- {
- return null;
- }
- }
}
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 9795e2da..06e5af0f 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
@@ -20,6 +20,7 @@ import javax.crypto.spec.PBEParameterSpec;
// import javax.crypto.spec.RC5ParameterSpec;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.params.KeyParameter;
@@ -112,6 +113,38 @@ public class BaseStreamCipher
return null;
}
}
+ else if (ivParam != null)
+ {
+ String name = cipher.getAlgorithmName();
+
+ if (name.indexOf('/') >= 0)
+ {
+ name = name.substring(0, name.indexOf('/'));
+ }
+ if (name.startsWith("ChaCha7539"))
+ {
+ name = "ChaCha7539";
+ }
+ else if (name.startsWith("Grain"))
+ {
+ name = "Grainv1";
+ }
+ else if (name.startsWith("HC"))
+ {
+ int endIndex = name.indexOf('-');
+ name = name.substring(0, endIndex) + name.substring(endIndex + 1);
+ }
+
+ try
+ {
+ engineParams = createParametersInstance(name);
+ engineParams.init(new IvParameterSpec(ivParam.getIV()));
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.toString());
+ }
+ }
}
return engineParams;
@@ -124,7 +157,7 @@ public class BaseStreamCipher
String mode)
throws NoSuchAlgorithmException
{
- if (!mode.equalsIgnoreCase("ECB"))
+ if (!(mode.equalsIgnoreCase("ECB") || mode.equals("NONE")))
{
throw new NoSuchAlgorithmException("can't support mode " + mode);
}
@@ -233,7 +266,7 @@ public class BaseStreamCipher
if (ivRandom == null)
{
- ivRandom = new SecureRandom();
+ ivRandom = CryptoServicesRegistrar.getSecureRandom();
}
if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE))
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 58da98e7..4ebb2941 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
@@ -1,8 +1,10 @@
package org.bouncycastle.jcajce.provider.symmetric.util;
+import java.io.ByteArrayOutputStream;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
@@ -34,6 +36,10 @@ import org.bouncycastle.crypto.Wrapper;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.params.ParametersWithRandom;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.crypto.params.ParametersWithSBox;
+// import org.bouncycastle.crypto.params.ParametersWithUKM;
+// import org.bouncycastle.jcajce.spec.GOST28147WrapParameterSpec;
// Android-changed: Use default provider for JCA algorithms instead of BC
// Was: import org.bouncycastle.jcajce.util.BCJcaJceHelper;
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
@@ -50,11 +56,13 @@ public abstract class BaseWrapCipher
//
private Class[] availableSpecs =
{
- IvParameterSpec.class,
+ // Android-removed: Unsupported algorithms
+ // GOST28147WrapParameterSpec.class,
PBEParameterSpec.class,
// Android-removed: Unsupported algorithms
// RC2ParameterSpec.class,
// RC5ParameterSpec.class
+ IvParameterSpec.class
};
protected int pbeType = PKCS12;
@@ -69,6 +77,9 @@ public abstract class BaseWrapCipher
private int ivSize;
private byte[] iv;
+ private ErasableOutputStream wrapStream = null;
+ private boolean forWrapping;
+
// Android-changed: Use default provider for JCA algorithms instead of BC
// Was: private final JcaJceHelper helper = new BCJcaJceHelper();
private final JcaJceHelper helper = new DefaultJcaJceHelper();
@@ -115,7 +126,30 @@ public abstract class BaseWrapCipher
protected AlgorithmParameters engineGetParameters()
{
- return null;
+ if (engineParams == null)
+ {
+ if (iv != null)
+ {
+ String name = wrapEngine.getAlgorithmName();
+
+ if (name.indexOf('/') >= 0)
+ {
+ name = name.substring(0, name.indexOf('/'));
+ }
+
+ try
+ {
+ engineParams = createParametersInstance(name);
+ engineParams.init(new IvParameterSpec(iv));
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+
+ return engineParams;
}
protected final AlgorithmParameters createParametersInstance(String algorithm)
@@ -171,15 +205,35 @@ public abstract class BaseWrapCipher
if (params instanceof IvParameterSpec)
{
- IvParameterSpec iv = (IvParameterSpec) params;
- param = new ParametersWithIV(param, iv.getIV());
+ IvParameterSpec ivSpec = (IvParameterSpec)params;
+ this.iv = ivSpec.getIV();
+ param = new ParametersWithIV(param, iv);
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ if (params instanceof GOST28147WrapParameterSpec)
+ {
+ GOST28147WrapParameterSpec spec = (GOST28147WrapParameterSpec) params;
+
+ byte[] sBox = spec.getSBox();
+ if (sBox != null)
+ {
+ param = new ParametersWithSBox(param, sBox);
+ }
+ param = new ParametersWithUKM(param, spec.getUKM());
+ }
+ */
+ // END Android-removed: Unsupported algorithms
+
if (param instanceof KeyParameter && ivSize != 0)
{
- iv = new byte[ivSize];
- random.nextBytes(iv);
- param = new ParametersWithIV(param, iv);
+ if (opmode == Cipher.WRAP_MODE || opmode == Cipher.ENCRYPT_MODE)
+ {
+ iv = new byte[ivSize];
+ random.nextBytes(iv);
+ param = new ParametersWithIV(param, iv);
+ }
}
if (random != null)
@@ -187,19 +241,37 @@ public abstract class BaseWrapCipher
param = new ParametersWithRandom(param, random);
}
- switch (opmode)
+ try
{
- case Cipher.WRAP_MODE:
- wrapEngine.init(true, param);
- break;
- case Cipher.UNWRAP_MODE:
- wrapEngine.init(false, param);
- break;
- case Cipher.ENCRYPT_MODE:
- case Cipher.DECRYPT_MODE:
- throw new IllegalArgumentException("engine only valid for wrapping");
- default:
- System.out.println("eeek!");
+ switch (opmode)
+ {
+ case Cipher.WRAP_MODE:
+ wrapEngine.init(true, param);
+ this.wrapStream = null;
+ this.forWrapping = true;
+ break;
+ case Cipher.UNWRAP_MODE:
+ wrapEngine.init(false, param);
+ this.wrapStream = null;
+ this.forWrapping = false;
+ break;
+ case Cipher.ENCRYPT_MODE:
+ wrapEngine.init(true, param);
+ this.wrapStream = new ErasableOutputStream();
+ this.forWrapping = true;
+ break;
+ case Cipher.DECRYPT_MODE:
+ wrapEngine.init(false, param);
+ this.wrapStream = new ErasableOutputStream();
+ this.forWrapping = false;
+ break;
+ default:
+ throw new InvalidParameterException("Unknown mode parameter passed to init.");
+ }
+ }
+ catch (Exception e)
+ {
+ throw new InvalidKeyOrParametersException(e.getMessage(), e);
}
}
@@ -249,7 +321,7 @@ public abstract class BaseWrapCipher
}
catch (InvalidAlgorithmParameterException e)
{
- throw new IllegalArgumentException(e.getMessage());
+ throw new InvalidKeyOrParametersException(e.getMessage(), e);
}
}
@@ -258,7 +330,14 @@ public abstract class BaseWrapCipher
int inputOffset,
int inputLen)
{
- throw new RuntimeException("not supported for wrapping");
+ if (wrapStream == null)
+ {
+ throw new IllegalStateException("not supported in a wrapping mode");
+ }
+
+ wrapStream.write(input, inputOffset, inputLen);
+
+ return null;
}
protected int engineUpdate(
@@ -269,7 +348,14 @@ public abstract class BaseWrapCipher
int outputOffset)
throws ShortBufferException
{
- throw new RuntimeException("not supported for wrapping");
+ if (wrapStream == null)
+ {
+ throw new IllegalStateException("not supported in a wrapping mode");
+ }
+
+ wrapStream.write(input, inputOffset, inputLen);
+
+ return 0;
}
protected byte[] engineDoFinal(
@@ -278,7 +364,42 @@ public abstract class BaseWrapCipher
int inputLen)
throws IllegalBlockSizeException, BadPaddingException
{
- return null;
+ if (wrapStream == null)
+ {
+ throw new IllegalStateException("not supported in a wrapping mode");
+ }
+
+ wrapStream.write(input, inputOffset, inputLen);
+
+ try
+ {
+ if (forWrapping)
+ {
+ try
+ {
+ return wrapEngine.wrap(wrapStream.getBuf(), 0, wrapStream.size());
+ }
+ catch (Exception e)
+ {
+ throw new IllegalBlockSizeException(e.getMessage());
+ }
+ }
+ else
+ {
+ try
+ {
+ return wrapEngine.unwrap(wrapStream.getBuf(), 0, wrapStream.size());
+ }
+ catch (InvalidCipherTextException e)
+ {
+ throw new BadPaddingException(e.getMessage());
+ }
+ }
+ }
+ finally
+ {
+ wrapStream.erase();
+ }
}
protected int engineDoFinal(
@@ -289,7 +410,53 @@ public abstract class BaseWrapCipher
int outputOffset)
throws IllegalBlockSizeException, BadPaddingException, ShortBufferException
{
- return 0;
+ if (wrapStream == null)
+ {
+ throw new IllegalStateException("not supported in a wrapping mode");
+ }
+
+ wrapStream.write(input, inputOffset, inputLen);
+
+ try
+ {
+ byte[] enc;
+
+ if (forWrapping)
+ {
+ try
+ {
+ enc = wrapEngine.wrap(wrapStream.getBuf(), 0, wrapStream.size());
+ }
+ catch (Exception e)
+ {
+ throw new IllegalBlockSizeException(e.getMessage());
+ }
+ }
+ else
+ {
+ try
+ {
+ enc = wrapEngine.unwrap(wrapStream.getBuf(), 0, wrapStream.size());
+ }
+ catch (InvalidCipherTextException e)
+ {
+ throw new BadPaddingException(e.getMessage());
+ }
+ }
+
+ if (outputOffset + enc.length > output.length)
+ {
+ throw new ShortBufferException("output buffer too short for input.");
+ }
+
+ System.arraycopy(enc, 0, output, outputOffset, enc.length);
+
+ return enc.length;
+ }
+ finally
+ {
+ wrapStream.erase();
+ }
}
protected byte[] engineWrap(
@@ -408,4 +575,39 @@ public abstract class BaseWrapCipher
}
}
+ protected static final class ErasableOutputStream
+ extends ByteArrayOutputStream
+ {
+ public ErasableOutputStream()
+ {
+ }
+
+ public byte[] getBuf()
+ {
+ return buf;
+ }
+
+ public void erase()
+ {
+ Arrays.fill(this.buf, (byte)0);
+ reset();
+ }
+ }
+
+ protected static class InvalidKeyOrParametersException
+ extends InvalidKeyException
+ {
+ private final Throwable cause;
+
+ InvalidKeyOrParametersException(String msg, Throwable cause)
+ {
+ super(msg);
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/ClassUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/ClassUtil.java
new file mode 100644
index 00000000..37ea08b5
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/ClassUtil.java
@@ -0,0 +1,45 @@
+package org.bouncycastle.jcajce.provider.symmetric.util;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+public class ClassUtil
+{
+ public static Class loadClass(Class sourceClass, final String className)
+ {
+ try
+ {
+ ClassLoader loader = sourceClass.getClassLoader();
+
+ if (loader != null)
+ {
+ return loader.loadClass(className);
+ }
+ else
+ {
+ return (Class)AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ try
+ {
+ return Class.forName(className);
+ }
+ catch (Exception e)
+ {
+ // ignore - maybe log?
+ }
+
+ return null;
+ }
+ });
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ // ignore - maybe log?
+ }
+
+ return null;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
index 89c21734..fcfd4df6 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
@@ -49,6 +49,10 @@ public interface PBE
static final int SHA224 = 7;
static final int SHA384 = 8;
static final int SHA512 = 9;
+ static final int SHA3_224 = 10;
+ static final int SHA3_256 = 11;
+ static final int SHA3_384 = 12;
+ static final int SHA3_512 = 13;
static final int PKCS5S1 = 0;
static final int PKCS5S2 = 1;
@@ -142,6 +146,22 @@ public interface PBE
// generator = new PKCS5S2ParametersGenerator(DigestFactory.createSHA512());
generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA512());
break;
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ case SHA3_224:
+ generator = new PKCS5S2ParametersGenerator(DigestFactory.createSHA3_224());
+ break;
+ case SHA3_256:
+ generator = new PKCS5S2ParametersGenerator(DigestFactory.createSHA3_256());
+ break;
+ case SHA3_384:
+ generator = new PKCS5S2ParametersGenerator(DigestFactory.createSHA3_384());
+ break;
+ case SHA3_512:
+ generator = new PKCS5S2ParametersGenerator(DigestFactory.createSHA3_512());
+ break;
+ */
+ // END Android-removed: Unsupported algorithms
default:
throw new IllegalStateException("unknown digest scheme for PBE PKCS5S2 encryption.");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider.java
index 448c3527..fc4cf4fb 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider.java
@@ -5,7 +5,18 @@ import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
public abstract class AsymmetricAlgorithmProvider
extends AlgorithmProvider
-{
+{
+ protected void addSignatureAlgorithm(
+ ConfigurableProvider provider,
+ String algorithm,
+ String className,
+ ASN1ObjectIdentifier oid)
+ {
+ provider.addAlgorithm("Signature." + algorithm, className);
+ provider.addAlgorithm("Alg.Alias.Signature." + oid, algorithm);
+ provider.addAlgorithm("Alg.Alias.Signature.OID." + oid, algorithm);
+ }
+
protected void addSignatureAlgorithm(
ConfigurableProvider provider,
String digest,
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/DHDomainParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/DHDomainParameterSpec.java
new file mode 100644
index 00000000..13b8d451
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/DHDomainParameterSpec.java
@@ -0,0 +1,129 @@
+package org.bouncycastle.jcajce.spec;
+
+import java.math.BigInteger;
+
+import javax.crypto.spec.DHParameterSpec;
+
+import org.bouncycastle.crypto.params.DHParameters;
+import org.bouncycastle.crypto.params.DHValidationParameters;
+
+/**
+ * Extension class for DHParameterSpec that wraps a DHDomainParameters object and provides the q domain parameter.
+ */
+public class DHDomainParameterSpec
+ extends DHParameterSpec
+{
+ private final BigInteger q;
+ private final BigInteger j;
+ private final int m;
+
+ private DHValidationParameters validationParameters;
+
+ /**
+ * Base constructor - use the values in an existing set of domain parameters.
+ *
+ * @param domainParameters the Diffie-Hellman domain parameters to wrap.
+ */
+ public DHDomainParameterSpec(DHParameters domainParameters)
+ {
+ this(domainParameters.getP(), domainParameters.getQ(), domainParameters.getG(), domainParameters.getJ(), domainParameters.getM(), domainParameters.getL());
+ this.validationParameters = domainParameters.getValidationParameters();
+ }
+
+ /**
+ * Minimal constructor for parameters able to be used to verify a public key, or use with MQV.
+ *
+ * @param p the prime p defining the Galois field.
+ * @param g the generator of the multiplicative subgroup of order g.
+ * @param q specifies the prime factor of p - 1
+ */
+ public DHDomainParameterSpec(BigInteger p, BigInteger q, BigInteger g)
+ {
+ this(p, q, g, null, 0);
+ }
+
+ /**
+ * Minimal constructor for parameters able to be used to verify a public key, or use with MQV, and a private value length.
+ *
+ * @param p the prime p defining the Galois field.
+ * @param g the generator of the multiplicative subgroup of order g.
+ * @param q specifies the prime factor of p - 1
+ * @param l the maximum bit length for the private value.
+ */
+ public DHDomainParameterSpec(BigInteger p, BigInteger q, BigInteger g, int l)
+ {
+ this(p, q, g, null, l);
+ }
+
+ /**
+ * X9.42 parameters with private value length.
+ *
+ * @param p the prime p defining the Galois field.
+ * @param g the generator of the multiplicative subgroup of order g.
+ * @param q specifies the prime factor of p - 1
+ * @param j optionally specifies the value that satisfies the equation p = jq+1
+ * @param l the maximum bit length for the private value.
+ */
+ public DHDomainParameterSpec(BigInteger p, BigInteger q, BigInteger g, BigInteger j, int l)
+ {
+ this(p, q, g, j, 0, l);
+ }
+
+ /**
+ * Base constructor - the full domain parameter set.
+ *
+ * @param p the prime p defining the Galois field.
+ * @param g the generator of the multiplicative subgroup of order g.
+ * @param q specifies the prime factor of p - 1
+ * @param j optionally specifies the value that satisfies the equation p = jq+1
+ * @param m the minimum bit length for the private value.
+ * @param l the maximum bit length for the private value.
+ */
+ public DHDomainParameterSpec(BigInteger p, BigInteger q, BigInteger g, BigInteger j, int m, int l)
+ {
+ super(p, g, l);
+ this.q = q;
+ this.j = j;
+ this.m = m;
+ }
+
+ /**
+ * Return the Q value for the domain parameter set.
+ *
+ * @return the value Q.
+ */
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ /**
+ * Return the J value for the domain parameter set if available.
+ *
+ * @return the value J, null otherwise.
+ */
+ public BigInteger getJ()
+ {
+ return j;
+ }
+
+ /**
+ * Return the minimum bitlength for a private value to be generated from these parameters, 0 if not set.
+ *
+ * @return minimum bitlength for private value.
+ */
+ public int getM()
+ {
+ return m;
+ }
+
+ /**
+ * Return the DHDomainParameters object we represent.
+ *
+ * @return the internal DHDomainParameters.
+ */
+ public DHParameters getDomainParameters()
+ {
+ return new DHParameters(getP(), getG(), q, m, getL(), j, validationParameters);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java
index 25897cf5..892aa00e 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java
@@ -13,7 +13,7 @@ public class BCJcaJceHelper
{
private static volatile Provider bcProvider;
- private static Provider getBouncyCastleProvider()
+ private static synchronized Provider getBouncyCastleProvider()
{
if (Security.getProvider("BC") != null)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java
index 119d8eb5..e20d1f10 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java
@@ -6,6 +6,7 @@ import java.util.Map;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+// import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
// import org.bouncycastle.asn1.gnu.GNUObjectIdentifiers;
// import org.bouncycastle.asn1.iso.ISOIECObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
@@ -44,6 +45,7 @@ public class MessageDigestUtils
digestOidMap.put(NISTObjectIdentifiers.id_sha3_256, "SHA3-256");
digestOidMap.put(NISTObjectIdentifiers.id_sha3_384, "SHA3-384");
digestOidMap.put(NISTObjectIdentifiers.id_sha3_512, "SHA3-512");
+ digestOidMap.put(GMObjectIdentifiers.sm3, "SM3");
*/
// END Android-removed: Unsupported algorithms
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java b/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java
index 22373486..1c63c3b2 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/PKCS10CertificationRequest.java
@@ -66,8 +66,8 @@ import org.bouncycastle.util.Strings;
* 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>
* @deprecated use classes in org.bouncycastle.pkcs.
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/netscape/NetscapeCertRequest.java b/bcprov/src/main/java/org/bouncycastle/jce/netscape/NetscapeCertRequest.java
index f8a1a6fd..159224f2 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/netscape/NetscapeCertRequest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/netscape/NetscapeCertRequest.java
@@ -31,7 +31,7 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
*
*
* Handles NetScape certificate request (KEYGEN), these are constructed as:
- * <pre><code>
+ * <pre>
* SignedPublicKeyAndChallenge ::= SEQUENCE {
* publicKeyAndChallenge PublicKeyAndChallenge,
* signatureAlgorithm AlgorithmIdentifier,
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 dfc56d7e..4458fc14 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
@@ -15,8 +15,19 @@ import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
+import org.bouncycastle.jcajce.provider.symmetric.util.ClassUtil;
import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
+// Android-removed: Unsupported algorithms
+// import org.bouncycastle.pqc.asn1.PQCObjectIdentifiers;
+// import org.bouncycastle.pqc.jcajce.provider.mceliece.McElieceCCA2KeyFactorySpi;
+// import org.bouncycastle.pqc.jcajce.provider.mceliece.McElieceKeyFactorySpi;
+// import org.bouncycastle.pqc.jcajce.provider.newhope.NHKeyFactorySpi;
+// import org.bouncycastle.pqc.jcajce.provider.qtesla.QTESLAKeyFactorySpi;
+// import org.bouncycastle.pqc.jcajce.provider.rainbow.RainbowKeyFactorySpi;
+// import org.bouncycastle.pqc.jcajce.provider.sphincs.Sphincs256KeyFactorySpi;
+// import org.bouncycastle.pqc.jcajce.provider.xmss.XMSSKeyFactorySpi;
+// import org.bouncycastle.pqc.jcajce.provider.xmss.XMSSMTKeyFactorySpi;
/**
* To add the provider at runtime use:
@@ -45,7 +56,7 @@ import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
public final class BouncyCastleProvider extends Provider
implements ConfigurableProvider
{
- private static String info = "BouncyCastle Security Provider v1.57";
+ private static String info = "BouncyCastle Security Provider v1.61";
public static final String PROVIDER_NAME = "BC";
@@ -61,7 +72,7 @@ public final class BouncyCastleProvider extends Provider
private static final String[] SYMMETRIC_GENERIC =
{
// Android-changed: Remove unsupported algorithms, add our own version of PBEv2 AlgParams
- // "PBEPBKDF2", "TLSKDF"
+ // "PBEPBKDF1", "PBEPBKDF2", "PBEPKCS12", "TLSKDF", "SCRYPT"
"PBEPBKDF2", "PBEPKCS12", "PBES2AlgorithmParameters"
};
@@ -77,7 +88,7 @@ public final class BouncyCastleProvider extends Provider
// "AES", "ARC4", "ARIA", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede",
// "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA", "Noekeon", "RC2", "RC5",
// "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "SM4", "TEA", "Twofish", "Threefish",
- // "VMPC", "VMPCKSA3", "XTEA", "XSalsa20", "OpenSSLPBKDF"
+ // "VMPC", "VMPCKSA3", "XTEA", "XSalsa20", "OpenSSLPBKDF", "DSTU7624", "GOST3412_2015"
"AES", "ARC4", "Blowfish", "DES", "DESede", "RC2", "Twofish",
};
@@ -98,7 +109,7 @@ public final class BouncyCastleProvider extends Provider
private static final String[] ASYMMETRIC_CIPHERS =
{
// Android-changed: Unsupported algorithms
- // "DSA", "DH", "EC", "RSA", "GOST", "ECGOST", "ElGamal", "DSTU4145", "GM"
+ // "DSA", "DH", "EC", "RSA", "GOST", "ECGOST", "ElGamal", "DSTU4145", "GM", "EdEC"
"DSA", "DH", "EC", "RSA",
};
@@ -110,7 +121,7 @@ public final class BouncyCastleProvider extends Provider
{
// Android-changed: Unsupported algorithms
// "GOST3411", "Keccak", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224",
- // "SHA256", "SHA384", "SHA512", "SHA3", "Skein", "SM3", "Tiger", "Whirlpool", "Blake2b"
+ // "SHA256", "SHA384", "SHA512", "SHA3", "Skein", "SM3", "Tiger", "Whirlpool", "Blake2b", "Blake2s", "DSTU7564"
"MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512",
};
@@ -140,7 +151,7 @@ public final class BouncyCastleProvider extends Provider
*/
public BouncyCastleProvider()
{
- super(PROVIDER_NAME, 1.57, info);
+ super(PROVIDER_NAME, 1.61, info);
AccessController.doPrivileged(new PrivilegedAction()
{
@@ -172,6 +183,7 @@ public final class BouncyCastleProvider extends Provider
/*
loadAlgorithms(SECURE_RANDOM_PACKAGE, SECURE_RANDOMS);
+ loadPQCKeys(); // so we can handle certificates containing them.
//
// X509Store
//
@@ -224,24 +236,7 @@ public final class BouncyCastleProvider extends Provider
{
for (int i = 0; i != names.length; i++)
{
- Class clazz = null;
- try
- {
- ClassLoader loader = this.getClass().getClassLoader();
-
- if (loader != null)
- {
- clazz = loader.loadClass(packageName + names[i] + "$Mappings");
- }
- else
- {
- clazz = Class.forName(packageName + names[i] + "$Mappings");
- }
- }
- catch (ClassNotFoundException e)
- {
- // ignore
- }
+ Class clazz = ClassUtil.loadClass(BouncyCastleProvider.class, packageName + names[i] + "$Mappings");
if (clazz != null)
{
@@ -258,6 +253,26 @@ public final class BouncyCastleProvider extends Provider
}
}
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ private void loadPQCKeys()
+ {
+ addKeyInfoConverter(PQCObjectIdentifiers.sphincs256, new Sphincs256KeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.newHope, new NHKeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.xmss, new XMSSKeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.xmss_mt, new XMSSMTKeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.mcEliece, new McElieceKeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.mcElieceCca2, new McElieceCCA2KeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.rainbow, new RainbowKeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.qTESLA_I, new QTESLAKeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.qTESLA_III_size, new QTESLAKeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.qTESLA_III_speed, new QTESLAKeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.qTESLA_p_I, new QTESLAKeyFactorySpi());
+ addKeyInfoConverter(PQCObjectIdentifiers.qTESLA_p_III, new QTESLAKeyFactorySpi());
+ }
+ */
+ // END Android-removed: Unsupported algorithms
+
public void setParameter(String parameterName, Object parameter)
{
synchronized (CONFIGURATION)
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration.java
index f89b9fd7..87b69273 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration.java
@@ -1,6 +1,7 @@
package org.bouncycastle.jce.provider;
import java.security.Permission;
+import java.security.spec.DSAParameterSpec;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -9,10 +10,14 @@ import java.util.Set;
import javax.crypto.spec.DHParameterSpec;
+import org.bouncycastle.crypto.CryptoServicesRegistrar;
+import org.bouncycastle.crypto.params.DHParameters;
+import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jcajce.provider.config.ProviderConfigurationPermission;
+import org.bouncycastle.jcajce.spec.DHDomainParameterSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
class BouncyCastleProviderConfiguration
@@ -191,6 +196,23 @@ class BouncyCastleProviderConfiguration
}
}
+ DHParameters dhParams = CryptoServicesRegistrar.getSizedProperty(CryptoServicesRegistrar.Property.DH_DEFAULT_PARAMS, keySize);
+ if (dhParams != null)
+ {
+ return new DHDomainParameterSpec(dhParams);
+ }
+
+ return null;
+ }
+
+ public DSAParameterSpec getDSADefaultParameters(int keySize)
+ {
+ DSAParameters dsaParams = CryptoServicesRegistrar.getSizedProperty(CryptoServicesRegistrar.Property.DSA_DEFAULT_PARAMS, keySize);
+ if (dsaParams != null)
+ {
+ return new DSAParameterSpec(dsaParams.getP(), dsaParams.getQ(), dsaParams.getG());
+ }
+
return null;
}
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 b72a6f44..0f783ec2 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
@@ -237,6 +237,22 @@ class CertPathValidatorUtilities
return trust;
}
+ static boolean isIssuerTrustAnchor(
+ X509Certificate cert,
+ Set trustAnchors,
+ String sigProvider)
+ throws AnnotatedException
+ {
+ try
+ {
+ return findTrustAnchor(cert, trustAnchors, sigProvider) != null;
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+
static List<PKIXCertStore> getAdditionalStoresFromAltNames(
byte[] issuerAlternativeName,
Map<GeneralName, PKIXCertStore> altNameCertStoreMap)
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 a30b2df7..d4fa2852 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEDHPrivateKey.java
@@ -59,9 +59,9 @@ public class JCEDHPrivateKey
PrivateKeyInfo info)
throws IOException
{
- ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithmId().getParameters());
+ ASN1Sequence seq = ASN1Sequence.getInstance(info.getPrivateKeyAlgorithm().getParameters());
ASN1Integer derX = ASN1Integer.getInstance(info.parsePrivateKey());
- ASN1ObjectIdentifier id = info.getAlgorithmId().getAlgorithm();
+ ASN1ObjectIdentifier id = info.getPrivateKeyAlgorithm().getAlgorithm();
this.info = info;
this.x = derX.getValue();
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 7d6a50cf..1e99c86f 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
@@ -114,22 +114,19 @@ public class JCEECPrivateKey
JCEECPublicKey pubKey,
ECParameterSpec spec)
{
- ECDomainParameters dp = params.getParameters();
-
this.algorithm = algorithm;
this.d = params.getD();
if (spec == null)
{
+ ECDomainParameters dp = params.getParameters();
EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getAffineXCoord().toBigInteger(),
- dp.getG().getAffineYCoord().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ EC5Util.convertPoint(dp.getG()),
+ dp.getN(),
+ dp.getH().intValue());
}
else
{
@@ -145,34 +142,29 @@ public class JCEECPrivateKey
JCEECPublicKey pubKey,
org.bouncycastle.jce.spec.ECParameterSpec spec)
{
- ECDomainParameters dp = params.getParameters();
-
this.algorithm = algorithm;
this.d = params.getD();
if (spec == null)
{
+ ECDomainParameters dp = params.getParameters();
EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getAffineXCoord().toBigInteger(),
- dp.getG().getAffineYCoord().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ EC5Util.convertPoint(dp.getG()),
+ dp.getN(),
+ dp.getH().intValue());
}
else
{
EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- spec.getG().getAffineXCoord().toBigInteger(),
- spec.getG().getAffineYCoord().toBigInteger()),
- spec.getN(),
- spec.getH().intValue());
+ ellipticCurve,
+ EC5Util.convertPoint(spec.getG()),
+ spec.getN(),
+ spec.getH().intValue());
}
publicKey = getPublicKeyDetails(pubKey);
@@ -212,13 +204,11 @@ public class JCEECPrivateKey
EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed());
ecSpec = new ECNamedCurveSpec(
- ECGOST3410NamedCurves.getName(oid),
- ellipticCurve,
- new ECPoint(
- gParam.getG().getAffineXCoord().toBigInteger(),
- gParam.getG().getAffineYCoord().toBigInteger()),
- gParam.getN(),
- gParam.getH());
+ ECGOST3410NamedCurves.getName(oid),
+ ellipticCurve,
+ EC5Util.convertPoint(gParam.getG()),
+ gParam.getN(),
+ gParam.getH());
}
else
*/
@@ -227,13 +217,11 @@ public class JCEECPrivateKey
EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
ecSpec = new ECNamedCurveSpec(
- ECUtil.getCurveName(oid),
- ellipticCurve,
- new ECPoint(
- ecP.getG().getAffineXCoord().toBigInteger(),
- ecP.getG().getAffineYCoord().toBigInteger()),
- ecP.getN(),
- ecP.getH());
+ ECUtil.getCurveName(oid),
+ ellipticCurve,
+ EC5Util.convertPoint(ecP.getG()),
+ ecP.getN(),
+ ecP.getH());
}
}
else if (params.isImplicitlyCA())
@@ -247,9 +235,7 @@ public class JCEECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
- new ECPoint(
- ecP.getG().getAffineXCoord().toBigInteger(),
- ecP.getG().getAffineYCoord().toBigInteger()),
+ EC5Util.convertPoint(ecP.getG()),
ecP.getN(),
ecP.getH().intValue());
}
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 654b5e1d..916f6fd8 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
@@ -163,14 +163,12 @@ public class JCEECPublicKey
private ECParameterSpec createSpec(EllipticCurve ellipticCurve, ECDomainParameters dp)
{
return new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getAffineXCoord().toBigInteger(),
- dp.getG().getAffineYCoord().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ EC5Util.convertPoint(dp.getG()),
+ dp.getN(),
+ dp.getH().intValue());
}
-
+
public JCEECPublicKey(
ECPublicKey key)
{
@@ -204,18 +202,14 @@ public class JCEECPublicKey
throw new IllegalArgumentException("error recovering public key");
}
- byte[] keyEnc = key.getOctets();
- byte[] x = new byte[32];
- byte[] y = new byte[32];
-
- for (int i = 0; i != x.length; i++)
- {
- x[i] = keyEnc[32 - 1 - i];
- }
+ byte[] keyEnc = key.getOctets();
- for (int i = 0; i != y.length; i++)
+ byte[] x9Encoding = new byte[65];
+ x9Encoding[0] = 0x04;
+ for (int i = 1; i <= 32; ++i)
{
- y[i] = keyEnc[64 - 1 - i];
+ x9Encoding[i ] = keyEnc[32 - i];
+ x9Encoding[i + 32] = keyEnc[64 - i];
}
gostParams = new GOST3410PublicKeyAlgParameters((ASN1Sequence)info.getAlgorithmId().getParameters());
@@ -225,16 +219,14 @@ public class JCEECPublicKey
ECCurve curve = spec.getCurve();
EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
- this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y), false);
+ this.q = curve.decodePoint(x9Encoding);
ecSpec = new ECNamedCurveSpec(
- ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
- ellipticCurve,
- new ECPoint(
- spec.getG().getAffineXCoord().toBigInteger(),
- spec.getG().getAffineYCoord().toBigInteger()),
- spec.getN(), spec.getH());
-
+ ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
+ ellipticCurve,
+ EC5Util.convertPoint(spec.getG()),
+ spec.getN(),
+ spec.getH());
}
else
*/
@@ -253,13 +245,11 @@ public class JCEECPublicKey
ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
ecSpec = new ECNamedCurveSpec(
- ECUtil.getCurveName(oid),
- ellipticCurve,
- new ECPoint(
- ecP.getG().getAffineXCoord().toBigInteger(),
- ecP.getG().getAffineYCoord().toBigInteger()),
- ecP.getN(),
- ecP.getH());
+ ECUtil.getCurveName(oid),
+ ellipticCurve,
+ EC5Util.convertPoint(ecP.getG()),
+ ecP.getN(),
+ ecP.getH());
}
else if (params.isImplicitlyCA())
{
@@ -268,18 +258,16 @@ public class JCEECPublicKey
}
else
{
- X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters());
+ X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters());
curve = ecP.getCurve();
ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- ecP.getG().getAffineXCoord().toBigInteger(),
- ecP.getG().getAffineYCoord().toBigInteger()),
- ecP.getN(),
- ecP.getH().intValue());
+ ellipticCurve,
+ EC5Util.convertPoint(ecP.getG()),
+ ecP.getN(),
+ ecP.getH().intValue());
}
DERBitString bits = info.getPublicKeyData();
@@ -448,7 +436,7 @@ public class JCEECPublicKey
public ECPoint getW()
{
- return new ECPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
+ return EC5Util.convertPoint(q);
}
public org.bouncycastle.math.ec.ECPoint getQ()
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java
index dfe9cef5..b9086219 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java
@@ -54,7 +54,6 @@ public class PKIXCertPathBuilderSpi
{
ExtendedPKIXBuilderParameters extPKIX = (ExtendedPKIXBuilderParameters)params;
- ;
for (Iterator it = extPKIX.getAdditionalStores().iterator(); it.hasNext();)
{
paramsPKIXBldr.addCertificateStore((PKIXCertStore)it.next());
@@ -187,8 +186,8 @@ public class PKIXCertPathBuilderSpi
try
{
// check whether the issuer of <tbvCert> is a TrustAnchor
- if (CertPathValidatorUtilities.findTrustAnchor(tbvCert, pkixParams.getBaseParameters().getTrustAnchors(),
- pkixParams.getBaseParameters().getSigProvider()) != null)
+ if (CertPathValidatorUtilities.isIssuerTrustAnchor(tbvCert, pkixParams.getBaseParameters().getTrustAnchors(),
+ pkixParams.getBaseParameters().getSigProvider()))
{
// exception message from possibly later tried certification
// chains
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 bd2331ab..16659525 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
@@ -1,8 +1,6 @@
package org.bouncycastle.jce.provider;
-// BEGIN Android-added: Blacklist support
import java.math.BigInteger;
-// END Android-added: Blacklist support
import java.security.InvalidAlgorithmParameterException;
import java.security.PublicKey;
import java.security.cert.CertPath;
@@ -10,6 +8,7 @@ import java.security.cert.CertPathParameters;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorResult;
import java.security.cert.CertPathValidatorSpi;
+import java.security.cert.CertificateEncodingException;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXCertPathValidatorResult;
import java.security.cert.PKIXParameters;
@@ -26,6 +25,7 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.TBSCertificate;
import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters;
import org.bouncycastle.jcajce.PKIXExtendedParameters;
import org.bouncycastle.jcajce.util.BCJcaJceHelper;
@@ -140,15 +140,17 @@ public class PKIXCertPathValidatorSpi
{
trust = CertPathValidatorUtilities.findTrustAnchor((X509Certificate) certs.get(certs.size() - 1),
paramsPKIX.getTrustAnchors(), paramsPKIX.getSigProvider());
+
+ if (trust == null)
+ {
+ throw new CertPathValidatorException("Trust anchor for certification path not found.", null, certPath, -1);
+ }
+
+ checkCertificate(trust.getTrustedCert());
}
catch (AnnotatedException e)
{
- throw new CertPathValidatorException(e.getMessage(), e, certPath, certs.size() - 1);
- }
-
- if (trust == null)
- {
- throw new CertPathValidatorException("Trust anchor for certification path not found.", null, certPath, -1);
+ throw new CertPathValidatorException(e.getMessage(), e.getUnderlyingException(), certPath, certs.size() - 1);
}
// RFC 5280 - CRLs must originate from the same trust anchor as the target certificate.
@@ -325,6 +327,15 @@ public class PKIXCertPathValidatorSpi
cert = (X509Certificate) certs.get(index);
boolean verificationAlreadyPerformed = (index == certs.size() - 1);
+ try
+ {
+ checkCertificate(cert);
+ }
+ catch (AnnotatedException e)
+ {
+ throw new CertPathValidatorException(e.getMessage(), e.getUnderlyingException(), certPath, index);
+ }
+
//
// 6.1.3
//
@@ -344,11 +355,15 @@ public class PKIXCertPathValidatorSpi
//
// 6.1.4
//
-
if (i != n)
{
if (cert != null && cert.getVersion() == 1)
{
+ // we've found the trust anchor at the top of the path, ignore and keep going
+ if ((i == 1) && cert.equals(trust.getTrustedCert()))
+ {
+ continue;
+ }
throw new CertPathValidatorException("Version 1 certificates can't be used as CA ones.", null,
certPath, index);
}
@@ -487,4 +502,20 @@ public class PKIXCertPathValidatorSpi
throw new CertPathValidatorException("Path processing failed on policy.", null, certPath, index);
}
+ static void checkCertificate(X509Certificate cert)
+ throws AnnotatedException
+ {
+ try
+ {
+ TBSCertificate.getInstance(cert.getTBSCertificate());
+ }
+ catch (CertificateEncodingException e)
+ {
+ throw new AnnotatedException("unable to process TBSCertificate", e);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new AnnotatedException(e.getMessage());
+ }
+ }
}
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 d67a77ee..1ed22d59 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java
@@ -59,7 +59,6 @@ import org.bouncycastle.jcajce.PKIXCertStoreSelector;
import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters;
import org.bouncycastle.jcajce.PKIXExtendedParameters;
import org.bouncycastle.jcajce.util.JcaJceHelper;
-import org.bouncycastle.jce.PrincipalUtil;
import org.bouncycastle.jce.exception.ExtCertPathValidatorException;
import org.bouncycastle.util.Arrays;
@@ -2421,8 +2420,11 @@ class RFC3280CertPathUtilities
}
catch (CertPathValidatorException e)
{
- throw new ExtCertPathValidatorException("Additional certificate path checker failed.", e, certPath,
- index);
+ throw new ExtCertPathValidatorException(e.getMessage(), e, certPath, index);
+ }
+ catch (Exception e)
+ {
+ throw new CertPathValidatorException("Additional certificate path checker failed.", e, certPath, index);
}
}
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 36aa595e..0be2ca90 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
@@ -7,6 +7,7 @@ import java.security.spec.ECFieldFp;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
+import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.field.FiniteField;
@@ -46,21 +47,14 @@ public class ECNamedCurveSpec
return new ECFieldF2m(poly.getDegree(), ks);
}
}
-
- private static ECPoint convertPoint(
- org.bouncycastle.math.ec.ECPoint g)
- {
- g = g.normalize();
- return new ECPoint(g.getAffineXCoord().toBigInteger(), g.getAffineYCoord().toBigInteger());
- }
-
+
public ECNamedCurveSpec(
String name,
ECCurve curve,
org.bouncycastle.math.ec.ECPoint g,
BigInteger n)
{
- super(convertCurve(curve, null), convertPoint(g), n, 1);
+ super(convertCurve(curve, null), EC5Util.convertPoint(g), n, 1);
this.name = name;
}
@@ -83,7 +77,7 @@ public class ECNamedCurveSpec
BigInteger n,
BigInteger h)
{
- super(convertCurve(curve, null), convertPoint(g), n, h.intValue());
+ super(convertCurve(curve, null), EC5Util.convertPoint(g), n, h.intValue());
this.name = name;
}
@@ -108,8 +102,8 @@ public class ECNamedCurveSpec
BigInteger h,
byte[] seed)
{
- super(convertCurve(curve, seed), convertPoint(g), n, h.intValue());
-
+ super(convertCurve(curve, seed), EC5Util.convertPoint(g), n, h.intValue());
+
this.name = name;
}
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 d1f35c56..e0a55435 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
@@ -19,8 +19,13 @@ public abstract class AbstractECMultiplier implements ECMultiplier
* 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);
+ return checkResult(result);
}
protected abstract ECPoint multiplyPositive(ECPoint p, BigInteger k);
+
+ protected ECPoint checkResult(ECPoint p)
+ {
+ return ECAlgorithms.implCheckResult(p);
+ }
}
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 f8bf1eb5..f0b1585d 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
@@ -61,10 +61,10 @@ public class ECAlgorithms
ECEndomorphism endomorphism = c.getEndomorphism();
if (endomorphism instanceof GLVEndomorphism)
{
- return validatePoint(implSumOfMultipliesGLV(imported, ks, (GLVEndomorphism)endomorphism));
+ return implCheckResult(implSumOfMultipliesGLV(imported, ks, (GLVEndomorphism)endomorphism));
}
- return validatePoint(implSumOfMultiplies(imported, ks));
+ return implCheckResult(implSumOfMultiplies(imported, ks));
}
public static ECPoint sumOfTwoMultiplies(ECPoint P, BigInteger a,
@@ -79,18 +79,18 @@ public class ECAlgorithms
ECCurve.AbstractF2m f2mCurve = (ECCurve.AbstractF2m)cp;
if (f2mCurve.isKoblitz())
{
- return validatePoint(P.multiply(a).add(Q.multiply(b)));
+ return implCheckResult(P.multiply(a).add(Q.multiply(b)));
}
}
ECEndomorphism endomorphism = cp.getEndomorphism();
if (endomorphism instanceof GLVEndomorphism)
{
- return validatePoint(
+ return implCheckResult(
implSumOfMultipliesGLV(new ECPoint[]{ P, Q }, new BigInteger[]{ a, b }, (GLVEndomorphism)endomorphism));
}
- return validatePoint(implShamirsTrickWNaf(P, a, Q, b));
+ return implCheckResult(implShamirsTrickWNaf(P, a, Q, b));
}
/*
@@ -118,7 +118,7 @@ public class ECAlgorithms
ECCurve cp = P.getCurve();
Q = importPoint(cp, Q);
- return validatePoint(implShamirsTrickJsf(P, k, Q, l));
+ return implCheckResult(implShamirsTrickJsf(P, k, Q, l));
}
public static ECPoint importPoint(ECCurve c, ECPoint p)
@@ -211,7 +211,28 @@ public class ECAlgorithms
{
if (!p.isValid())
{
- throw new IllegalArgumentException("Invalid point");
+ throw new IllegalStateException("Invalid point");
+ }
+
+ return p;
+ }
+
+ public static ECPoint cleanPoint(ECCurve c, ECPoint p)
+ {
+ ECCurve cp = p.getCurve();
+ if (!c.equals(cp))
+ {
+ throw new IllegalArgumentException("Point must be on the same curve");
+ }
+
+ return c.decodePoint(p.getEncoded(false));
+ }
+
+ static ECPoint implCheckResult(ECPoint p)
+ {
+ if (!p.isValidPartial())
+ {
+ throw new IllegalStateException("Invalid result");
}
return p;
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 7f3197bc..7c10c78b 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
@@ -8,6 +8,7 @@ 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.math.raw.Nat;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.Integers;
@@ -173,15 +174,26 @@ public abstract class ECCurve
public PreCompInfo getPreCompInfo(ECPoint point, String name)
{
checkPoint(point);
+
+ Hashtable table;
synchronized (point)
{
- Hashtable table = point.preCompTable;
- return table == null ? null : (PreCompInfo)table.get(name);
+ table = point.preCompTable;
+ }
+
+ if (null == table)
+ {
+ return null;
+ }
+
+ synchronized (table)
+ {
+ return (PreCompInfo)table.get(name);
}
}
/**
- * Adds <code>PreCompInfo</code> for a point on this curve, under a given name. Used by
+ * Compute a <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.
*
@@ -189,20 +201,34 @@ public abstract class ECCurve
* 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>.
+ * @param callback
+ * Called to calculate the <code>PreCompInfo</code>.
*/
- public void setPreCompInfo(ECPoint point, String name, PreCompInfo preCompInfo)
+ public PreCompInfo precompute(ECPoint point, String name, PreCompCallback callback)
{
checkPoint(point);
+
+ Hashtable table;
synchronized (point)
{
- Hashtable table = point.preCompTable;
+ table = point.preCompTable;
if (null == table)
{
point.preCompTable = table = new Hashtable(4);
}
- table.put(name, preCompInfo);
+ }
+
+ synchronized (table)
+ {
+ PreCompInfo existing = (PreCompInfo)table.get(name);
+ PreCompInfo result = callback.precompute(existing);
+
+ if (result != existing)
+ {
+ table.put(name, result);
+ }
+
+ return result;
}
}
@@ -220,7 +246,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 validatePoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression);
+ return createPoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression);
}
/**
@@ -390,7 +416,7 @@ public abstract class ECCurve
BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
p = decompressPoint(yTilde, X);
- if (!p.satisfiesCofactor())
+ if (!p.implIsValid(true, true))
{
throw new IllegalArgumentException("Invalid point");
}
@@ -441,6 +467,61 @@ public abstract class ECCurve
return p;
}
+ /**
+ * Create a cache-safe lookup table for the specified sequence of points. All the points MUST
+ * belong to this {@link ECCurve} instance, and MUST already be normalized.
+ */
+ public ECLookupTable createCacheSafeLookupTable(final ECPoint[] points, int off, final int len)
+ {
+ final int FE_BYTES = (getFieldSize() + 7) >>> 3;
+
+ final byte[] table = new byte[len * FE_BYTES * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ byte[] px = p.getRawXCoord().toBigInteger().toByteArray();
+ byte[] py = p.getRawYCoord().toBigInteger().toByteArray();
+
+ int pxStart = px.length > FE_BYTES ? 1 : 0, pxLen = px.length - pxStart;
+ int pyStart = py.length > FE_BYTES ? 1 : 0, pyLen = py.length - pyStart;
+
+ System.arraycopy(px, pxStart, table, pos + FE_BYTES - pxLen, pxLen); pos += FE_BYTES;
+ System.arraycopy(py, pyStart, table, pos + FE_BYTES - pyLen, pyLen); pos += FE_BYTES;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ byte[] x = new byte[FE_BYTES], y = new byte[FE_BYTES];
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_BYTES; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_BYTES + j] & MASK;
+ }
+
+ pos += (FE_BYTES * 2);
+ }
+
+ return createRawPoint(fromBigInteger(new BigInteger(1, x)), fromBigInteger(new BigInteger(1, y)), false);
+ }
+ };
+ }
+
protected void checkPoint(ECPoint point)
{
if (null == point || (this != point.getCurve()))
@@ -542,6 +623,9 @@ public abstract class ECCurve
BigInteger q, r;
ECPoint.Fp infinity;
+ /**
+ * @deprecated use constructor taking order/cofactor
+ */
public Fp(BigInteger q, BigInteger a, BigInteger b)
{
this(q, a, b, null, null);
@@ -553,7 +637,7 @@ public abstract class ECCurve
this.q = q;
this.r = ECFieldElement.Fp.calculateResidue(q);
- this.infinity = new ECPoint.Fp(this, null, null);
+ this.infinity = new ECPoint.Fp(this, null, null, false);
this.a = fromBigInteger(a);
this.b = fromBigInteger(b);
@@ -562,6 +646,9 @@ public abstract class ECCurve
this.coord = FP_DEFAULT_COORDS;
}
+ /**
+ * @deprecated use constructor taking order/cofactor
+ */
protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)
{
this(q, r, a, b, null, null);
@@ -573,7 +660,7 @@ public abstract class ECCurve
this.q = q;
this.r = r;
- this.infinity = new ECPoint.Fp(this, null, null);
+ this.infinity = new ECPoint.Fp(this, null, null, false);
this.a = a;
this.b = b;
@@ -814,7 +901,7 @@ public abstract class ECCurve
* @return the solution for <code>z<sup>2</sup> + z = beta</code> or
* <code>null</code> if no solution exists.
*/
- private ECFieldElement solveQuadraticEquation(ECFieldElement beta)
+ protected ECFieldElement solveQuadraticEquation(ECFieldElement beta)
{
if (beta.isZero())
{
@@ -928,6 +1015,7 @@ 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>.
+ * @deprecated use constructor taking order/cofactor
*/
public F2m(
int m,
@@ -985,6 +1073,7 @@ 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>.
+ * @deprecated use constructor taking order/cofactor
*/
public F2m(
int m,
@@ -1039,7 +1128,7 @@ public abstract class ECCurve
this.order = order;
this.cofactor = cofactor;
- this.infinity = new ECPoint.F2m(this, null, null);
+ this.infinity = new ECPoint.F2m(this, null, null, false);
this.a = fromBigInteger(a);
this.b = fromBigInteger(b);
this.coord = F2M_DEFAULT_COORDS;
@@ -1056,7 +1145,7 @@ public abstract class ECCurve
this.order = order;
this.cofactor = cofactor;
- this.infinity = new ECPoint.F2m(this, null, null);
+ this.infinity = new ECPoint.F2m(this, null, null, false);
this.a = a;
this.b = b;
this.coord = F2M_DEFAULT_COORDS;
@@ -1145,20 +1234,50 @@ public abstract class ECCurve
return k3;
}
- /**
- * @deprecated use {@link #getOrder()} instead
- */
- public BigInteger getN()
+ public ECLookupTable createCacheSafeLookupTable(ECPoint[] points, int off, final int len)
{
- return this.order;
- }
+ final int FE_LONGS = (m + 63) >>> 6;
+ final int[] ks = isTrinomial() ? new int[]{ k1 } : new int[]{ k1, k2, k3 };
- /**
- * @deprecated use {@link #getCofactor()} instead
- */
- public BigInteger getH()
- {
- return this.cofactor;
+ final long[] table = new long[len * FE_LONGS * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ ((ECFieldElement.F2m)p.getRawXCoord()).x.copyTo(table, pos); pos += FE_LONGS;
+ ((ECFieldElement.F2m)p.getRawYCoord()).x.copyTo(table, pos); pos += FE_LONGS;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ long[] x = Nat.create64(FE_LONGS), y = Nat.create64(FE_LONGS);
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ long MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_LONGS; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_LONGS + j] & MASK;
+ }
+
+ pos += (FE_LONGS * 2);
+ }
+
+ return createRawPoint(new ECFieldElement.F2m(m, ks, new LongArray(x)), new ECFieldElement.F2m(m, ks, new LongArray(y)), false);
+ }
+ };
}
}
}
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 18409c09..49d1c2f1 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
@@ -24,6 +24,11 @@ public abstract class ECFieldElement
public abstract ECFieldElement invert();
public abstract ECFieldElement sqrt();
+ public ECFieldElement()
+ {
+
+ }
+
public int bitLength()
{
return toBigInteger().bitLength();
@@ -84,7 +89,11 @@ public abstract class ECFieldElement
return BigIntegers.asUnsignedByteArray((getFieldSize() + 7) / 8, toBigInteger());
}
- public static class Fp extends ECFieldElement
+ public static abstract class AbstractFp extends ECFieldElement
+ {
+ }
+
+ public static class Fp extends AbstractFp
{
BigInteger q, r, x;
@@ -491,6 +500,49 @@ public abstract class ECFieldElement
}
}
+ public static abstract class AbstractF2m extends ECFieldElement
+ {
+ public ECFieldElement halfTrace()
+ {
+ int m = this.getFieldSize();
+ if ((m & 1) == 0)
+ {
+ throw new IllegalStateException("Half-trace only defined for odd m");
+ }
+
+ ECFieldElement fe = this;
+ ECFieldElement ht = fe;
+ for (int i = 2; i < m; i += 2)
+ {
+ fe = fe.squarePow(2);
+ ht = ht.add(fe);
+ }
+
+ return ht;
+ }
+
+ public int trace()
+ {
+ int m = this.getFieldSize();
+ ECFieldElement fe = this;
+ ECFieldElement tr = fe;
+ for (int i = 1; i < m; ++i)
+ {
+ fe = fe.square();
+ tr = tr.add(fe);
+ }
+ if (tr.isZero())
+ {
+ return 0;
+ }
+ if (tr.isOne())
+ {
+ return 1;
+ }
+ throw new IllegalStateException("Internal error in trace calculation");
+ }
+ }
+
/**
* Class representing the Elements of the finite field
* <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
@@ -498,7 +550,7 @@ public abstract class ECFieldElement
* basis representations are supported. Gaussian normal basis (GNB)
* representation is not supported.
*/
- public static class F2m extends ECFieldElement
+ public static class F2m extends AbstractF2m
{
/**
* Indicates gaussian normal basis representation (GNB). Number chosen
@@ -533,7 +585,7 @@ public abstract class ECFieldElement
/**
* The <code>LongArray</code> holding the bits.
*/
- private LongArray x;
+ LongArray x;
/**
* Constructor for PPB.
@@ -588,23 +640,7 @@ public abstract class ECFieldElement
this.x = new LongArray(x);
}
- /**
- * 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.
- * @deprecated Use ECCurve.fromBigInteger to construct field elements
- */
- public F2m(int m, int k, BigInteger x)
- {
- // Set k1 to k, and set k2 and k3 to 0
- this(m, k, 0, 0, x);
- }
-
- private F2m(int m, int[] ks, LongArray x)
+ F2m(int m, int[] ks, LongArray x)
{
this.m = m;
this.representation = (ks.length == 1) ? TPB : PPB;
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECLookupTable.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECLookupTable.java
new file mode 100644
index 00000000..7ff5c6a4
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECLookupTable.java
@@ -0,0 +1,7 @@
+package org.bouncycastle.math.ec;
+
+public interface ECLookupTable
+{
+ int getSize();
+ ECPoint lookup(int index);
+}
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 0ea5026c..57dfa339 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
@@ -8,7 +8,7 @@ import java.util.Hashtable;
*/
public abstract class ECPoint
{
- protected static ECFieldElement[] EMPTY_ZS = new ECFieldElement[0];
+ protected final static ECFieldElement[] EMPTY_ZS = new ECFieldElement[0];
protected static ECFieldElement[] getInitialZCoords(ECCurve curve)
{
@@ -64,13 +64,21 @@ public abstract class ECPoint
this.zs = zs;
}
- protected boolean satisfiesCofactor()
+ protected abstract boolean satisfiesCurveEquation();
+
+ protected boolean satisfiesOrder()
{
- BigInteger h = curve.getCofactor();
- return h == null || h.equals(ECConstants.ONE) || !ECAlgorithms.referenceMultiply(this, h).isInfinity();
- }
+ if (ECConstants.ONE.equals(curve.getCofactor()))
+ {
+ return true;
+ }
- protected abstract boolean satisfiesCurveEquation();
+ BigInteger n = curve.getOrder();
+
+ // TODO Require order to be available for all curves
+
+ return n == null || ECAlgorithms.referenceMultiply(this, n).isInfinity();
+ }
public final ECPoint getDetachedPoint()
{
@@ -91,33 +99,6 @@ public abstract class ECPoint
}
/**
- * Normalizes this point, and then returns the affine x-coordinate.
- *
- * Note: normalization can be expensive, this method is deprecated in favour
- * of caller-controlled normalization.
- *
- * @deprecated Use getAffineXCoord(), or normalize() and getXCoord(), instead
- */
- public ECFieldElement getX()
- {
- return normalize().getXCoord();
- }
-
-
- /**
- * Normalizes this point, and then returns the affine y-coordinate.
- *
- * Note: normalization can be expensive, this method is deprecated in favour
- * of caller-controlled normalization.
- *
- * @deprecated Use getAffineYCoord(), or normalize() and getYCoord(), instead
- */
- public ECFieldElement getY()
- {
- return normalize().getYCoord();
- }
-
- /**
* Returns the affine x-coordinate after checking that this point is normalized.
*
* @return The affine x-coordinate of this point
@@ -297,28 +278,58 @@ public abstract class ECPoint
public boolean isValid()
{
+ return implIsValid(false, true);
+ }
+
+ boolean isValidPartial()
+ {
+ return implIsValid(false, false);
+ }
+
+ boolean implIsValid(final boolean decompressed, final boolean checkOrder)
+ {
if (isInfinity())
{
return true;
}
- // TODO Sanity-check the field elements
-
- ECCurve curve = getCurve();
- if (curve != null)
+ ValidityPrecompInfo validity = (ValidityPrecompInfo)getCurve().precompute(this, ValidityPrecompInfo.PRECOMP_NAME, new PreCompCallback()
{
- if (!satisfiesCurveEquation())
+ public PreCompInfo precompute(PreCompInfo existing)
{
- return false;
- }
+ ValidityPrecompInfo info = (existing instanceof ValidityPrecompInfo) ? (ValidityPrecompInfo)existing : null;
+ if (info == null)
+ {
+ info = new ValidityPrecompInfo();
+ }
- if (!satisfiesCofactor())
- {
- return false;
+ if (info.hasFailed())
+ {
+ return info;
+ }
+ if (!info.hasCurveEquationPassed())
+ {
+ if (!decompressed && !satisfiesCurveEquation())
+ {
+ info.reportFailed();
+ return info;
+ }
+ info.reportCurveEquationPassed();
+ }
+ if (checkOrder && !info.hasOrderPassed())
+ {
+ if (!satisfiesOrder())
+ {
+ info.reportFailed();
+ return info;
+ }
+ info.reportOrderPassed();
+ }
+ return info;
}
- }
+ });
- return true;
+ return !validity.hasFailed();
}
public ECPoint scaleX(ECFieldElement scale)
@@ -440,6 +451,7 @@ public abstract class ECPoint
/**
* @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
+ * @return a byte encoding.
*/
public byte[] getEncoded()
{
@@ -602,20 +614,6 @@ public abstract class ECPoint
public static class Fp extends AbstractFp
{
/**
- * Create a point which encodes without 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 Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
* Create a point that encodes with or without point compression.
*
* @param curve the curve to use
@@ -646,7 +644,7 @@ public abstract class ECPoint
protected ECPoint detach()
{
- return new ECPoint.Fp(null, this.getAffineXCoord(), this.getAffineYCoord());
+ return new ECPoint.Fp(null, this.getAffineXCoord(), this.getAffineYCoord(), false);
}
public ECFieldElement getZCoord(int index)
@@ -1423,6 +1421,46 @@ public abstract class ECPoint
return lhs.equals(rhs);
}
+ protected boolean satisfiesOrder()
+ {
+ BigInteger cofactor = curve.getCofactor();
+ if (ECConstants.TWO.equals(cofactor))
+ {
+ /*
+ * Check that the trace of (X + A) is 0, then there exists a solution to L^2 + L = X + A,
+ * and so a halving is possible, so this point is the double of another.
+ */
+ ECPoint N = this.normalize();
+ ECFieldElement X = N.getAffineXCoord();
+ ECFieldElement rhs = X.add(curve.getA());
+ return ((ECFieldElement.AbstractF2m)rhs).trace() == 0;
+ }
+ if (ECConstants.FOUR.equals(cofactor))
+ {
+ /*
+ * Solve L^2 + L = X + A to find the half of this point, if it exists (fail if not).
+ * Generate both possibilities for the square of the half-point's x-coordinate (w),
+ * and check if Tr(w + A) == 0 for at least one; then a second halving is possible
+ * (see comments for cofactor 2 above), so this point is four times another.
+ *
+ * Note: Tr(x^2) == Tr(x).
+ */
+ ECPoint N = this.normalize();
+ ECFieldElement X = N.getAffineXCoord();
+ ECFieldElement lambda = ((ECCurve.AbstractF2m)curve).solveQuadraticEquation(X.add(curve.getA()));
+ if (lambda == null)
+ {
+ return false;
+ }
+ ECFieldElement w = X.multiply(lambda).add(N.getAffineYCoord());
+ ECFieldElement t = w.add(curve.getA());
+ return ((ECFieldElement.AbstractF2m)t).trace() == 0
+ || ((ECFieldElement.AbstractF2m)(t.add(X))).trace() == 0;
+ }
+
+ return super.satisfiesOrder();
+ }
+
public ECPoint scaleX(ECFieldElement scale)
{
if (this.isInfinity())
@@ -1580,18 +1618,6 @@ public abstract class ECPoint
* @param curve base curve
* @param x x point
* @param y y point
- *
- * @deprecated Use ECCurve.createPoint to construct points
- */
- public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * @param curve base curve
- * @param x x point
- * @param y y point
* @param withCompression true if encode with point compression.
*
* @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
@@ -1633,7 +1659,7 @@ public abstract class ECPoint
protected ECPoint detach()
{
- return new ECPoint.F2m(null, this.getAffineXCoord(), this.getAffineYCoord()); // earlier JDK
+ return new ECPoint.F2m(null, this.getAffineXCoord(), this.getAffineYCoord(), false); // earlier JDK
}
public ECFieldElement getYCoord()
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java
index c91de7b1..f3dad929 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java
@@ -2,6 +2,8 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
+import org.bouncycastle.math.raw.Nat;
+
public class FixedPointCombMultiplier extends AbstractECMultiplier
{
protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
@@ -20,38 +22,35 @@ public class FixedPointCombMultiplier extends AbstractECMultiplier
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();
+ FixedPointPreCompInfo info = FixedPointUtil.precompute(p);
+ ECLookupTable lookupTable = info.getLookupTable();
int width = info.getWidth();
int d = (size + width - 1) / width;
ECPoint R = c.getInfinity();
- int top = d * width - 1;
+ int fullComb = d * width;
+ int[] K = Nat.fromBigInteger(fullComb, k);
+
+ int top = fullComb - 1;
for (int i = 0; i < d; ++i)
{
- int index = 0;
+ int secretIndex = 0;
for (int j = top - i; j >= 0; j -= d)
{
- index <<= 1;
- if (k.testBit(j))
- {
- index |= 1;
- }
+ int secretBit = K[j >>> 5] >>> (j & 0x1F);
+ secretIndex ^= secretBit >>> 1;
+ secretIndex <<= 1;
+ secretIndex ^= secretBit;
}
- R = R.twicePlus(lookupTable[index]);
+ ECPoint add = lookupTable.lookup(secretIndex);
+
+ R = R.twicePlus(add);
}
return R.add(info.getOffset());
}
-
- 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
index 31f5d101..93889e1f 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java
@@ -8,10 +8,9 @@ public class FixedPointPreCompInfo implements PreCompInfo
protected ECPoint offset = null;
/**
- * Array holding the precomputed <code>ECPoint</code>s used for a fixed
- * point multiplication.
+ * Lookup table for the precomputed {@link ECPoint}s used for a fixed point multiplication.
*/
- protected ECPoint[] preComp = null;
+ protected ECLookupTable lookupTable = null;
/**
* The width used for the precomputation. If a larger width precomputation
@@ -20,24 +19,24 @@ public class FixedPointPreCompInfo implements PreCompInfo
*/
protected int width = -1;
- public ECPoint getOffset()
+ public ECLookupTable getLookupTable()
{
- return offset;
+ return lookupTable;
}
- public void setOffset(ECPoint offset)
+ public void setLookupTable(ECLookupTable lookupTable)
{
- this.offset = offset;
+ this.lookupTable = lookupTable;
}
- public ECPoint[] getPreComp()
+ public ECPoint getOffset()
{
- return preComp;
+ return offset;
}
- public void setPreComp(ECPoint[] preComp)
+ public void setOffset(ECPoint offset)
{
- this.preComp = preComp;
+ this.offset = offset;
}
public int getWidth()
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java
index 93b435c5..6b81d236 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java
@@ -14,62 +14,74 @@ public class FixedPointUtil
public static FixedPointPreCompInfo getFixedPointPreCompInfo(PreCompInfo preCompInfo)
{
- if ((preCompInfo != null) && (preCompInfo instanceof FixedPointPreCompInfo))
- {
- return (FixedPointPreCompInfo)preCompInfo;
- }
-
- return new FixedPointPreCompInfo();
+ return (preCompInfo instanceof FixedPointPreCompInfo) ? (FixedPointPreCompInfo)preCompInfo : null;
}
- public static FixedPointPreCompInfo precompute(ECPoint p, int minWidth)
+ public static FixedPointPreCompInfo precompute(final ECPoint p)
{
- ECCurve c = p.getCurve();
-
- int n = 1 << minWidth;
- FixedPointPreCompInfo info = getFixedPointPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME));
- ECPoint[] lookupTable = info.getPreComp();
+ final ECCurve c = p.getCurve();
- if (lookupTable == null || lookupTable.length < n)
+ return (FixedPointPreCompInfo)c.precompute(p, PRECOMP_NAME, new PreCompCallback()
{
- int bits = getCombSize(c);
- int d = (bits + minWidth - 1) / minWidth;
-
- ECPoint[] pow2Table = new ECPoint[minWidth + 1];
- pow2Table[0] = p;
- for (int i = 1; i < minWidth; ++i)
+ public PreCompInfo precompute(PreCompInfo existing)
{
- pow2Table[i] = pow2Table[i - 1].timesPow2(d);
- }
+ FixedPointPreCompInfo existingFP = (existing instanceof FixedPointPreCompInfo) ? (FixedPointPreCompInfo)existing : null;
- // This will be the 'offset' value
- pow2Table[minWidth] = pow2Table[0].subtract(pow2Table[1]);
+ int bits = getCombSize(c);
+ int minWidth = bits > 250 ? 6 : 5;
+ int n = 1 << minWidth;
- c.normalizeAll(pow2Table);
+ if (checkExisting(existingFP, n))
+ {
+ return existingFP;
+ }
- lookupTable = new ECPoint[n];
- lookupTable[0] = pow2Table[0];
+ int d = (bits + minWidth - 1) / minWidth;
- for (int bit = minWidth - 1; bit >= 0; --bit)
- {
- ECPoint pow2 = pow2Table[bit];
+ ECPoint[] pow2Table = new ECPoint[minWidth + 1];
+ pow2Table[0] = p;
+ for (int i = 1; i < minWidth; ++i)
+ {
+ pow2Table[i] = pow2Table[i - 1].timesPow2(d);
+ }
- int step = 1 << bit;
- for (int i = step; i < n; i += (step << 1))
+ // This will be the 'offset' value
+ pow2Table[minWidth] = pow2Table[0].subtract(pow2Table[1]);
+
+ c.normalizeAll(pow2Table);
+
+ ECPoint[] lookupTable = new ECPoint[n];
+ lookupTable[0] = pow2Table[0];
+
+ for (int bit = minWidth - 1; bit >= 0; --bit)
{
- lookupTable[i] = lookupTable[i - step].add(pow2);
+ 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);
+ c.normalizeAll(lookupTable);
- info.setOffset(pow2Table[minWidth]);
- info.setPreComp(lookupTable);
- info.setWidth(minWidth);
+ FixedPointPreCompInfo result = new FixedPointPreCompInfo();
+ result.setLookupTable(c.createCacheSafeLookupTable(lookupTable, 0, lookupTable.length));
+ result.setOffset(pow2Table[minWidth]);
+ result.setWidth(minWidth);
+ return result;
+ }
- c.setPreCompInfo(p, PRECOMP_NAME, info);
- }
+ private boolean checkExisting(FixedPointPreCompInfo existingFP, int n)
+ {
+ return existingFP != null && checkTable(existingFP.getLookupTable(), n);
+ }
- return info;
+ private boolean checkTable(ECLookupTable table, int n)
+ {
+ return table != null && table.getSize() >= n;
+ }
+ });
}
}
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 b963118a..b9a1535f 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java
@@ -373,6 +373,11 @@ class LongArray implements Cloneable
}
}
+ void copyTo(long[] z, int zOff)
+ {
+ System.arraycopy(m_ints, 0, z, zOff, m_ints.length);
+ }
+
public boolean isOne()
{
long[] a = m_ints;
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompCallback.java b/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompCallback.java
new file mode 100644
index 00000000..5cbd8d02
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompCallback.java
@@ -0,0 +1,6 @@
+package org.bouncycastle.math.ec;
+
+public interface PreCompCallback
+{
+ PreCompInfo precompute(PreCompInfo existing);
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ValidityPrecompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ValidityPrecompInfo.java
new file mode 100644
index 00000000..d3a3ce31
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ValidityPrecompInfo.java
@@ -0,0 +1,40 @@
+package org.bouncycastle.math.ec;
+
+class ValidityPrecompInfo implements PreCompInfo
+{
+ static final String PRECOMP_NAME = "bc_validity";
+
+ private boolean failed = false;
+ private boolean curveEquationPassed = false;
+ private boolean orderPassed = false;
+
+ boolean hasFailed()
+ {
+ return failed;
+ }
+
+ void reportFailed()
+ {
+ failed = true;
+ }
+
+ boolean hasCurveEquationPassed()
+ {
+ return curveEquationPassed;
+ }
+
+ void reportCurveEquationPassed()
+ {
+ curveEquationPassed = true;
+ }
+
+ boolean hasOrderPassed()
+ {
+ return orderPassed;
+ }
+
+ void reportOrderPassed()
+ {
+ orderPassed = true;
+ }
+}
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 301b5aee..f383308a 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
@@ -304,12 +304,7 @@ public abstract class WNafUtil
public static WNafPreCompInfo getWNafPreCompInfo(PreCompInfo preCompInfo)
{
- if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
- {
- return (WNafPreCompInfo)preCompInfo;
- }
-
- return new WNafPreCompInfo();
+ return (preCompInfo instanceof WNafPreCompInfo) ? (WNafPreCompInfo)preCompInfo : null;
}
/**
@@ -343,178 +338,214 @@ public abstract class WNafUtil
return w + 2;
}
- public static ECPoint mapPointWithPrecomp(ECPoint p, int width, boolean includeNegated,
- ECPointMap pointMap)
+ public static ECPoint mapPointWithPrecomp(ECPoint p, final int width, final boolean includeNegated,
+ final ECPointMap pointMap)
{
- ECCurve c = p.getCurve();
- WNafPreCompInfo wnafPreCompP = precompute(p, width, includeNegated);
+ final ECCurve c = p.getCurve();
+ final 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)
+ c.precompute(q, PRECOMP_NAME, new PreCompCallback()
{
- ECPoint twiceQ = pointMap.map(twiceP);
- wnafPreCompQ.setTwice(twiceQ);
- }
+ public PreCompInfo precompute(PreCompInfo existing)
+ {
+ WNafPreCompInfo result = new WNafPreCompInfo();
- 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);
+ ECPoint twiceP = wnafPreCompP.getTwice();
+ if (twiceP != null)
+ {
+ ECPoint twiceQ = pointMap.map(twiceP);
+ result.setTwice(twiceQ);
+ }
- if (includeNegated)
- {
- ECPoint[] preCompNegQ = new ECPoint[preCompQ.length];
- for (int i = 0; i < preCompNegQ.length; ++i)
- {
- preCompNegQ[i] = preCompQ[i].negate();
- }
- wnafPreCompQ.setPreCompNeg(preCompNegQ);
- }
+ ECPoint[] preCompP = wnafPreCompP.getPreComp();
+ ECPoint[] preCompQ = new ECPoint[preCompP.length];
+ for (int i = 0; i < preCompP.length; ++i)
+ {
+ preCompQ[i] = pointMap.map(preCompP[i]);
+ }
+ result.setPreComp(preCompQ);
+
+ if (includeNegated)
+ {
+ ECPoint[] preCompNegQ = new ECPoint[preCompQ.length];
+ for (int i = 0; i < preCompNegQ.length; ++i)
+ {
+ preCompNegQ[i] = preCompQ[i].negate();
+ }
+ result.setPreCompNeg(preCompNegQ);
+ }
- c.setPreCompInfo(q, PRECOMP_NAME, wnafPreCompQ);
+ return result;
+ }
+ });
return q;
}
- public static WNafPreCompInfo precompute(ECPoint p, int width, boolean includeNegated)
+ public static WNafPreCompInfo precompute(final ECPoint p, final int width, final boolean includeNegated)
{
- ECCurve c = p.getCurve();
- WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME));
+ final ECCurve c = p.getCurve();
- int iniPreCompLen = 0, reqPreCompLen = 1 << Math.max(0, width - 2);
-
- ECPoint[] preComp = wnafPreCompInfo.getPreComp();
- if (preComp == null)
- {
- preComp = EMPTY_POINTS;
- }
- else
+ return (WNafPreCompInfo)c.precompute(p, PRECOMP_NAME, new PreCompCallback()
{
- iniPreCompLen = preComp.length;
- }
+ public PreCompInfo precompute(PreCompInfo existing)
+ {
+ WNafPreCompInfo existingWNaf = (existing instanceof WNafPreCompInfo) ? (WNafPreCompInfo)existing : null;
- if (iniPreCompLen < reqPreCompLen)
- {
- preComp = resizeTable(preComp, reqPreCompLen);
+ int reqPreCompLen = 1 << Math.max(0, width - 2);
- if (reqPreCompLen == 1)
- {
- preComp[0] = p.normalize();
- }
- else
- {
- int curPreCompLen = iniPreCompLen;
- if (curPreCompLen == 0)
+ if (checkExisting(existingWNaf, reqPreCompLen, includeNegated))
{
- preComp[0] = p;
- curPreCompLen = 1;
+ return existingWNaf;
}
- ECFieldElement iso = null;
+ ECPoint[] preComp = null, preCompNeg = null;
+ ECPoint twiceP = null;
+
+ if (existingWNaf != null)
+ {
+ preComp = existingWNaf.getPreComp();
+ preCompNeg = existingWNaf.getPreCompNeg();
+ twiceP = existingWNaf.getTwice();
+ }
- if (reqPreCompLen == 2)
+ int iniPreCompLen = 0;
+ if (preComp == null)
{
- preComp[1] = p.threeTimes();
+ preComp = EMPTY_POINTS;
}
else
{
- ECPoint twiceP = wnafPreCompInfo.getTwice(), last = preComp[curPreCompLen - 1];
- if (twiceP == null)
- {
- twiceP = preComp[0].twice();
- wnafPreCompInfo.setTwice(twiceP);
+ iniPreCompLen = preComp.length;
+ }
- /*
- * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism
- * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This
- * also requires scaling the initial point's X, Y coordinates, and reversing the
- * isomorphism as part of the subsequent normalization.
- *
- * NOTE: The correctness of this optimization depends on:
- * 1) additions do not use the curve's A, B coefficients.
- * 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
- */
- if (!twiceP.isInfinity() && ECAlgorithms.isFpCurve(c) && c.getFieldSize() >= 64)
+ if (iniPreCompLen < reqPreCompLen)
+ {
+ preComp = resizeTable(preComp, reqPreCompLen);
+
+ if (reqPreCompLen == 1)
+ {
+ preComp[0] = p.normalize();
+ }
+ else
+ {
+ int curPreCompLen = iniPreCompLen;
+ if (curPreCompLen == 0)
{
- switch (c.getCoordinateSystem())
- {
- case ECCurve.COORD_JACOBIAN:
- case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
- case ECCurve.COORD_JACOBIAN_MODIFIED:
- {
- iso = twiceP.getZCoord(0);
- twiceP = c.createPoint(twiceP.getXCoord().toBigInteger(), twiceP.getYCoord()
- .toBigInteger());
+ preComp[0] = p;
+ curPreCompLen = 1;
+ }
- ECFieldElement iso2 = iso.square(), iso3 = iso2.multiply(iso);
- last = last.scaleX(iso2).scaleY(iso3);
+ ECFieldElement iso = null;
- if (iniPreCompLen == 0)
+ if (reqPreCompLen == 2)
+ {
+ preComp[1] = p.threeTimes();
+ }
+ else
+ {
+ ECPoint isoTwiceP = twiceP, last = preComp[curPreCompLen - 1];
+ if (isoTwiceP == null)
+ {
+ isoTwiceP = preComp[0].twice();
+ twiceP = isoTwiceP;
+
+ /*
+ * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism
+ * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This
+ * also requires scaling the initial point's X, Y coordinates, and reversing the
+ * isomorphism as part of the subsequent normalization.
+ *
+ * NOTE: The correctness of this optimization depends on:
+ * 1) additions do not use the curve's A, B coefficients.
+ * 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
+ */
+ if (!twiceP.isInfinity() && ECAlgorithms.isFpCurve(c) && c.getFieldSize() >= 64)
{
- preComp[0] = last;
+ switch (c.getCoordinateSystem())
+ {
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ iso = twiceP.getZCoord(0);
+ isoTwiceP = c.createPoint(twiceP.getXCoord().toBigInteger(), twiceP.getYCoord()
+ .toBigInteger());
+
+ ECFieldElement iso2 = iso.square(), iso3 = iso2.multiply(iso);
+ last = last.scaleX(iso2).scaleY(iso3);
+
+ if (iniPreCompLen == 0)
+ {
+ preComp[0] = last;
+ }
+ break;
+ }
+ }
}
- break;
}
+
+ while (curPreCompLen < reqPreCompLen)
+ {
+ /*
+ * Compute the new ECPoints for the precomputation array. The values 1, 3,
+ * 5, ..., 2^(width-1)-1 times p are computed
+ */
+ preComp[curPreCompLen++] = last = last.add(isoTwiceP);
}
}
- }
- while (curPreCompLen < reqPreCompLen)
- {
/*
- * Compute the new ECPoints for the precomputation array. The values 1, 3,
- * 5, ..., 2^(width-1)-1 times p are computed
+ * Having oft-used operands in affine form makes operations faster.
*/
- preComp[curPreCompLen++] = last = last.add(twiceP);
+ c.normalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso);
}
}
- /*
- * Having oft-used operands in affine form makes operations faster.
- */
- c.normalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso);
- }
- }
+ if (includeNegated)
+ {
+ int pos;
+ if (preCompNeg == null)
+ {
+ pos = 0;
+ preCompNeg = new ECPoint[reqPreCompLen];
+ }
+ else
+ {
+ pos = preCompNeg.length;
+ if (pos < reqPreCompLen)
+ {
+ preCompNeg = resizeTable(preCompNeg, reqPreCompLen);
+ }
+ }
- wnafPreCompInfo.setPreComp(preComp);
+ while (pos < reqPreCompLen)
+ {
+ preCompNeg[pos] = preComp[pos].negate();
+ ++pos;
+ }
+ }
- if (includeNegated)
- {
- ECPoint[] preCompNeg = wnafPreCompInfo.getPreCompNeg();
-
- int pos;
- if (preCompNeg == null)
- {
- pos = 0;
- preCompNeg = new ECPoint[reqPreCompLen];
+ WNafPreCompInfo result = new WNafPreCompInfo();
+ result.setPreComp(preComp);
+ result.setPreCompNeg(preCompNeg);
+ result.setTwice(twiceP);
+ return result;
}
- else
+
+ private boolean checkExisting(WNafPreCompInfo existingWNaf, int reqPreCompLen, boolean includeNegated)
{
- pos = preCompNeg.length;
- if (pos < reqPreCompLen)
- {
- preCompNeg = resizeTable(preCompNeg, reqPreCompLen);
- }
+ return existingWNaf != null
+ && checkTable(existingWNaf.getPreComp(), reqPreCompLen)
+ && (!includeNegated || checkTable(existingWNaf.getPreCompNeg(), reqPreCompLen));
}
- while (pos < reqPreCompLen)
+ private boolean checkTable(ECPoint[] table, int reqLen)
{
- preCompNeg[pos] = preComp[pos].negate();
- ++pos;
+ return table != null && table.length >= reqLen;
}
-
- wnafPreCompInfo.setPreCompNeg(preCompNeg);
- }
-
- c.setPreCompInfo(p, PRECOMP_NAME, wnafPreCompInfo);
-
- return wnafPreCompInfo;
+ });
}
private static byte[] trim(byte[] a, int length)
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 7974e1d3..0438e1db 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
@@ -36,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, PRECOMP_NAME), a, mu);
+ return multiplyWTnaf(p, rho, a, mu);
}
/**
@@ -49,8 +49,7 @@ public class WTauNafMultiplier extends AbstractECMultiplier
* <code>[&tau;]</code>-adic NAF.
* @return <code>p</code> multiplied by <code>&lambda;</code>.
*/
- private ECPoint.AbstractF2m multiplyWTnaf(ECPoint.AbstractF2m p, ZTauElement lambda,
- PreCompInfo preCompInfo, byte a, byte mu)
+ private ECPoint.AbstractF2m multiplyWTnaf(ECPoint.AbstractF2m p, ZTauElement lambda, byte a, byte mu)
{
ZTauElement[] alpha = (a == 0) ? Tnaf.alpha0 : Tnaf.alpha1;
@@ -59,7 +58,7 @@ public class WTauNafMultiplier extends AbstractECMultiplier
byte[]u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH,
BigInteger.valueOf(Tnaf.POW_2_WIDTH), tw, alpha);
- return multiplyFromWTnaf(p, u, preCompInfo);
+ return multiplyFromWTnaf(p, u);
}
/**
@@ -71,24 +70,27 @@ public class WTauNafMultiplier extends AbstractECMultiplier
* @param u The the WTNAF of <code>&lambda;</code>..
* @return <code>&lambda; * p</code>
*/
- private static ECPoint.AbstractF2m multiplyFromWTnaf(ECPoint.AbstractF2m p, byte[] u, PreCompInfo preCompInfo)
+ private static ECPoint.AbstractF2m multiplyFromWTnaf(final ECPoint.AbstractF2m p, byte[] u)
{
ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m)p.getCurve();
- byte a = curve.getA().toBigInteger().byteValue();
+ final byte a = curve.getA().toBigInteger().byteValue();
- ECPoint.AbstractF2m[] pu;
- if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo))
+ WTauNafPreCompInfo preCompInfo = (WTauNafPreCompInfo)curve.precompute(p, PRECOMP_NAME, new PreCompCallback()
{
- pu = Tnaf.getPreComp(p, a);
+ public PreCompInfo precompute(PreCompInfo existing)
+ {
+ if (existing instanceof WTauNafPreCompInfo)
+ {
+ return existing;
+ }
+
+ WTauNafPreCompInfo result = new WTauNafPreCompInfo();
+ result.setPreComp(Tnaf.getPreComp(p, a));
+ return result;
+ }
+ });
- WTauNafPreCompInfo pre = new WTauNafPreCompInfo();
- pre.setPreComp(pu);
- curve.setPreCompInfo(p, PRECOMP_NAME, pre);
- }
- else
- {
- pu = ((WTauNafPreCompInfo)preCompInfo).getPreComp();
- }
+ ECPoint.AbstractF2m[] pu = preCompInfo.getPreComp();
// TODO Include negations in precomp (optionally) and use from here
ECPoint.AbstractF2m[] puNeg = new ECPoint.AbstractF2m[pu.length];
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
index b46cba6a..f160ab31 100644
--- 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
@@ -5,7 +5,9 @@ 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.ECLookupTable;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat192;
import org.bouncycastle.util.encoders.Hex;
public class SecP192K1Curve extends ECCurve.AbstractFp
@@ -76,4 +78,49 @@ public class SecP192K1Curve extends ECCurve.AbstractFp
{
return infinity;
}
+
+ public ECLookupTable createCacheSafeLookupTable(ECPoint[] points, int off, final int len)
+ {
+ final int FE_INTS = 6;
+
+ final int[] table = new int[len * FE_INTS * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ Nat192.copy(((SecP192K1FieldElement)p.getRawXCoord()).x, 0, table, pos); pos += FE_INTS;
+ Nat192.copy(((SecP192K1FieldElement)p.getRawYCoord()).x, 0, table, pos); pos += FE_INTS;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ int[] x = Nat192.create(), y = Nat192.create();
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_INTS; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_INTS + j] & MASK;
+ }
+
+ pos += (FE_INTS * 2);
+ }
+
+ return createRawPoint(new SecP192K1FieldElement(x), new SecP192K1FieldElement(y), false);
+ }
+ };
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java
index 642c44cd..39e62afa 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP192K1FieldElement.java
@@ -7,7 +7,7 @@ import org.bouncycastle.math.raw.Mod;
import org.bouncycastle.math.raw.Nat192;
import org.bouncycastle.util.Arrays;
-public class SecP192K1FieldElement extends ECFieldElement
+public class SecP192K1FieldElement extends ECFieldElement.AbstractFp
{
public static final BigInteger Q = SecP192K1Curve.q;
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
index be67100a..a43a5966 100644
--- 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
@@ -4,7 +4,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECLookupTable;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat192;
import org.bouncycastle.util.encoders.Hex;
public class SecP192R1Curve extends ECCurve.AbstractFp
@@ -77,4 +79,49 @@ public class SecP192R1Curve extends ECCurve.AbstractFp
{
return infinity;
}
+
+ public ECLookupTable createCacheSafeLookupTable(ECPoint[] points, int off, final int len)
+ {
+ final int FE_INTS = 6;
+
+ final int[] table = new int[len * FE_INTS * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ Nat192.copy(((SecP192R1FieldElement)p.getRawXCoord()).x, 0, table, pos); pos += FE_INTS;
+ Nat192.copy(((SecP192R1FieldElement)p.getRawYCoord()).x, 0, table, pos); pos += FE_INTS;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ int[] x = Nat192.create(), y = Nat192.create();
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_INTS; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_INTS + j] & MASK;
+ }
+
+ pos += (FE_INTS * 2);
+ }
+
+ return createRawPoint(new SecP192R1FieldElement(x), new SecP192R1FieldElement(y), false);
+ }
+ };
+ }
}
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
index 68c8080d..15fdcd63 100644
--- 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
@@ -7,7 +7,7 @@ import org.bouncycastle.math.raw.Mod;
import org.bouncycastle.math.raw.Nat192;
import org.bouncycastle.util.Arrays;
-public class SecP192R1FieldElement extends ECFieldElement
+public class SecP192R1FieldElement extends ECFieldElement.AbstractFp
{
public static final BigInteger Q = SecP192R1Curve.q;
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
index ad733da6..6b28be79 100644
--- 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
@@ -5,7 +5,9 @@ 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.ECLookupTable;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat224;
import org.bouncycastle.util.encoders.Hex;
public class SecP224K1Curve extends ECCurve.AbstractFp
@@ -75,4 +77,49 @@ public class SecP224K1Curve extends ECCurve.AbstractFp
{
return infinity;
}
+
+ public ECLookupTable createCacheSafeLookupTable(ECPoint[] points, int off, final int len)
+ {
+ final int FE_INTS = 7;
+
+ final int[] table = new int[len * FE_INTS * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ Nat224.copy(((SecP224K1FieldElement)p.getRawXCoord()).x, 0, table, pos); pos += FE_INTS;
+ Nat224.copy(((SecP224K1FieldElement)p.getRawYCoord()).x, 0, table, pos); pos += FE_INTS;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ int[] x = Nat224.create(), y = Nat224.create();
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_INTS; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_INTS + j] & MASK;
+ }
+
+ pos += (FE_INTS * 2);
+ }
+
+ return createRawPoint(new SecP224K1FieldElement(x), new SecP224K1FieldElement(y), false);
+ }
+ };
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java
index 8285a4e9..2093a061 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP224K1FieldElement.java
@@ -7,7 +7,7 @@ import org.bouncycastle.math.raw.Mod;
import org.bouncycastle.math.raw.Nat224;
import org.bouncycastle.util.Arrays;
-public class SecP224K1FieldElement extends ECFieldElement
+public class SecP224K1FieldElement extends ECFieldElement.AbstractFp
{
public static final BigInteger Q = SecP224K1Curve.q;
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
index c8443299..febb323c 100644
--- 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
@@ -4,7 +4,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECLookupTable;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat224;
import org.bouncycastle.util.encoders.Hex;
public class SecP224R1Curve extends ECCurve.AbstractFp
@@ -77,4 +79,49 @@ public class SecP224R1Curve extends ECCurve.AbstractFp
{
return infinity;
}
+
+ public ECLookupTable createCacheSafeLookupTable(ECPoint[] points, int off, final int len)
+ {
+ final int FE_INTS = 7;
+
+ final int[] table = new int[len * FE_INTS * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ Nat224.copy(((SecP224R1FieldElement)p.getRawXCoord()).x, 0, table, pos); pos += FE_INTS;
+ Nat224.copy(((SecP224R1FieldElement)p.getRawYCoord()).x, 0, table, pos); pos += FE_INTS;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ int[] x = Nat224.create(), y = Nat224.create();
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_INTS; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_INTS + j] & MASK;
+ }
+
+ pos += (FE_INTS * 2);
+ }
+
+ return createRawPoint(new SecP224R1FieldElement(x), new SecP224R1FieldElement(y), false);
+ }
+ };
+ }
}
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
index 4a28f3d0..ed2334a7 100644
--- 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
@@ -8,7 +8,7 @@ import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.math.raw.Nat224;
import org.bouncycastle.util.Arrays;
-public class SecP224R1FieldElement extends ECFieldElement
+public class SecP224R1FieldElement extends ECFieldElement.AbstractFp
{
public static final BigInteger Q = SecP224R1Curve.q;
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
index 9b885764..6235381e 100644
--- 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
@@ -5,7 +5,9 @@ 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.ECLookupTable;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat256;
import org.bouncycastle.util.encoders.Hex;
public class SecP256K1Curve extends ECCurve.AbstractFp
@@ -75,4 +77,49 @@ public class SecP256K1Curve extends ECCurve.AbstractFp
{
return infinity;
}
+
+ public ECLookupTable createCacheSafeLookupTable(ECPoint[] points, int off, final int len)
+ {
+ final int FE_INTS = 8;
+
+ final int[] table = new int[len * FE_INTS * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ Nat256.copy(((SecP256K1FieldElement)p.getRawXCoord()).x, 0, table, pos); pos += FE_INTS;
+ Nat256.copy(((SecP256K1FieldElement)p.getRawYCoord()).x, 0, table, pos); pos += FE_INTS;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ int[] x = Nat256.create(), y = Nat256.create();
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_INTS; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_INTS + j] & MASK;
+ }
+
+ pos += (FE_INTS * 2);
+ }
+
+ return createRawPoint(new SecP256K1FieldElement(x), new SecP256K1FieldElement(y), false);
+ }
+ };
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java
index 467b17f5..30bca2e3 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256K1FieldElement.java
@@ -7,7 +7,7 @@ import org.bouncycastle.math.raw.Mod;
import org.bouncycastle.math.raw.Nat256;
import org.bouncycastle.util.Arrays;
-public class SecP256K1FieldElement extends ECFieldElement
+public class SecP256K1FieldElement extends ECFieldElement.AbstractFp
{
public static final BigInteger Q = SecP256K1Curve.q;
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
index 5ff6a38d..7d7b51d5 100644
--- 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
@@ -4,7 +4,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECLookupTable;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat256;
import org.bouncycastle.util.encoders.Hex;
public class SecP256R1Curve extends ECCurve.AbstractFp
@@ -77,4 +79,49 @@ public class SecP256R1Curve extends ECCurve.AbstractFp
{
return infinity;
}
+
+ public ECLookupTable createCacheSafeLookupTable(ECPoint[] points, int off, final int len)
+ {
+ final int FE_INTS = 8;
+
+ final int[] table = new int[len * FE_INTS * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ Nat256.copy(((SecP256R1FieldElement)p.getRawXCoord()).x, 0, table, pos); pos += FE_INTS;
+ Nat256.copy(((SecP256R1FieldElement)p.getRawYCoord()).x, 0, table, pos); pos += FE_INTS;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ int[] x = Nat256.create(), y = Nat256.create();
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_INTS; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_INTS + j] & MASK;
+ }
+
+ pos += (FE_INTS * 2);
+ }
+
+ return createRawPoint(new SecP256R1FieldElement(x), new SecP256R1FieldElement(y), false);
+ }
+ };
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java
index 1e04f4b9..cea1af78 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java
@@ -16,7 +16,7 @@ public class SecP256R1Field
0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0x00000001, 0xFFFFFFFE,
0x00000002, 0xFFFFFFFE };
private static final int P7 = 0xFFFFFFFF;
- private static final int PExt15 = 0xFFFFFFFF;
+ private static final int PExt15s1 = 0xFFFFFFFE >>> 1;
public static void add(int[] x, int[] y, int[] z)
{
@@ -30,7 +30,7 @@ public class SecP256R1Field
public static void addExt(int[] xx, int[] yy, int[] zz)
{
int c = Nat.add(16, xx, yy, zz);
- if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt)))
+ if (c != 0 || ((zz[15] >>> 1) >= PExt15s1 && Nat.gte(16, zz, PExt)))
{
Nat.subFrom(16, PExt, zz);
}
@@ -78,7 +78,7 @@ public class SecP256R1Field
public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
{
int c = Nat256.mulAddTo(x, y, zz);
- if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt)))
+ if (c != 0 || ((zz[15] >>> 1) >= PExt15s1 && Nat.gte(16, zz, PExt)))
{
Nat.subFrom(16, PExt, zz);
}
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
index be250d10..6be46f24 100644
--- 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
@@ -7,7 +7,7 @@ import org.bouncycastle.math.raw.Mod;
import org.bouncycastle.math.raw.Nat256;
import org.bouncycastle.util.Arrays;
-public class SecP256R1FieldElement extends ECFieldElement
+public class SecP256R1FieldElement extends ECFieldElement.AbstractFp
{
public static final BigInteger Q = SecP256R1Curve.q;
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
index 27cbcdb2..7a5603d2 100644
--- 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
@@ -4,7 +4,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECLookupTable;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.util.encoders.Hex;
public class SecP384R1Curve extends ECCurve.AbstractFp
@@ -77,4 +79,49 @@ public class SecP384R1Curve extends ECCurve.AbstractFp
{
return infinity;
}
+
+ public ECLookupTable createCacheSafeLookupTable(ECPoint[] points, int off, final int len)
+ {
+ final int FE_INTS = 12;
+
+ final int[] table = new int[len * FE_INTS * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ Nat.copy(FE_INTS, ((SecP384R1FieldElement)p.getRawXCoord()).x, 0, table, pos); pos += FE_INTS;
+ Nat.copy(FE_INTS, ((SecP384R1FieldElement)p.getRawYCoord()).x, 0, table, pos); pos += FE_INTS;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ int[] x = Nat.create(FE_INTS), y = Nat.create(FE_INTS);
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_INTS; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_INTS + j] & MASK;
+ }
+
+ pos += (FE_INTS * 2);
+ }
+
+ return createRawPoint(new SecP384R1FieldElement(x), new SecP384R1FieldElement(y), false);
+ }
+ };
+ }
}
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
index 24e585d8..3116b443 100644
--- 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
@@ -7,7 +7,7 @@ import org.bouncycastle.math.raw.Mod;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.util.Arrays;
-public class SecP384R1FieldElement extends ECFieldElement
+public class SecP384R1FieldElement extends ECFieldElement.AbstractFp
{
public static final BigInteger Q = SecP384R1Curve.q;
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
index 16691b10..267defcf 100644
--- 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
@@ -4,7 +4,9 @@ import java.math.BigInteger;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECLookupTable;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.util.encoders.Hex;
public class SecP521R1Curve extends ECCurve.AbstractFp
@@ -77,4 +79,49 @@ public class SecP521R1Curve extends ECCurve.AbstractFp
{
return infinity;
}
+
+ public ECLookupTable createCacheSafeLookupTable(ECPoint[] points, int off, final int len)
+ {
+ final int FE_INTS = 17;
+
+ final int[] table = new int[len * FE_INTS * 2];
+ {
+ int pos = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ ECPoint p = points[off + i];
+ Nat.copy(FE_INTS, ((SecP521R1FieldElement)p.getRawXCoord()).x, 0, table, pos); pos += FE_INTS;
+ Nat.copy(FE_INTS, ((SecP521R1FieldElement)p.getRawYCoord()).x, 0, table, pos); pos += FE_INTS;
+ }
+ }
+
+ return new ECLookupTable()
+ {
+ public int getSize()
+ {
+ return len;
+ }
+
+ public ECPoint lookup(int index)
+ {
+ int[] x = Nat.create(FE_INTS), y = Nat.create(FE_INTS);
+ int pos = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int MASK = ((i ^ index) - 1) >> 31;
+
+ for (int j = 0; j < FE_INTS; ++j)
+ {
+ x[j] ^= table[pos + j] & MASK;
+ y[j] ^= table[pos + FE_INTS + j] & MASK;
+ }
+
+ pos += (FE_INTS * 2);
+ }
+
+ return createRawPoint(new SecP521R1FieldElement(x), new SecP521R1FieldElement(y), false);
+ }
+ };
+ }
}
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
index ce9b6392..5cf30fc0 100644
--- 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
@@ -7,7 +7,7 @@ import org.bouncycastle.math.raw.Mod;
import org.bouncycastle.math.raw.Nat;
import org.bouncycastle.util.Arrays;
-public class SecP521R1FieldElement extends ECFieldElement
+public class SecP521R1FieldElement extends ECFieldElement.AbstractFp
{
public static final BigInteger Q = SecP521R1Curve.q;
diff --git a/bcprov/src/main/java/org/bouncycastle/math/package.html b/bcprov/src/main/java/org/bouncycastle/math/package.html
new file mode 100644
index 00000000..0e6088d8
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/package.html
@@ -0,0 +1,5 @@
+<html>
+<body bgcolor="#ffffff">
+The Bouncy Castle math package.
+</body>
+</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Interleave.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Interleave.java
new file mode 100644
index 00000000..85f4f6d6
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Interleave.java
@@ -0,0 +1,177 @@
+package org.bouncycastle.math.raw;
+
+public class Interleave
+{
+ private static final long M32 = 0x55555555L;
+ private static final long M64 = 0x5555555555555555L;
+ private static final long M64R = 0xAAAAAAAAAAAAAAAAL;
+
+ /*
+ * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits.
+ * In a binary field, this operation is the same as squaring an 8 bit number.
+ *
+ * NOTE: All entries are positive so sign-extension is not an issue.
+ */
+// private static final short[] INTERLEAVE2_TABLE = new short[]
+// {
+// 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
+// };
+
+ public static int expand8to16(int x)
+ {
+ x &= 0xFF;
+ x = (x | (x << 4)) & 0x0F0F;
+ x = (x | (x << 2)) & 0x3333;
+ x = (x | (x << 1)) & 0x5555;
+ return x;
+ }
+
+ public static int expand16to32(int x)
+ {
+ x &= 0xFFFF;
+ x = (x | (x << 8)) & 0x00FF00FF;
+ x = (x | (x << 4)) & 0x0F0F0F0F;
+ x = (x | (x << 2)) & 0x33333333;
+ x = (x | (x << 1)) & 0x55555555;
+ return x;
+ }
+
+ public static long expand32to64(int x)
+ {
+ // "shuffle" low half to even bits and high half to odd bits
+ int t;
+ t = (x ^ (x >>> 8)) & 0x0000FF00; x ^= (t ^ (t << 8));
+ t = (x ^ (x >>> 4)) & 0x00F000F0; x ^= (t ^ (t << 4));
+ t = (x ^ (x >>> 2)) & 0x0C0C0C0C; x ^= (t ^ (t << 2));
+ t = (x ^ (x >>> 1)) & 0x22222222; x ^= (t ^ (t << 1));
+
+ return ((x >>> 1) & M32) << 32 | (x & M32);
+ }
+
+ public static void expand64To128(long x, long[] z, int zOff)
+ {
+ // "shuffle" low half to even bits and high half to odd bits
+ long t;
+ t = (x ^ (x >>> 16)) & 0x00000000FFFF0000L; x ^= (t ^ (t << 16));
+ t = (x ^ (x >>> 8)) & 0x0000FF000000FF00L; x ^= (t ^ (t << 8));
+ t = (x ^ (x >>> 4)) & 0x00F000F000F000F0L; x ^= (t ^ (t << 4));
+ t = (x ^ (x >>> 2)) & 0x0C0C0C0C0C0C0C0CL; x ^= (t ^ (t << 2));
+ t = (x ^ (x >>> 1)) & 0x2222222222222222L; x ^= (t ^ (t << 1));
+
+ z[zOff ] = (x ) & M64;
+ z[zOff + 1] = (x >>> 1) & M64;
+ }
+
+ public static void expand64To128Rev(long x, long[] z, int zOff)
+ {
+ // "shuffle" low half to even bits and high half to odd bits
+ long t;
+ t = (x ^ (x >>> 16)) & 0x00000000FFFF0000L; x ^= (t ^ (t << 16));
+ t = (x ^ (x >>> 8)) & 0x0000FF000000FF00L; x ^= (t ^ (t << 8));
+ t = (x ^ (x >>> 4)) & 0x00F000F000F000F0L; x ^= (t ^ (t << 4));
+ t = (x ^ (x >>> 2)) & 0x0C0C0C0C0C0C0C0CL; x ^= (t ^ (t << 2));
+ t = (x ^ (x >>> 1)) & 0x2222222222222222L; x ^= (t ^ (t << 1));
+
+ z[zOff ] = (x ) & M64R;
+ z[zOff + 1] = (x << 1) & M64R;
+ }
+
+ public static int shuffle(int x)
+ {
+ // "shuffle" low half to even bits and high half to odd bits
+ int t;
+ t = (x ^ (x >>> 8)) & 0x0000FF00; x ^= (t ^ (t << 8));
+ t = (x ^ (x >>> 4)) & 0x00F000F0; x ^= (t ^ (t << 4));
+ t = (x ^ (x >>> 2)) & 0x0C0C0C0C; x ^= (t ^ (t << 2));
+ t = (x ^ (x >>> 1)) & 0x22222222; x ^= (t ^ (t << 1));
+ return x;
+ }
+
+ public static long shuffle(long x)
+ {
+ // "shuffle" low half to even bits and high half to odd bits
+ long t;
+ t = (x ^ (x >>> 16)) & 0x00000000FFFF0000L; x ^= (t ^ (t << 16));
+ t = (x ^ (x >>> 8)) & 0x0000FF000000FF00L; x ^= (t ^ (t << 8));
+ t = (x ^ (x >>> 4)) & 0x00F000F000F000F0L; x ^= (t ^ (t << 4));
+ t = (x ^ (x >>> 2)) & 0x0C0C0C0C0C0C0C0CL; x ^= (t ^ (t << 2));
+ t = (x ^ (x >>> 1)) & 0x2222222222222222L; x ^= (t ^ (t << 1));
+ return x;
+ }
+
+ public static int shuffle2(int x)
+ {
+ // "shuffle" (twice) low half to even bits and high half to odd bits
+ int t;
+ t = (x ^ (x >>> 7)) & 0x00AA00AA; x ^= (t ^ (t << 7));
+ t = (x ^ (x >>> 14)) & 0x0000CCCC; x ^= (t ^ (t << 14));
+ t = (x ^ (x >>> 4)) & 0x00F000F0; x ^= (t ^ (t << 4));
+ t = (x ^ (x >>> 8)) & 0x0000FF00; x ^= (t ^ (t << 8));
+ return x;
+ }
+
+ public static int unshuffle(int x)
+ {
+ // "unshuffle" even bits to low half and odd bits to high half
+ int t;
+ t = (x ^ (x >>> 1)) & 0x22222222; x ^= (t ^ (t << 1));
+ t = (x ^ (x >>> 2)) & 0x0C0C0C0C; x ^= (t ^ (t << 2));
+ t = (x ^ (x >>> 4)) & 0x00F000F0; x ^= (t ^ (t << 4));
+ t = (x ^ (x >>> 8)) & 0x0000FF00; x ^= (t ^ (t << 8));
+ return x;
+ }
+
+ public static long unshuffle(long x)
+ {
+ // "unshuffle" even bits to low half and odd bits to high half
+ long t;
+ t = (x ^ (x >>> 1)) & 0x2222222222222222L; x ^= (t ^ (t << 1));
+ t = (x ^ (x >>> 2)) & 0x0C0C0C0C0C0C0C0CL; x ^= (t ^ (t << 2));
+ t = (x ^ (x >>> 4)) & 0x00F000F000F000F0L; x ^= (t ^ (t << 4));
+ t = (x ^ (x >>> 8)) & 0x0000FF000000FF00L; x ^= (t ^ (t << 8));
+ t = (x ^ (x >>> 16)) & 0x00000000FFFF0000L; x ^= (t ^ (t << 16));
+ return x;
+ }
+
+ public static int unshuffle2(int x)
+ {
+ // "unshuffle" (twice) even bits to low half and odd bits to high half
+ int t;
+ t = (x ^ (x >>> 8)) & 0x0000FF00; x ^= (t ^ (t << 8));
+ t = (x ^ (x >>> 4)) & 0x00F000F0; x ^= (t ^ (t << 4));
+ t = (x ^ (x >>> 14)) & 0x0000CCCC; x ^= (t ^ (t << 14));
+ t = (x ^ (x >>> 7)) & 0x00AA00AA; x ^= (t ^ (t << 7));
+ return x;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java
index 6b77f8fa..d9482cf7 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java
@@ -194,6 +194,41 @@ public abstract class Nat
return c == 0 ? 0 : incAt(len, z, zOff, 1);
}
+ public static int cadd(int len, int mask, int[] x, int[] y, int[] z)
+ {
+ long MASK = -(mask & 1) & M;
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) + (y[i] & MASK);
+ z[i] = (int)c;
+ c >>>= 32;
+ }
+ return (int)c;
+ }
+
+ public static void cmov(int len, int mask, int[] x, int xOff, int[] z, int zOff)
+ {
+ mask = -(mask & 1);
+
+ for (int i = 0; i < len; ++i)
+ {
+ int z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
+ z_i ^= (diff & mask);
+ z[zOff + i] = z_i;
+ }
+
+// final int half = 0x55555555, rest = half << (-mask);
+//
+// for (int i = 0; i < len; ++i)
+// {
+// int z_i = z[zOff + i], diff = z_i ^ x[xOff + i];
+// z_i ^= (diff & half);
+// z_i ^= (diff & rest);
+// z[zOff + i] = z_i;
+// }
+ }
+
public static int[] copy(int len, int[] x)
{
int[] z = new int[len];
@@ -206,6 +241,11 @@ public abstract class Nat
System.arraycopy(x, 0, z, 0, len);
}
+ public static void copy(int len, int[] x, int xOff, int[] z, int zOff)
+ {
+ System.arraycopy(x, xOff, z, zOff, len);
+ }
+
public static int[] create(int len)
{
return new int[len];
@@ -216,6 +256,19 @@ public abstract class Nat
return new long[len];
}
+ public static int csub(int len, int mask, int[] x, int[] y, int[] z)
+ {
+ long MASK = -(mask & 1) & M;
+ long c = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ c += (x[i] & M) - (y[i] & MASK);
+ z[i] = (int)c;
+ c >>= 32;
+ }
+ return (int)c;
+ }
+
public static int dec(int len, int[] z)
{
for (int i = 0; i < len; ++i)
@@ -441,6 +494,16 @@ public abstract class Nat
}
}
+ public static void mul(int[] x, int xOff, int xLen, int[] y, int yOff, int yLen, int[] zz, int zzOff)
+ {
+ zz[zzOff + yLen] = mulWord(yLen, x[xOff], y, yOff, zz, zzOff);
+
+ for (int i = 1; i < xLen; ++i)
+ {
+ zz[zzOff + i + yLen] = mulWordAddTo(yLen, x[xOff + i], y, yOff, zz, zzOff + i);
+ }
+ }
+
public static int mulAddTo(int len, int[] x, int[] y, int[] zz)
{
long zc = 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
index 12db01bc..ffe74d70 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java
@@ -144,6 +144,16 @@ public abstract class Nat192
z[5] = x[5];
}
+ public static void copy(int[] x, int xOff, int[] z, int zOff)
+ {
+ z[zOff + 0] = x[xOff + 0];
+ z[zOff + 1] = x[xOff + 1];
+ z[zOff + 2] = x[xOff + 2];
+ z[zOff + 3] = x[xOff + 3];
+ z[zOff + 4] = x[xOff + 4];
+ z[zOff + 5] = x[xOff + 5];
+ }
+
public static void copy64(long[] x, long[] z)
{
z[0] = x[0];
@@ -151,6 +161,13 @@ public abstract class Nat192
z[2] = x[2];
}
+ public static void copy64(long[] x, int xOff, long[] z, int zOff)
+ {
+ z[zOff + 0] = x[xOff + 0];
+ z[zOff + 1] = x[xOff + 1];
+ z[zOff + 2] = x[xOff + 2];
+ }
+
public static int[] create()
{
return new int[6];
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java
index 9ff107c1..59be1f51 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java
@@ -215,6 +215,17 @@ public abstract class Nat224
z[6] = x[6];
}
+ public static void copy(int[] x, int xOff, int[] z, int zOff)
+ {
+ z[zOff + 0] = x[xOff + 0];
+ z[zOff + 1] = x[xOff + 1];
+ z[zOff + 2] = x[xOff + 2];
+ z[zOff + 3] = x[xOff + 3];
+ z[zOff + 4] = x[xOff + 4];
+ z[zOff + 5] = x[xOff + 5];
+ z[zOff + 6] = x[xOff + 6];
+ }
+
public static int[] create()
{
return new int[7];
diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java
index 726bae35..f7d80b3a 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java
@@ -238,6 +238,18 @@ public abstract class Nat256
z[7] = x[7];
}
+ public static void copy(int[] x, int xOff, int[] z, int zOff)
+ {
+ z[zOff + 0] = x[xOff + 0];
+ z[zOff + 1] = x[xOff + 1];
+ z[zOff + 2] = x[xOff + 2];
+ z[zOff + 3] = x[xOff + 3];
+ z[zOff + 4] = x[xOff + 4];
+ z[zOff + 5] = x[xOff + 5];
+ z[zOff + 6] = x[xOff + 6];
+ z[zOff + 7] = x[xOff + 7];
+ }
+
public static void copy64(long[] x, long[] z)
{
z[0] = x[0];
@@ -246,6 +258,14 @@ public abstract class Nat256
z[3] = x[3];
}
+ public static void copy64(long[] x, int xOff, long[] z, int zOff)
+ {
+ z[zOff + 0] = x[xOff + 0];
+ z[zOff + 1] = x[xOff + 1];
+ z[zOff + 2] = x[xOff + 2];
+ z[zOff + 3] = x[xOff + 3];
+ }
+
public static int[] create()
{
return new int[8];
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
index 6873117a..c48ae757 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
@@ -8,11 +8,21 @@ import java.util.NoSuchElementException;
*/
public final class Arrays
{
- private Arrays()
+ private Arrays()
{
// static class, hide constructor
}
+ public static boolean areAllZeroes(byte[] buf, int off, int len)
+ {
+ int bits = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ bits |= buf[off + i];
+ }
+ return bits == 0;
+ }
+
public static boolean areEqual(
boolean[] a,
boolean[] b)
@@ -135,36 +145,37 @@ public final class Arrays
/**
* A constant time equals comparison - does not terminate early if
- * test will fail.
+ * test will fail. For best results always pass the expected value
+ * as the first parameter.
*
- * @param a first array
- * @param b second array
+ * @param expected first array
+ * @param supplied second array
* @return true if arrays equal, false otherwise.
*/
public static boolean constantTimeAreEqual(
- byte[] a,
- byte[] b)
+ byte[] expected,
+ byte[] supplied)
{
- if (a == b)
+ if (expected == supplied)
{
return true;
}
- if (a == null || b == null)
+ if (expected == null || supplied == null)
{
return false;
}
- if (a.length != b.length)
+ if (expected.length != supplied.length)
{
- return false;
+ return !Arrays.constantTimeAreEqual(expected, expected);
}
int nonEqual = 0;
- for (int i = 0; i != a.length; i++)
+ for (int i = 0; i != expected.length; i++)
{
- nonEqual |= (a[i] ^ b[i]);
+ nonEqual |= (expected[i] ^ supplied[i]);
}
return nonEqual == 0;
@@ -335,6 +346,18 @@ public final class Arrays
}
public static void fill(
+ byte[] array,
+ int start,
+ int finish,
+ byte value)
+ {
+ for (int i = start; i < finish; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
char[] array,
char value)
{
@@ -355,7 +378,7 @@ public final class Arrays
}
public static void fill(
- short[] array,
+ short[] array,
short value)
{
for (int i = 0; i < array.length; i++)
@@ -373,7 +396,63 @@ public final class Arrays
array[i] = value;
}
}
-
+
+ public static void fill(
+ byte[] array,
+ int out,
+ byte value)
+ {
+ if(out < array.length)
+ {
+ for (int i = out; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+ }
+
+ public static void fill(
+ int[] array,
+ int out,
+ int value)
+ {
+ if(out < array.length)
+ {
+ for (int i = out; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+ }
+
+ public static void fill(
+ short[] array,
+ int out,
+ short value)
+ {
+ if(out < array.length)
+ {
+ for (int i = out; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+ }
+
+ public static void fill(
+ long[] array,
+ int out,
+ long value)
+ {
+ if(out < array.length)
+ {
+ for (int i = out; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+ }
+
public static int hashCode(byte[] data)
{
if (data == null)
@@ -681,9 +760,9 @@ public final class Arrays
return null;
}
long[] copy = new long[data.length];
-
+
System.arraycopy(data, 0, copy, 0, data.length);
-
+
return copy;
}
@@ -1126,7 +1205,7 @@ public final class Arrays
int p1 = 0, p2 = a.length;
byte[] result = new byte[p2];
-
+
while (--p2 >= 0)
{
result[p2] = a[p1++];
@@ -1196,4 +1275,20 @@ public final class Arrays
throw new UnsupportedOperationException("Cannot remove element from an Array.");
}
}
+
+ /**
+ * Fill input array by zeros
+ *
+ * @param array input array
+ */
+ public static void clear(byte[] array)
+ {
+ if (array != null)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = 0;
+ }
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java b/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java
index f7f7e68b..a118ba5a 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java
@@ -8,8 +8,13 @@ import java.security.SecureRandom;
*/
public final class BigIntegers
{
+ public static final BigInteger ZERO = BigInteger.valueOf(0);
+ public static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+ private static final BigInteger THREE = BigInteger.valueOf(3);
+
private static final int MAX_ITERATIONS = 1000;
- private static final BigInteger ZERO = BigInteger.valueOf(0);
/**
* Return the passed in value as an unsigned byte array.
@@ -92,7 +97,7 @@ public final class BigIntegers
for (int i = 0; i < MAX_ITERATIONS; ++i)
{
- BigInteger x = new BigInteger(max.bitLength(), random);
+ BigInteger x = createRandomBigInteger(max.bitLength(), random);
if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0)
{
return x;
@@ -100,7 +105,7 @@ public final class BigIntegers
}
// fall back to a faster (restricted) method
- return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min);
+ return createRandomBigInteger(max.subtract(min).bitLength() - 1, random).add(min);
}
public static BigInteger fromUnsignedByteArray(byte[] buf)
@@ -118,4 +123,81 @@ public final class BigIntegers
}
return new BigInteger(1, mag);
}
+
+ public static int getUnsignedByteLength(BigInteger n)
+ {
+ return (n.bitLength() + 7) / 8;
+ }
+
+ /**
+ * Return a positive BigInteger in the range of 0 to 2**bitLength - 1.
+ *
+ * @param bitLength maximum bit length for the generated BigInteger.
+ * @param random a source of randomness.
+ * @return a positive BigInteger
+ */
+ public static BigInteger createRandomBigInteger(int bitLength, SecureRandom random)
+ {
+ return new BigInteger(1, createRandom(bitLength, random));
+ }
+
+ /**
+ * Return a prime number candidate of the specified bit length.
+ *
+ * @param bitLength bit length for the generated BigInteger.
+ * @param random a source of randomness.
+ * @return a positive BigInteger of numBits length
+ */
+ public static BigInteger createRandomPrime(int bitLength, int certainty, SecureRandom random)
+ {
+ if (bitLength < 2)
+ {
+ throw new IllegalArgumentException("bitLength < 2");
+ }
+
+ BigInteger rv;
+
+ if (bitLength == 2)
+ {
+ return (random.nextInt() < 0) ? TWO : THREE;
+ }
+
+ do
+ {
+ byte[] base = createRandom(bitLength, random);
+
+ int xBits = 8 * base.length - bitLength;
+ byte lead = (byte)(1 << (7 - xBits));
+
+ // ensure top and bottom bit set
+ base[0] |= lead;
+ base[base.length - 1] |= 0x01;
+
+ rv = new BigInteger(1, base);
+ }
+ while (!rv.isProbablePrime(certainty));
+
+ return rv;
+ }
+
+ private static byte[] createRandom(int bitLength, SecureRandom random)
+ throws IllegalArgumentException
+ {
+ if (bitLength < 1)
+ {
+ throw new IllegalArgumentException("bitLength must be at least 1");
+ }
+
+ int nBytes = (bitLength + 7) / 8;
+
+ byte[] rv = new byte[nBytes];
+
+ random.nextBytes(rv);
+
+ // strip off any excess bits in the MSB
+ int xBits = 8 * nBytes - bitLength;
+ rv[0] &= (byte)(255 >>> xBits);
+
+ return rv;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Fingerprint.java b/bcprov/src/main/java/org/bouncycastle/util/Fingerprint.java
new file mode 100644
index 00000000..d190ea6a
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/util/Fingerprint.java
@@ -0,0 +1,180 @@
+package org.bouncycastle.util;
+
+// Android-changed: Use Android digests
+// import org.bouncycastle.crypto.digests.SHA512tDigest;
+// import org.bouncycastle.crypto.digests.SHAKEDigest;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.digests.AndroidDigestFactory;
+
+/**
+ * Basic 20 byte finger print class.
+ */
+public class Fingerprint
+{
+ private static char[] encodingTable =
+ {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ private final byte[] fingerprint;
+
+ /**
+ * Base constructor - use SHAKE-256 (160 bits). This is the recommended one as it is also
+ * produced by the FIPS API.
+ *
+ * @param source original data to calculate the fingerprint from.
+ */
+ public Fingerprint(byte[] source)
+ {
+ this(source, 160);
+ }
+
+ /**
+ * Constructor with length - use SHAKE-256 (bitLength bits). This is the recommended one as it is also
+ * produced by the FIPS API.
+ *
+ * @param source original data to calculate the fingerprint from.
+ */
+ public Fingerprint(byte[] source, int bitLength)
+ {
+ this.fingerprint = calculateFingerprint(source, bitLength);
+ }
+
+ // BEGIN Android-removed: Unsupported algorithms
+ /*
+ /**
+ * Base constructor - for backwards compatibility.
+ *
+ * @param source original data to calculate the fingerprint from.
+ * @param useSHA512t use the old SHA512/160 calculation.
+ * @deprecated use the SHAKE only version.
+ *
+ public Fingerprint(byte[] source, boolean useSHA512t)
+ {
+ if (useSHA512t)
+ {
+ this.fingerprint = calculateFingerprintSHA512_160(source);
+ }
+ else
+ {
+ this.fingerprint = calculateFingerprint(source);
+ }
+ }
+ */
+ // END Android-removed: Unsupported algorithms
+
+ public byte[] getFingerprint()
+ {
+ return Arrays.clone(fingerprint);
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i != fingerprint.length; i++)
+ {
+ if (i > 0)
+ {
+ sb.append(":");
+ }
+ sb.append(encodingTable[(fingerprint[i] >>> 4) & 0xf]);
+ sb.append(encodingTable[fingerprint[i] & 0x0f]);
+ }
+
+ return sb.toString();
+ }
+
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+ if (o instanceof Fingerprint)
+ {
+ return Arrays.areEqual(((Fingerprint)o).fingerprint, fingerprint);
+ }
+
+ return false;
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(fingerprint);
+ }
+
+ /**
+ * Return a byte array containing a calculated fingerprint for the passed in input data.
+ * This calculation is compatible with the BC FIPS API.
+ *
+ * @param input data to base the fingerprint on.
+ * @return a byte array containing a 160 bit fingerprint.
+ */
+ public static byte[] calculateFingerprint(byte[] input)
+ {
+ return calculateFingerprint(input, 160);
+ }
+
+ /*
+ /**
+ * Return a byte array containing a calculated fingerprint for the passed in input data.
+ * This calculation is compatible with the BC FIPS API.
+ *
+ * @param input data to base the fingerprint on.
+ * @param bitLength bit length of finger print to be produced.
+ * @return a byte array containing a 20 byte fingerprint.
+ */
+ public static byte[] calculateFingerprint(byte[] input, int bitLength)
+ {
+ if (bitLength % 8 != 0)
+ {
+ throw new IllegalArgumentException("bitLength must be a multiple of 8");
+ }
+
+ // Android-changed: Use SHA-256 instead of SHAKE-256, since we don't support SHAKE
+ // SHAKEDigest digest = new SHAKEDigest(256);
+ Digest digest = AndroidDigestFactory.getSHA256();
+
+ digest.update(input, 0, input.length);
+
+ byte[] rv = new byte[bitLength / 8];
+
+ // Android-changed: Hash and truncate since SHA-256 doesn't support variable length output
+ //
+ // digest.doFinal(rv, 0, bitLength / 8);
+ byte[] untruncated = new byte[32];
+ digest.doFinal(untruncated, 0);
+ if ((bitLength / 8) >= 32) {
+ return untruncated;
+ }
+
+ System.arraycopy(untruncated, 0, rv, 0, rv.length);
+
+ return rv;
+ }
+
+ // BEGIN Android-removed: Unsupported algorithms
+ /**
+ * Return a byte array containing a calculated fingerprint for the passed in input data.
+ * The fingerprint is based on SHA512/160.
+ *
+ * @param input data to base the fingerprint on.
+ * @return a byte array containing a 20 byte fingerprint.
+ * @deprecated use the SHAKE based version.
+ *
+ public static byte[] calculateFingerprintSHA512_160(byte[] input)
+ {
+ SHA512tDigest digest = new SHA512tDigest(160);
+
+ digest.update(input, 0, input.length);
+
+ byte[] rv = new byte[digest.getDigestSize()];
+
+ digest.doFinal(rv, 0);
+
+ return rv;
+ }
+ */
+ // END Android-removed: Unsupported algorithms
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/IPAddress.java b/bcprov/src/main/java/org/bouncycastle/util/IPAddress.java
index 8af1709e..8f57263f 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/IPAddress.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/IPAddress.java
@@ -118,7 +118,7 @@ public class IPAddress
*
* @param address the IP address as a String.
*
- * @return true if a valid IPv4 address, false otherwise
+ * @return true if a valid IPv6 address, false otherwise
*/
public static boolean isValidIPv6(
String address)
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Pack.java b/bcprov/src/main/java/org/bouncycastle/util/Pack.java
index 82b02ea5..44b0b278 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Pack.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Pack.java
@@ -211,6 +211,15 @@ public abstract class Pack
}
}
+ public static void littleEndianToLong(byte[] bs, int bsOff, long[] ns, int nsOff, int nsLen)
+ {
+ for (int i = 0; i < nsLen; ++i)
+ {
+ ns[nsOff + i] = littleEndianToLong(bs, bsOff);
+ bsOff += 8;
+ }
+ }
+
public static byte[] longToLittleEndian(long n)
{
byte[] bs = new byte[8];
@@ -239,4 +248,13 @@ public abstract class Pack
off += 8;
}
}
+
+ public static void longToLittleEndian(long[] ns, int nsOff, int nsLen, byte[] bs, int bsOff)
+ {
+ for (int i = 0; i < nsLen; ++i)
+ {
+ longToLittleEndian(ns[nsOff + i], bs, bsOff);
+ bsOff += 8;
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Properties.java b/bcprov/src/main/java/org/bouncycastle/util/Properties.java
index e533b586..c472d187 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Properties.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Properties.java
@@ -1,10 +1,13 @@
package org.bouncycastle.util;
+import java.math.BigInteger;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
@@ -13,24 +16,31 @@ import java.util.StringTokenizer;
*/
public class Properties
{
- public static boolean isOverrideSet(final String propertyName)
+ private Properties()
+ {
+
+ }
+
+ private static final ThreadLocal threadProperties = new ThreadLocal();
+
+ /**
+ * Return whether a particular override has been set to true.
+ *
+ * @param propertyName the property name for the override.
+ * @return true if the property is set to "true", false otherwise.
+ */
+ public static boolean isOverrideSet(String propertyName)
{
try
{
- return "true".equals(AccessController.doPrivileged(new PrivilegedAction()
+ String p = fetchProperty(propertyName);
+
+ if (p != null)
{
- // JDK 1.4 compatibility
- public Object run()
- {
- String value = System.getProperty(propertyName);
- if (value == null)
- {
- return null;
- }
+ return "true".equals(Strings.toLowerCase(p));
+ }
- return Strings.toLowerCase(value);
- }
- }));
+ return false;
}
catch (AccessControlException e)
{
@@ -38,10 +48,78 @@ public class Properties
}
}
- public static Set<String> asKeySet(final String propertyName)
+ /**
+ * Enable the specified override property for the current thread only.
+ *
+ * @param propertyName the property name for the override.
+ * @param enable true if the override should be enabled, false if it should be disabled.
+ * @return true if the override was already set, false otherwise.
+ */
+ public static boolean setThreadOverride(String propertyName, boolean enable)
+ {
+ boolean isSet = isOverrideSet(propertyName);
+
+ Map localProps = (Map)threadProperties.get();
+ if (localProps == null)
+ {
+ localProps = new HashMap();
+ }
+
+ localProps.put(propertyName, enable ? "true" : "false");
+
+ threadProperties.set(localProps);
+
+ return isSet;
+ }
+
+ /**
+ * Enable the specified override property in the current thread only.
+ *
+ * @param propertyName the property name for the override.
+ * @return true if the override set true in thread local, false otherwise.
+ */
+ public static boolean removeThreadOverride(String propertyName)
+ {
+ boolean isSet = isOverrideSet(propertyName);
+
+ Map localProps = (Map)threadProperties.get();
+ if (localProps == null)
+ {
+ return false;
+ }
+
+ localProps.remove(propertyName);
+
+ if (localProps.isEmpty())
+ {
+ threadProperties.remove();
+ }
+ else
+ {
+ threadProperties.set(localProps);
+ }
+
+ return isSet;
+ }
+
+ public static BigInteger asBigInteger(String propertyName)
+ {
+ String p = fetchProperty(propertyName);
+
+ if (p != null)
+ {
+ return new BigInteger(p);
+ }
+
+ return null;
+ }
+
+ public static Set<String> asKeySet(String propertyName)
{
Set<String> set = new HashSet<String>();
- String p = System.getProperty(propertyName);
+
+ String p = fetchProperty(propertyName);
+
if (p != null)
{
StringTokenizer sTok = new StringTokenizer(p, ",");
@@ -50,6 +128,24 @@ public class Properties
set.add(Strings.toLowerCase(sTok.nextToken()).trim());
}
}
+
return Collections.unmodifiableSet(set);
}
+
+ private static String fetchProperty(final String propertyName)
+ {
+ return (String)AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ Map localProps = (Map)threadProperties.get();
+ if (localProps != null)
+ {
+ return localProps.get(propertyName);
+ }
+
+ return System.getProperty(propertyName);
+ }
+ });
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Strings.java b/bcprov/src/main/java/org/bouncycastle/util/Strings.java
index a42830b3..bda9d9a6 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Strings.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Strings.java
@@ -8,6 +8,8 @@ import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Vector;
+import org.bouncycastle.util.encoders.UTF8;
+
/**
* String utilities.
*/
@@ -17,105 +19,41 @@ public final class Strings
static
{
- try
- {
- LINE_SEPARATOR = AccessController.doPrivileged(new PrivilegedAction<String>()
- {
- public String run()
- {
- // the easy way
- return System.getProperty("line.separator");
- }
- });
-
- }
- catch (Exception e)
- {
- try
- {
- // the harder way
- LINE_SEPARATOR = String.format("%n");
- }
- catch (Exception ef)
- {
- LINE_SEPARATOR = "\n"; // we're desperate use this...
- }
- }
- }
-
- public static String fromUTF8ByteArray(byte[] bytes)
- {
- int i = 0;
- int length = 0;
-
- while (i < bytes.length)
+ try
{
- length++;
- if ((bytes[i] & 0xf0) == 0xf0)
- {
- // surrogate pair
- length++;
- i += 4;
- }
- else if ((bytes[i] & 0xe0) == 0xe0)
+ LINE_SEPARATOR = AccessController.doPrivileged(new PrivilegedAction<String>()
{
- i += 3;
- }
- else if ((bytes[i] & 0xc0) == 0xc0)
- {
- i += 2;
- }
- else
- {
- i += 1;
- }
- }
-
- char[] cs = new char[length];
-
- i = 0;
- length = 0;
+ public String run()
+ {
+ // the easy way
+ return System.getProperty("line.separator");
+ }
+ });
- while (i < bytes.length)
+ }
+ catch (Exception e)
{
- char ch;
-
- if ((bytes[i] & 0xf0) == 0xf0)
- {
- int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i + 1] & 0x3F) << 12) | ((bytes[i + 2] & 0x3F) << 6) | (bytes[i + 3] & 0x3F);
- int U = codePoint - 0x10000;
- char W1 = (char)(0xD800 | (U >> 10));
- char W2 = (char)(0xDC00 | (U & 0x3FF));
- cs[length++] = W1;
- ch = W2;
- i += 4;
- }
- else if ((bytes[i] & 0xe0) == 0xe0)
+ try
{
- ch = (char)(((bytes[i] & 0x0f) << 12)
- | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
- i += 3;
+ // the harder way
+ LINE_SEPARATOR = String.format("%n");
}
- else if ((bytes[i] & 0xd0) == 0xd0)
- {
- ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
- i += 2;
- }
- else if ((bytes[i] & 0xc0) == 0xc0)
- {
- ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
- i += 2;
- }
- else
+ catch (Exception ef)
{
- ch = (char)(bytes[i] & 0xff);
- i += 1;
+ LINE_SEPARATOR = "\n"; // we're desperate use this...
}
-
- cs[length++] = ch;
}
+ }
- return new String(cs);
+ public static String fromUTF8ByteArray(byte[] bytes)
+ {
+ char[] chars = new char[bytes.length];
+ int len = UTF8.transcodeToUTF16(bytes, chars);
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Invalid UTF-8 input");
+ }
+ return new String(chars, 0, len);
}
public static byte[] toUTF8ByteArray(String string)
@@ -263,6 +201,7 @@ public final class Strings
return bytes;
}
+
public static byte[] toByteArray(String string)
{
byte[] bytes = new byte[string.length()];
@@ -401,4 +340,6 @@ public final class Strings
return strs;
}
}
+
+
}
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 4216674a..645b151c 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java
@@ -149,11 +149,27 @@ public class Base64Encoder
end--;
}
+
+ // empty data!
+ if (end == 0)
+ {
+ return 0;
+ }
- int i = off;
- int finish = end - 4;
-
- i = nextI(data, i, finish);
+ int i = 0;
+ int finish = end;
+
+ while (finish > off && i != 4)
+ {
+ if (!ignore((char)data[finish - 1]))
+ {
+ i++;
+ }
+
+ finish--;
+ }
+
+ i = nextI(data, off, finish);
while (i < finish)
{
@@ -185,8 +201,13 @@ public class Base64Encoder
i = nextI(data, i, finish);
}
- outLen += decodeLastBlock(out, (char)data[end - 4], (char)data[end - 3], (char)data[end - 2], (char)data[end - 1]);
-
+ int e0 = nextI(data, i, end);
+ int e1 = nextI(data, e0 + 1, end);
+ int e2 = nextI(data, e1 + 1, end);
+ int e3 = nextI(data, e2 + 1, end);
+
+ outLen += decodeLastBlock(out, (char)data[e0], (char)data[e1], (char)data[e2], (char)data[e3]);
+
return outLen;
}
@@ -224,11 +245,27 @@ public class Base64Encoder
end--;
}
+
+ // empty data!
+ if (end == 0)
+ {
+ return 0;
+ }
int i = 0;
- int finish = end - 4;
+ int finish = end;
+
+ while (finish > 0 && i != 4)
+ {
+ if (!ignore(data.charAt(finish - 1)))
+ {
+ i++;
+ }
+
+ finish--;
+ }
- i = nextI(data, i, finish);
+ i = nextI(data, 0, finish);
while (i < finish)
{
@@ -260,8 +297,13 @@ public class Base64Encoder
i = nextI(data, i, finish);
}
- length += decodeLastBlock(out, data.charAt(end - 4), data.charAt(end - 3), data.charAt(end - 2), data.charAt(end - 1));
+ int e0 = nextI(data, i, end);
+ int e1 = nextI(data, e0 + 1, end);
+ int e2 = nextI(data, e1 + 1, end);
+ int e3 = nextI(data, e2 + 1, end);
+ length += decodeLastBlock(out, data.charAt(e0), data.charAt(e1), data.charAt(e2), data.charAt(e3));
+
return length;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/UTF8.java b/bcprov/src/main/java/org/bouncycastle/util/encoders/UTF8.java
new file mode 100644
index 00000000..e64e443c
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/UTF8.java
@@ -0,0 +1,156 @@
+package org.bouncycastle.util.encoders;
+
+/**
+ * Utilities for working with UTF-8 encodings.
+ *
+ * Decoding of UTF-8 is based on a presentation by Bob Steagall at CppCon2018 (see
+ * https://github.com/BobSteagall/CppCon2018). It uses a Deterministic Finite Automaton (DFA) to
+ * recognize and decode multi-byte code points.
+ */
+public class UTF8
+{
+ // Constants for the categorization of code units
+ private static final byte C_ILL = 0; //- C0..C1, F5..FF ILLEGAL octets that should never appear in a UTF-8 sequence
+ private static final byte C_CR1 = 1; //- 80..8F Continuation range 1
+ private static final byte C_CR2 = 2; //- 90..9F Continuation range 2
+ private static final byte C_CR3 = 3; //- A0..BF Continuation range 3
+ private static final byte C_L2A = 4; //- C2..DF Leading byte range A / 2-byte sequence
+ private static final byte C_L3A = 5; //- E0 Leading byte range A / 3-byte sequence
+ private static final byte C_L3B = 6; //- E1..EC, EE..EF Leading byte range B / 3-byte sequence
+ private static final byte C_L3C = 7; //- ED Leading byte range C / 3-byte sequence
+ private static final byte C_L4A = 8; //- F0 Leading byte range A / 4-byte sequence
+ private static final byte C_L4B = 9; //- F1..F3 Leading byte range B / 4-byte sequence
+ private static final byte C_L4C = 10; //- F4 Leading byte range C / 4-byte sequence
+// private static final byte C_ASC = 11; //- 00..7F ASCII leading byte range
+
+ // Constants for the states of a DFA
+ private static final byte S_ERR = -2; //- Error state
+ private static final byte S_END = -1; //- End (or Accept) state
+ private static final byte S_CS1 = 0x00; //- Continuation state 1
+ private static final byte S_CS2 = 0x10; //- Continuation state 2
+ private static final byte S_CS3 = 0x20; //- Continuation state 3
+ private static final byte S_P3A = 0x30; //- Partial 3-byte sequence state A
+ private static final byte S_P3B = 0x40; //- Partial 3-byte sequence state B
+ private static final byte S_P4A = 0x50; //- Partial 4-byte sequence state A
+ private static final byte S_P4B = 0x60; //- Partial 4-byte sequence state B
+
+ private static final short[] firstUnitTable = new short[128];
+ private static final byte[] transitionTable = new byte[S_P4B + 16];
+
+ private static void fill(byte[] table, int first, int last, byte b)
+ {
+ for (int i = first; i <= last; ++i)
+ {
+ table[i] = b;
+ }
+ }
+
+ static
+ {
+ byte[] categories = new byte[128];
+ fill(categories, 0x00, 0x0F, C_CR1);
+ fill(categories, 0x10, 0x1F, C_CR2);
+ fill(categories, 0x20, 0x3F, C_CR3);
+ fill(categories, 0x40, 0x41, C_ILL);
+ fill(categories, 0x42, 0x5F, C_L2A);
+ fill(categories, 0x60, 0x60, C_L3A);
+ fill(categories, 0x61, 0x6C, C_L3B);
+ fill(categories, 0x6D, 0x6D, C_L3C);
+ fill(categories, 0x6E, 0x6F, C_L3B);
+ fill(categories, 0x70, 0x70, C_L4A);
+ fill(categories, 0x71, 0x73, C_L4B);
+ fill(categories, 0x74, 0x74, C_L4C);
+ fill(categories, 0x75, 0x7F, C_ILL);
+
+ fill(transitionTable, 0, transitionTable.length - 1, S_ERR);
+ fill(transitionTable, S_CS1 + 0x8, S_CS1 + 0xB, S_END);
+ fill(transitionTable, S_CS2 + 0x8, S_CS2 + 0xB, S_CS1);
+ fill(transitionTable, S_CS3 + 0x8, S_CS3 + 0xB, S_CS2);
+ fill(transitionTable, S_P3A + 0xA, S_P3A + 0xB, S_CS1);
+ fill(transitionTable, S_P3B + 0x8, S_P3B + 0x9, S_CS1);
+ fill(transitionTable, S_P4A + 0x9, S_P4A + 0xB, S_CS2);
+ fill(transitionTable, S_P4B + 0x8, S_P4B + 0x8, S_CS2);
+
+ byte[] firstUnitMasks = { 0x00, 0x00, 0x00, 0x00, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07 };
+ byte[] firstUnitTransitions = { S_ERR, S_ERR, S_ERR, S_ERR, S_CS1, S_P3A, S_CS2, S_P3B, S_P4A, S_CS3, S_P4B };
+
+ for (int i = 0x00; i < 0x80; ++i)
+ {
+ byte category = categories[i];
+
+ int codePoint = i & firstUnitMasks[category];
+ byte state = firstUnitTransitions[category];
+
+ firstUnitTable[i] = (short)((codePoint << 8) | state);
+ }
+ }
+
+ /**
+ * Transcode a UTF-8 encoding into a UTF-16 representation. In the general case the output
+ * {@code utf16} array should be at least as long as the input {@code utf8} one to handle
+ * arbitrary inputs. The number of output UTF-16 code units is returned, or -1 if any errors are
+ * encountered (in which case an arbitrary amount of data may have been written into the output
+ * array). Errors that will be detected are malformed UTF-8, including incomplete, truncated or
+ * "overlong" encodings, and unmappable code points. In particular, no unmatched surrogates will
+ * be produced. An error will also result if {@code utf16} is found to be too small to store the
+ * complete output.
+ *
+ * @param utf8
+ * A non-null array containing a well-formed UTF-8 encoding.
+ * @param utf16
+ * A non-null array, at least as long as the {@code utf8} array in order to ensure
+ * the output will fit.
+ * @return The number of UTF-16 code units written to {@code utf16} (beginning from index 0), or
+ * else -1 if the input was either malformed or encoded any unmappable characters, or if
+ * the {@code utf16} is too small.
+ */
+ public static int transcodeToUTF16(byte[] utf8, char[] utf16)
+ {
+ int i = 0, j = 0;
+
+ while (i < utf8.length)
+ {
+ byte codeUnit = utf8[i++];
+ if (codeUnit >= 0)
+ {
+ if (j >= utf16.length) { return -1; }
+
+ utf16[j++] = (char)codeUnit;
+ continue;
+ }
+
+ short first = firstUnitTable[codeUnit & 0x7F];
+ int codePoint = first >>> 8;
+ byte state = (byte)first;
+
+ while (state >= 0)
+ {
+ if (i >= utf8.length) { return -1; }
+
+ codeUnit = utf8[i++];
+ codePoint = (codePoint << 6) | (codeUnit & 0x3F);
+ state = transitionTable[state + ((codeUnit & 0xFF) >>> 4)];
+ }
+
+ if (state == S_ERR) { return -1; }
+
+ if (codePoint <= 0xFFFF)
+ {
+ if (j >= utf16.length) { return -1; }
+
+ // Code points from U+D800 to U+DFFF are caught by the DFA
+ utf16[j++] = (char)codePoint;
+ }
+ else
+ {
+ if (j >= utf16.length - 1) { return -1; }
+
+ // Code points above U+10FFFF are caught by the DFA
+ utf16[j++] = (char)(0xD7C0 + (codePoint >>> 10));
+ utf16[j++] = (char)(0xDC00 | (codePoint & 0x3FF));
+ }
+ }
+
+ return j;
+ }
+}
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 3045b4d0..be9090d9 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
@@ -22,6 +22,12 @@ public class PemReader
super(reader);
}
+ /**
+ * Read the next PEM object as a blob of raw data with header information.
+ *
+ * @return the next object in the stream, null if no objects left.
+ * @throws IOException in case of a parse error.
+ */
public PemObject readPemObject()
throws IOException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXParameters.java b/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXParameters.java
index 952f7754..50a292b2 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXParameters.java
@@ -1,8 +1,5 @@
package org.bouncycastle.x509;
-import org.bouncycastle.util.Selector;
-import org.bouncycastle.util.Store;
-
import java.security.InvalidAlgorithmParameterException;
import java.security.cert.CertSelector;
import java.security.cert.CertStore;
@@ -16,6 +13,9 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import org.bouncycastle.util.Selector;
+import org.bouncycastle.util.Store;
+
/**
* This class extends the PKIXParameters with a validity model parameter.
*
@@ -286,7 +286,7 @@ public class ExtendedPKIXParameters
*
* @param store The store to add.
* @see #getStores()
- * @deprectaed use addStore().
+ * @deprecated use addStore().
*/
public void addAdditionalStore(Store store)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java b/bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java
index 2486d208..63ed8ab0 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/X509CRLStoreSelector.java
@@ -7,7 +7,7 @@ import java.security.cert.X509CRL;
import java.security.cert.X509CRLSelector;
import org.bouncycastle.asn1.ASN1Integer;
-import org.bouncycastle.asn1.x509.X509Extensions;
+import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Selector;
import org.bouncycastle.x509.extension.X509ExtensionUtil;
@@ -100,7 +100,7 @@ public class X509CRLStoreSelector
try
{
byte[] bytes = crl
- .getExtensionValue(X509Extensions.DeltaCRLIndicator.getId());
+ .getExtensionValue(Extension.deltaCRLIndicator.getId());
if (bytes != null)
{
dci = ASN1Integer.getInstance(X509ExtensionUtil
@@ -139,7 +139,7 @@ public class X509CRLStoreSelector
if (issuingDistributionPointEnabled)
{
byte[] idp = crl
- .getExtensionValue(X509Extensions.IssuingDistributionPoint
+ .getExtensionValue(Extension.issuingDistributionPoint
.getId());
if (issuingDistributionPoint == null)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/extension/X509ExtensionUtil.java b/bcprov/src/main/java/org/bouncycastle/x509/extension/X509ExtensionUtil.java
index 2e4d14d3..0779d1aa 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/extension/X509ExtensionUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/extension/X509ExtensionUtil.java
@@ -16,13 +16,19 @@ import org.bouncycastle.asn1.ASN1String;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.util.Integers;
+/**
+ * @deprecated use org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils
+ */
public class X509ExtensionUtil
{
+ /**
+ * @deprecated use org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils.parseExtensionValue()
+ */
public static ASN1Primitive fromExtensionValue(
byte[] encodedValue)
throws IOException
@@ -32,18 +38,24 @@ public class X509ExtensionUtil
return ASN1Primitive.fromByteArray(octs.getOctets());
}
+ /**
+ * @deprecated use org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils.getIssuerAlternativeNames()
+ */
public static Collection getIssuerAlternativeNames(X509Certificate cert)
throws CertificateParsingException
{
- byte[] extVal = cert.getExtensionValue(X509Extension.issuerAlternativeName.getId());
+ byte[] extVal = cert.getExtensionValue(Extension.issuerAlternativeName.getId());
return getAlternativeNames(extVal);
}
+ /**
+ * @deprecated use org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils.getSubjectAlternativeNames()
+ */
public static Collection getSubjectAlternativeNames(X509Certificate cert)
throws CertificateParsingException
{
- byte[] extVal = cert.getExtensionValue(X509Extension.subjectAlternativeName.getId());
+ byte[] extVal = cert.getExtensionValue(Extension.subjectAlternativeName.getId());
return getAlternativeNames(extVal);
}