summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergio Giro <sgiro@google.com>2016-01-27 20:40:41 +0000
committerSergio Giro <sgiro@google.com>2016-01-28 15:30:59 +0000
commit80261dd2d1824bb3862e90e77a5412d56ad88b1f (patch)
treed89e670054247d0a050ac1b0d9a7918cbe3498d6
parent9be78fe4c709f1e585b5ed7e99b21084045b7fba (diff)
downloadandroid_external_bouncycastle-80261dd2d1824bb3862e90e77a5412d56ad88b1f.tar.gz
android_external_bouncycastle-80261dd2d1824bb3862e90e77a5412d56ad88b1f.tar.bz2
android_external_bouncycastle-80261dd2d1824bb3862e90e77a5412d56ad88b1f.zip
bouncycastle: Android tree with upstream code for version 1.50
Android tree as of c0d8909a6c6a4ac075a9dee7ac1fe6baff34acc0 Change-Id: I8d381554d6edec32aae8ff5bab5d5314f0954440
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/X509ContentVerifierProviderBuilder.java14
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/cmp/package.html7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/cmp/test/AllTests.java45
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/crmf/CertificateRequestMessageBuilder.java28
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java9
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/package.html7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/crmf/package.html7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509ContentVerifierProviderBuilder.java50
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/jcajce/package.html7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/ocsp/jcajce/package.html7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/ocsp/package.html7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/package.html5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/CertPath.java80
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathUtils.java21
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidation.java11
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationContext.java61
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationException.java24
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationResult.java66
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationResultBuilder.java14
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathTest.java369
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathValidationTest.java403
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/validations/BasicConstraintsValidation.java103
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CRLValidation.java78
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CertificatePoliciesValidation.java146
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CertificatePoliciesValidationBuilder.java35
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/validations/KeyUsageValidation.java63
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/validations/ParentCertIssuedValidation.java127
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/path/validations/ValidationUtils.java11
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/selector/package.html7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/test/BcCertTest.java2
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cert/test/PKCS10Test.java29
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java39
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java85
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataParser.java41
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java82
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedGenerator.java12
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedData.java65
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataGenerator.java41
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataParser.java22
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataStreamGenerator.java68
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedData.java46
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataGenerator.java129
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataParser.java37
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataStreamGenerator.java116
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedGenerator.java315
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedHelper.java50
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSPBEKey.java73
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java278
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java574
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java367
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataStreamGenerator.java577
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedGenerator.java136
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedHelper.java117
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java112
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java17
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/KEKRecipientInformation.java54
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInformation.java58
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/KeyTransRecipientInformation.java61
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/PKCS5Scheme2PBEKey.java35
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/PKCS5Scheme2UTF8PBEKey.java35
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java90
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/RecipientInformation.java87
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java12
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java130
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/jcajce/CMSUtils.java34
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java71
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceAlgorithmIdentifierConverter.java7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java54
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java28
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java26
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipientInfoGenerator.java27
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java3
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/package.html5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/AllTests.java8
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/AuthenticatedDataStreamTest.java142
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/AuthenticatedDataTest.java308
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/BcSignedDataTest.java41
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/CMSTestUtil.java218
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/CompressedDataStreamTest.java126
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/CompressedDataTest.java150
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/EnvelopedDataStreamTest.java631
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/EnvelopedDataTest.java1002
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/MiscDataStreamTest.java64
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/NewEnvelopedDataTest.java304
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java22
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataTest.java6
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/NullProviderTest.java71
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/Rfc4134Test.java67
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/SignedDataStreamTest.java1158
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/SignedDataTest.java1573
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/cms/test/SunProviderTest.java64
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/dvcs/package.html5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/eac/package.html5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/mozilla/package.html5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/openssl/PEMReader.java1023
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/openssl/PEMWriter.java35
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/openssl/PKCS8Generator.java109
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JcaPEMKeyConverter.java58
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/openssl/package.html5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/openssl/test/AllTests.java109
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/openssl/test/ReaderTest.java417
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/openssl/test/WriterTest.java29
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/BufferingContentSigner.java70
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java (renamed from bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java)29
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java9
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaAlgorithmParametersConverter.java73
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java11
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyWrapper.java34
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java70
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/operator/package.html5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java37
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java4
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/package.html7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/pkcs/package.html7
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/pkcs/test/PfxPduTest.java153
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/TSPUtil.java176
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampRequest.java58
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampResponseGenerator.java80
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampToken.java109
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenGenerator.java333
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/cms/package.html5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/package.html5
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/test/AllTests.java1
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/test/CMSTimeStampedDataGeneratorTest.java14
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/test/NewTSPTest.java6
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/test/ParseTest.java4
-rw-r--r--bcpkix/src/main/java/org/bouncycastle/tsp/test/TSPTest.java603
-rw-r--r--bcprov/src/main/java/org/bouncycastle/LICENSE.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/apache/bzip2/BZip2Constants.java100
-rw-r--r--bcprov/src/main/java/org/bouncycastle/apache/bzip2/CBZip2InputStream.java848
-rw-r--r--bcprov/src/main/java/org/bouncycastle/apache/bzip2/CBZip2OutputStream.java1651
-rw-r--r--bcprov/src/main/java/org/bouncycastle/apache/bzip2/CRC.java131
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java61
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java60
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java55
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cmp/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java58
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java56
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java102
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java35
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Evidence.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java102
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java40
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java53
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/MetaData.java37
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java49
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java44
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java44
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java35
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java59
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java81
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java113
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java46
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java48
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cms/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java119
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java73
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/dvcs/DVCSObjectIdentifiers.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/dvcs/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java119
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/esf/package.html6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ess/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java50
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/icao/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java70
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java26
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java19
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/misc/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/mozilla/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java46
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/nist/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java22
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java33
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ocsp/RevokedInfo.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ocsp/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/oiw/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java156
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java238
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/pkcs/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java84
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/sec/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/smime/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java61
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/teletrust/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/tsp/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java48
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/util/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java51
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java106
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java58
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java98
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java21
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java167
-rw-r--r--bcprov/src/main/java/org/bouncycastle/asn1/x9/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/DigestDerivationFunction.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/MacDerivationFunction.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java50
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/jpake/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/commitments/GeneralHashCommitter.java93
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/commitments/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/SM3Digest.java333
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/SkeinDigest.java116
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/SkeinEngine.java817
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/digests/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalDecryptor.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java71
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/ECPair.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/ECPairFactorTransform.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/ec/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/encodings/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/ChaChaEngine.java186
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/Grain128Engine.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/Grainv1Engine.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/HC128Engine.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/HC256Engine.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/NullEngine.java51
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java253
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/Shacal2Engine.java201
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/TEAEngine.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/ThreefishEngine.java1494
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/VMPCEngine.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/XSalsa20Engine.java65
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/XTEAEngine.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/examples/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFCounterBytesGenerator.java152
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java181
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java175
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/Poly1305KeyGenerator.java117
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java237
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java142
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/io/InvalidCipherTextIOException.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/io/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java71
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/kems/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java38
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java279
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java119
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java142
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java88
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java109
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java269
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java487
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/paddings/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/KDFCounterParameters.java52
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/KDFDoublePipelineIterationParameters.java80
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/KDFFeedbackParameters.java96
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/SkeinParameters.java293
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java40
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECPoints.java82
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java134
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/prng/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java41
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java42
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java46
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java61
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/ECNRSigner.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/HMacDSAKCalculator.java161
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsAgreementCredentials.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCipherFactory.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java77
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsContext.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCredentials.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsEncryptionCredentials.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsPeer.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsServer.java70
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSigner.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSignerCredentials.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/AlertDescription.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/ByteQueue.java68
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/CertChainType.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/Certificate.java64
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateRequest.java72
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatus.java105
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusRequest.java98
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusType.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateURL.java133
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/ChangeCipherSpec.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/CipherSuite.java92
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/CombinedHash.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/ContentType.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java380
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSProtocol.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSRecordLayer.java71
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java78
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSServerProtocol.java186
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java85
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsClient.java138
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsEncryptionCredentials.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsServer.java77
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DeferredHash.java157
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DigestInputBuffer.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/DigitallySigned.java72
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/ExtensionType.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/HandshakeType.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/HashAlgorithm.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatExtension.java56
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessage.java108
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessageType.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMode.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/MACAlgorithm.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/MaxFragmentLength.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/NameType.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/NamedCurve.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/OCSPStatusRequest.java131
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/PSKTlsClient.java176
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/ProtocolVersion.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/RecordStream.java127
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/SRPTlsClient.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerDHParams.java63
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerName.java112
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerNameList.java86
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/SessionParameters.java142
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/SignatureAndHashAlgorithm.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/SignerInputBuffer.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataEntry.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsAEADCipher.java28
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsBlockCipher.java143
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientContextImpl.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java574
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsContext.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java76
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java36
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHUtils.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSASigner.java62
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSSSigner.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java254
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java83
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java77
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDSASigner.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsEncryptionCredentials.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java240
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsHandshakeHash.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsMac.java69
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNullCipher.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java133
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPeer.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsProtocol.java582
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java70
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSASigner.java65
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAUtils.java70
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java68
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRPUtils.java49
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRTPUtils.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServer.java43
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerContextImpl.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerProtocol.java392
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSession.java12
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSessionImpl.java48
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSigner.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSignerCredentials.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsStreamCipher.java69
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsUtils.java413
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/UDPTransport.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/tls/URLAndHash.java104
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java22
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/i18n/LocaleString.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java53
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/io/CipherInputStream.java217
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/io/CipherOutputStream.java147
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java52
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PrivateKey.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PublicKey.java275
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java84
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java39
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java51
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java46
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java304
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java288
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java65
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SM3.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Skein.java740
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java156
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java151
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/CAST6.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Camellia.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/ChaCha.java51
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Noekeon.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java106
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC6.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SEED.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Serpent.java21
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Shacal2.java124
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Threefish.java120
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/XSalsa20.java51
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java130
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/GOST28147ParameterSpec.java108
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/RepeatedSecretKeySpec.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/spec/SkeinParameterSpec.java283
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java65
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/ECPointUtil.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/examples/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/interfaces/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/package.html10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java59
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/AEADTest.java241
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/AESSICTest.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/BlockCipherTest.java207
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/CipherStreamTest.java72
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/CipherStreamTest2.java495
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/DHTest.java55
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/DetDSATest.java152
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/DigestTest.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECDSA5Test.java48
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECEncodingTest.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/GOST28147Test.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/ImplicitlyCaTest.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/OCBTest.java104
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java78
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/Poly1305Test.java150
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/RSATest.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/RegressionTest.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/SerialisationTest.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/Shacal2Test.java154
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/provider/test/SkeinTest.java316
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java67
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java23
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jce/spec/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java24
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java105
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java433
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java493
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java1596
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java39
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java766
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java1995
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java77
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java25
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java31
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java6
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java19
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java34
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java101
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafMultiplier.java240
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java32
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java393
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/math/ec/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/ocsp/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/asn1/PQCObjectIdentifiers.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/BouncyCastlePQCProvider.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Arrays.java140
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java58
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/Shorts.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/encoders/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/util/io/BufferingOutputStream.java108
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/X509Store.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/examples/package.html7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/extension/package.html5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/x509/package.html7
602 files changed, 33480 insertions, 18600 deletions
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509ContentVerifierProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509ContentVerifierProviderBuilder.java
new file mode 100644
index 0000000..af3bd09
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509ContentVerifierProviderBuilder.java
@@ -0,0 +1,14 @@
+package org.bouncycastle.cert;
+
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.operator.ContentVerifierProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+
+public interface X509ContentVerifierProviderBuilder
+{
+ ContentVerifierProvider build(SubjectPublicKeyInfo validatingKeyInfo)
+ throws OperatorCreationException;
+
+ ContentVerifierProvider build(X509CertificateHolder validatingKeyInfo)
+ throws OperatorCreationException;
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/cmp/package.html b/bcpkix/src/main/java/org/bouncycastle/cert/cmp/package.html
deleted file mode 100644
index a58af18..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cert/cmp/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<body bgcolor="#ffffff">
-Basic support package for handling and creating CMP (RFC 4210) certificate management messages.
-</body>
-</html> \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/cmp/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/cert/cmp/test/AllTests.java
index 7ccfd1f..2763083 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/cmp/test/AllTests.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/cmp/test/AllTests.java
@@ -36,6 +36,7 @@ import org.bouncycastle.cert.cmp.CertificateStatus;
import org.bouncycastle.cert.cmp.GeneralPKIMessage;
import org.bouncycastle.cert.cmp.ProtectedPKIMessage;
import org.bouncycastle.cert.cmp.ProtectedPKIMessageBuilder;
+import org.bouncycastle.cert.crmf.CertificateRequestMessage;
import org.bouncycastle.cert.crmf.CertificateRequestMessageBuilder;
import org.bouncycastle.cert.crmf.PKMACBuilder;
import org.bouncycastle.cert.crmf.jcajce.JcaCertificateRequestMessageBuilder;
@@ -224,6 +225,50 @@ public class AllTests
assertEquals(ProofOfPossession.TYPE_KEY_ENCIPHERMENT, reqMsg.getPopo().getType());
}
+ public void testNotBeforeNotAfter()
+ throws Exception
+ {
+ KeyPairGenerator kGen = KeyPairGenerator.getInstance("RSA", BC);
+
+ kGen.initialize(512);
+
+ KeyPair kp = kGen.generateKeyPair();
+
+ doNotBeforeNotAfterTest(kp, new Date(0L), new Date(60000L));
+ doNotBeforeNotAfterTest(kp, null, new Date(60000L));
+ doNotBeforeNotAfterTest(kp, new Date(0L), null);
+ }
+
+ private void doNotBeforeNotAfterTest(KeyPair kp, Date notBefore, Date notAfter)
+ throws Exception
+ {
+ CertificateRequestMessageBuilder builder = new JcaCertificateRequestMessageBuilder(
+ BigInteger.valueOf(1)).setPublicKey(kp.getPublic()).setProofOfPossessionSubsequentMessage(
+ SubsequentMessage.encrCert);
+
+ builder.setValidity(notBefore, notAfter);
+
+ CertificateRequestMessage message = builder.build();
+
+ if (notBefore != null)
+ {
+ assertEquals(notBefore.getTime(), message.getCertTemplate().getValidity().getNotBefore().getDate().getTime());
+ }
+ else
+ {
+ assertNull(message.getCertTemplate().getValidity().getNotBefore());
+ }
+
+ if (notAfter != null)
+ {
+ assertEquals(notAfter.getTime(), message.getCertTemplate().getValidity().getNotAfter().getDate().getTime());
+ }
+ else
+ {
+ assertNull(message.getCertTemplate().getValidity().getNotAfter());
+ }
+ }
+
private static X509CertificateHolder makeV3Certificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN)
throws GeneralSecurityException, IOException, OperatorCreationException, CertException
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/CertificateRequestMessageBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/CertificateRequestMessageBuilder.java
index 0147ffc..aa48235 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/CertificateRequestMessageBuilder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/CertificateRequestMessageBuilder.java
@@ -2,6 +2,7 @@ package org.bouncycastle.cert.crmf;
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -17,6 +18,7 @@ import org.bouncycastle.asn1.crmf.CertReqMsg;
import org.bouncycastle.asn1.crmf.CertRequest;
import org.bouncycastle.asn1.crmf.CertTemplate;
import org.bouncycastle.asn1.crmf.CertTemplateBuilder;
+import org.bouncycastle.asn1.crmf.OptionalValidity;
import org.bouncycastle.asn1.crmf.POPOPrivKey;
import org.bouncycastle.asn1.crmf.ProofOfPossession;
import org.bouncycastle.asn1.crmf.SubsequentMessage;
@@ -24,6 +26,7 @@ import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.ExtensionsGenerator;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.asn1.x509.Time;
import org.bouncycastle.cert.CertIOException;
import org.bouncycastle.operator.ContentSigner;
@@ -90,6 +93,31 @@ public class CertificateRequestMessageBuilder
return this;
}
+ /**
+ * Request a validity period for the certificate. Either, but not both, of the date parameters may be null.
+ *
+ * @param notBeforeDate not before date for certificate requested.
+ * @param notAfterDate not after date for the certificate requested.
+ *
+ * @return the current builder.
+ */
+ public CertificateRequestMessageBuilder setValidity(Date notBeforeDate, Date notAfterDate)
+ {
+ templateBuilder.setValidity(new OptionalValidity(createTime(notBeforeDate), createTime(notAfterDate)));
+
+ return this;
+ }
+
+ private Time createTime(Date date)
+ {
+ if (date != null)
+ {
+ return new Time(date);
+ }
+
+ return null;
+ }
+
public CertificateRequestMessageBuilder addExtension(
ASN1ObjectIdentifier oid,
boolean critical,
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java
index 30cae1e..8747bc0 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/CRMFHelper.java
@@ -42,6 +42,7 @@ import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.cert.crmf.CRMFException;
import org.bouncycastle.cms.CMSAlgorithm;
import org.bouncycastle.jcajce.JcaJceHelper;
+import org.bouncycastle.jcajce.JcaJceUtils;
class CRMFHelper
{
@@ -157,7 +158,9 @@ class CRMFHelper
throw new CRMFException("cannot create key generator: " + e.getMessage(), e);
}
}
-
+
+
+
Cipher createContentCipher(final Key sKey, final AlgorithmIdentifier encryptionAlgID)
throws CRMFException
{
@@ -180,7 +183,7 @@ class CRMFHelper
try
{
- params.init(sParams.getEncoded(), "ASN.1");
+ JcaJceUtils.loadParameters(params, sParams);
}
catch (IOException e)
{
@@ -389,7 +392,7 @@ class CRMFHelper
{
try
{
- asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
+ asn1Params = JcaJceUtils.extractParameters(params);
}
catch (IOException e)
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/package.html b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/package.html
deleted file mode 100644
index e9bc53f..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/jcajce/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<body bgcolor="#ffffff">
-JCA extensions to the CRMF online certificate request package.
-</body>
-</html> \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/package.html b/bcpkix/src/main/java/org/bouncycastle/cert/crmf/package.html
deleted file mode 100644
index 521fc44..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cert/crmf/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<body bgcolor="#ffffff">
-Basic support package for handling and creating CRMF (RFC 4211) certificate request messages.
-</body>
-</html> \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509ContentVerifierProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509ContentVerifierProviderBuilder.java
new file mode 100644
index 0000000..5f4c530
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509ContentVerifierProviderBuilder.java
@@ -0,0 +1,50 @@
+package org.bouncycastle.cert.jcajce;
+
+import java.security.Provider;
+import java.security.cert.CertificateException;
+
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.X509ContentVerifierProviderBuilder;
+import org.bouncycastle.operator.ContentVerifierProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
+
+public class JcaX509ContentVerifierProviderBuilder
+ implements X509ContentVerifierProviderBuilder
+{
+ private JcaContentVerifierProviderBuilder builder = new JcaContentVerifierProviderBuilder();
+
+ public JcaX509ContentVerifierProviderBuilder setProvider(Provider provider)
+ {
+ this.builder.setProvider(provider);
+
+ return this;
+ }
+
+ public JcaX509ContentVerifierProviderBuilder setProvider(String providerName)
+ {
+ this.builder.setProvider(providerName);
+
+ return this;
+ }
+
+ public ContentVerifierProvider build(SubjectPublicKeyInfo validatingKeyInfo)
+ throws OperatorCreationException
+ {
+ return builder.build(validatingKeyInfo);
+ }
+
+ public ContentVerifierProvider build(X509CertificateHolder validatingKeyInfo)
+ throws OperatorCreationException
+ {
+ try
+ {
+ return builder.build(validatingKeyInfo);
+ }
+ catch (CertificateException e)
+ {
+ throw new OperatorCreationException("Unable to process certificate: " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/package.html b/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/package.html
deleted file mode 100644
index cc15e01..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cert/jcajce/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<body bgcolor="#ffffff">
-JCA extensions to the certificate building and processing package.
-</body>
-</html> \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/jcajce/package.html b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/jcajce/package.html
deleted file mode 100644
index cfe87f2..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/jcajce/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<body bgcolor="#ffffff">
-JCA extensions to the OCSP online certificate status package.
-</body>
-</html> \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/package.html b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/package.html
deleted file mode 100644
index 234cb32..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<body bgcolor="#ffffff">
-Basic support package for handling and creating OCSP (RFC 2560) online certificate status requests.
-</body>
-</html> \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/package.html b/bcpkix/src/main/java/org/bouncycastle/cert/package.html
deleted file mode 100644
index 1b2a305..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cert/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Basic support package for handling and creating X.509 certificates, CRLs, and attribute certificates.
-</body>
-</html>
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPath.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPath.java
new file mode 100644
index 0000000..f91b3a8
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPath.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.cert.path;
+
+import org.bouncycastle.cert.X509CertificateHolder;
+
+public class CertPath
+{
+ private final X509CertificateHolder[] certificates;
+
+ public CertPath(X509CertificateHolder[] certificates)
+ {
+ this.certificates = copyArray(certificates);
+ }
+
+ public X509CertificateHolder[] getCertificates()
+ {
+ return copyArray(certificates);
+ }
+
+ public CertPathValidationResult validate(CertPathValidation[] ruleSet)
+ {
+ CertPathValidationContext context = new CertPathValidationContext(CertPathUtils.getCriticalExtensionsOIDs(certificates));
+
+ for (int i = 0; i != ruleSet.length; i++)
+ {
+ for (int j = certificates.length - 1; j >= 0; j--)
+ {
+ try
+ {
+ context.setIsEndEntity(j == 0);
+ ruleSet[i].validate(context, certificates[j]);
+ }
+ catch (CertPathValidationException e)
+ { // TODO: introduce object to hold (i and e)
+ return new CertPathValidationResult(context, j, i, e);
+ }
+ }
+ }
+
+ return new CertPathValidationResult(context);
+ }
+
+ public CertPathValidationResult evaluate(CertPathValidation[] ruleSet)
+ {
+ CertPathValidationContext context = new CertPathValidationContext(CertPathUtils.getCriticalExtensionsOIDs(certificates));
+
+ CertPathValidationResultBuilder builder = new CertPathValidationResultBuilder();
+
+ for (int i = 0; i != ruleSet.length; i++)
+ {
+ for (int j = certificates.length - 1; j >= 0; j--)
+ {
+ try
+ {
+ context.setIsEndEntity(j == 0);
+ ruleSet[i].validate(context, certificates[j]);
+ }
+ catch (CertPathValidationException e)
+ {
+ builder.addException(e);
+ }
+ }
+ }
+
+ return builder.build();
+ }
+
+ private X509CertificateHolder[] copyArray(X509CertificateHolder[] array)
+ {
+ X509CertificateHolder[] rv = new X509CertificateHolder[array.length];
+
+ System.arraycopy(array, 0, rv, 0, rv.length);
+
+ return rv;
+ }
+
+ public int length()
+ {
+ return certificates.length;
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathUtils.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathUtils.java
new file mode 100644
index 0000000..4811a3d
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathUtils.java
@@ -0,0 +1,21 @@
+package org.bouncycastle.cert.path;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.bouncycastle.cert.X509CertificateHolder;
+
+class CertPathUtils
+{
+ static Set getCriticalExtensionsOIDs(X509CertificateHolder[] certificates)
+ {
+ Set criticalExtensions = new HashSet();
+
+ for (int i = 0; i != certificates.length; i++)
+ {
+ criticalExtensions.addAll(certificates[i].getCriticalExtensionOIDs());
+ }
+
+ return criticalExtensions;
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidation.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidation.java
new file mode 100644
index 0000000..2704fe6
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidation.java
@@ -0,0 +1,11 @@
+package org.bouncycastle.cert.path;
+
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.util.Memoable;
+
+public interface CertPathValidation
+ extends Memoable
+{
+ public void validate(CertPathValidationContext context, X509CertificateHolder certificate)
+ throws CertPathValidationException;
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationContext.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationContext.java
new file mode 100644
index 0000000..6a4b0ec
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationContext.java
@@ -0,0 +1,61 @@
+package org.bouncycastle.cert.path;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.util.Memoable;
+
+public class CertPathValidationContext
+ implements Memoable
+{
+ private Set criticalExtensions;
+
+ private Set handledExtensions = new HashSet();
+ private boolean endEntity;
+ private int index;
+
+ public CertPathValidationContext(Set criticalExtensionsOIDs)
+ {
+ this.criticalExtensions = criticalExtensionsOIDs;
+ }
+
+ public void addHandledExtension(ASN1ObjectIdentifier extensionIdentifier)
+ {
+ this.handledExtensions.add(extensionIdentifier);
+ }
+
+ public void setIsEndEntity(boolean isEndEntity)
+ {
+ this.endEntity = isEndEntity;
+ }
+
+ public Set getUnhandledCriticalExtensionOIDs()
+ {
+ Set rv = new HashSet(criticalExtensions);
+
+ rv.removeAll(handledExtensions);
+
+ return rv;
+ }
+
+ /**
+ * Returns true if the current certificate is the end-entity certificate.
+ *
+ * @return if current cert end-entity, false otherwise.
+ */
+ public boolean isEndEntity()
+ {
+ return endEntity;
+ }
+
+ public Memoable copy()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void reset(Memoable other)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationException.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationException.java
new file mode 100644
index 0000000..958f2d0
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationException.java
@@ -0,0 +1,24 @@
+package org.bouncycastle.cert.path;
+
+public class CertPathValidationException
+ extends Exception
+{
+ private final Exception cause;
+
+ public CertPathValidationException(String msg)
+ {
+ this(msg, null);
+ }
+
+ public CertPathValidationException(String msg, Exception cause)
+ {
+ super(msg);
+
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationResult.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationResult.java
new file mode 100644
index 0000000..facefb4
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationResult.java
@@ -0,0 +1,66 @@
+package org.bouncycastle.cert.path;
+
+import java.util.Collections;
+import java.util.Set;
+
+public class CertPathValidationResult
+{
+ private final boolean isValid;
+ private final CertPathValidationException cause;
+ private final Set unhandledCriticalExtensionOIDs;
+
+ private int[] certIndexes;
+
+ public CertPathValidationResult(CertPathValidationContext context)
+ {
+ this.unhandledCriticalExtensionOIDs = Collections.unmodifiableSet(context.getUnhandledCriticalExtensionOIDs());
+ this.isValid = this.unhandledCriticalExtensionOIDs.isEmpty();
+ cause = null;
+ }
+
+ public CertPathValidationResult(CertPathValidationContext context, int certIndex, int ruleIndex, CertPathValidationException cause)
+ {
+ this.unhandledCriticalExtensionOIDs = Collections.unmodifiableSet(context.getUnhandledCriticalExtensionOIDs());
+ this.isValid = false;
+ this.cause = cause;
+ }
+
+ public CertPathValidationResult(CertPathValidationContext context, int[] certIndexes, int[] ruleIndexes, CertPathValidationException[] cause)
+ {
+ // TODO
+ this.unhandledCriticalExtensionOIDs = Collections.unmodifiableSet(context.getUnhandledCriticalExtensionOIDs());
+ this.isValid = false;
+ this.cause = cause[0];
+ this.certIndexes = certIndexes;
+ }
+
+ public boolean isValid()
+ {
+ return isValid;
+ }
+
+ public Exception getCause()
+ {
+ if (cause != null)
+ {
+ return cause;
+ }
+
+ if (!unhandledCriticalExtensionOIDs.isEmpty())
+ {
+ return new CertPathValidationException("Unhandled Critical Extensions");
+ }
+
+ return null;
+ }
+
+ public Set getUnhandledCriticalExtensionOIDs()
+ {
+ return unhandledCriticalExtensionOIDs;
+ }
+
+ public boolean isDetailed()
+ {
+ return this.certIndexes != null;
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationResultBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationResultBuilder.java
new file mode 100644
index 0000000..9e81339
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/CertPathValidationResultBuilder.java
@@ -0,0 +1,14 @@
+package org.bouncycastle.cert.path;
+
+class CertPathValidationResultBuilder
+{
+ public CertPathValidationResult build()
+ {
+ return new CertPathValidationResult(null, 0, 0, null);
+ }
+
+ public void addException(CertPathValidationException exception)
+ {
+ //To change body of created methods use File | Settings | File Templates.
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathTest.java
new file mode 100644
index 0000000..3b8e23e
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathTest.java
@@ -0,0 +1,369 @@
+package org.bouncycastle.cert.path.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.SignatureException;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathBuilder;
+import java.security.cert.CertPathBuilderException;
+import java.security.cert.CertPathBuilderResult;
+import java.security.cert.CertStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CollectionCertStoreParameters;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.test.SimpleTest;
+
+public class CertPathTest
+ extends SimpleTest
+{
+ public static byte[] rootCertBin = Base64.decode(
+ "MIIBqzCCARQCAQEwDQYJKoZIhvcNAQEFBQAwHjEcMBoGA1UEAxMTVGVzdCBDQSBDZXJ0aWZpY2F0ZTAeFw0wODA5MDQwNDQ1MDhaFw0wODA5MTEwNDQ1MDhaMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMRLUjhPe4YUdLo6EcjKcWUOG7CydFTH53Pr1lWjOkbmszYDpkhCTT9LOsI+disk18nkBxSl8DAHTqV+VxtuTPt64iyi10YxyDeep+DwZG/f8cVQv97U3hA9cLurZ2CofkMLGr6JpSGCMZ9FcstcTdHB4lbErIJ54YqfF4pNOs4/AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAgyrTEFY7ALpeY59jL6xFOLpuPqoBOWrUWv6O+zy5BCU0qiX71r3BpigtxRj+DYcfLIM9FNERDoHu3TthD3nwYWUBtFX8N0QUJIdJabxqAMhLjSC744koiFpCYse5Ye3ZvEdFwDzgAQsJTp5eFGgTZPkPzcdhkFJ2p9+OWs+cb24=");
+
+
+ static byte[] interCertBin = Base64.decode(
+ "MIICSzCCAbSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAeMRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlMB4XDTA4MDkwNDA0NDUwOFoXDTA4MDkxMTA0NDUwOFowKDEmMCQGA1UEAxMdVGVzdCBJbnRlcm1lZGlhdGUgQ2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAISS9OOZ2wxzdWny9aVvk4Joq+dwSJ+oqvHUxX3PflZyuiLiCBUOUE4q59dGKdtNX5fIfwyK3cpV0e73Y/0fwfM3m9rOWFrCKOhfeswNTes0w/2PqPVVDDsF/nj7NApuqXwioeQlgTL251RDF4sVoxXqAU7lRkcqwZt3mwqS4KTJAgMBAAGjgY4wgYswRgYDVR0jBD8wPYAUhv8BOT27EB9JaCccJD4YASPP5XWhIqQgMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGWCAQEwHQYDVR0OBBYEFL/IwAGOkHzaQyPZegy79CwM5oTFMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4GBAE4TRgUz4sUvZyVdZxqV+XyNRnqXAeLOOqFGYv2D96tQrS+zjd0elVlT6lFrtchZdOmmX7R6/H/tjMWMcTBICZyRYrvK8cCAmDOI+EIdq5p6lj2Oq6Pbw/wruojAqNrpaR6IkwNpWtdOSSupv4IJL+YU9q2YFTh4R1j3tOkPoFGr");
+
+ static byte[] finalCertBin = Base64.decode(
+ "MIICRjCCAa+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAoMSYwJAYDVQQDEx1UZXN0IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZTAeFw0wODA5MDQwNDQ1MDhaFw0wODA5MTEwNDQ1MDhaMB8xHTAbBgNVBAMTFFRlc3QgRW5kIENlcnRpZmljYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChpUeo0tPYywWKiLlbWKNJBcCpSaLSlaZ+4+yer1AxI5yJIVHP6SAlBghlbD5Qne5ImnN/15cz1xwYAiul6vGKJkVPlFEe2Mr+g/J/WJPQQPsjbZ1G+vxbAwXEDA4KaQrnpjRZFq+CdKHwOjuPLYS/MYQNgdIvDVEQcTbPQ8GaiQIDAQABo4GIMIGFMEYGA1UdIwQ/MD2AFL/IwAGOkHzaQyPZegy79CwM5oTFoSKkIDAeMRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlggEBMB0GA1UdDgQWBBSVkw+VpqBf3zsLc/9GdkK9TzHPwDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDANBgkqhkiG9w0BAQUFAAOBgQBLv/0bVDjzTs/y1vN3FUiZNknEbzupIZduTuXJjqv/vBX+LDPjUfu/+iOCXOSKoRn6nlOWhwB1z6taG2usQkFG8InMkRcPREi2uVgFdhJ/1C3dAWhsdlubjdL926bftXvxnx/koDzyrePW5U96RlOQM2qLvbaky2Giz6hrc3Wl+w==");
+ public static byte[] rootCrlBin = Base64.decode(
+ "MIIBYjCBzAIBATANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlFw0wODA5MDQwNDQ1MDhaFw0wODA5MDQwNzMxNDhaMCIwIAIBAhcNMDgwOTA0MDQ0NTA4WjAMMAoGA1UdFQQDCgEJoFYwVDBGBgNVHSMEPzA9gBSG/wE5PbsQH0loJxwkPhgBI8/ldaEipCAwHjEcMBoGA1UEAxMTVGVzdCBDQSBDZXJ0aWZpY2F0ZYIBATAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOBgQCAbaFCo0BNG4AktVf6jjBLeawP1u0ELYkOCEGvYZE0mBpQ+OvFg7subZ6r3lRIj030nUli28sPFtu5ZQMBNcpE4nS1ziF44RfT3Lp5UgHx9x17Krz781iEyV+7zU8YxYMY9wULD+DCuK294kGKIssVNbmTYXZatBNoXQN5CLIocA==");
+ static byte[] interCrlBin = Base64.decode(
+ "MIIBbDCB1gIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDEx1UZXN0IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZRcNMDgwOTA0MDQ0NTA4WhcNMDgwOTA0MDczMTQ4WjAiMCACAQIXDTA4MDkwNDA0NDUwOFowDDAKBgNVHRUEAwoBCaBWMFQwRgYDVR0jBD8wPYAUv8jAAY6QfNpDI9l6DLv0LAzmhMWhIqQgMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGWCAQEwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADgYEAEVCr5TKs5yguGgLH+dBzmSPoeSIWJFLsgWwJEit/iUDJH3dgYmaczOcGxIDtbYYHLWIHM+P2YRyQz3MEkCXEgm/cx4y7leAmux5l+xQWgmxFPz+197vaphPeCZo+B7V1CWtm518gcq4mrs9ovfgNqgyFj7KGjcBpWdJE32KMt50=");
+
+ /*
+ * certpath with a circular reference
+ */
+ static byte[] certA = Base64.decode(
+ "MIIC6jCCAlOgAwIBAgIBBTANBgkqhkiG9w0BAQUFADCBjTEPMA0GA1UEAxMGSW50"
+ + "ZXIzMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX"
+ + "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq"
+ + "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ2NTda"
+ + "Fw0xNzAzMzAwODQ0MDBaMIGlMScwJQYDVQQDHh4AQQByAG0AaQBuACAASADkAGIA"
+ + "ZQByAGwAaQBuAGcxCzAJBgNVBAYTAkNIMQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNV"
+ + "BAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNwaGVyZSBBRzEQMA4GA1UECxMHVGVzdGlu"
+ + "ZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5AcHJpdmFzcGhlcmUuY29tMIGfMA0GCSqG"
+ + "SIb3DQEBAQUAA4GNADCBiQKBgQCfHfyVs5dbxG35H/Thd29qR4NZU88taCu/OWA1"
+ + "GdACI02lXWYpmLWiDgnU0ULP+GG8OnVp1IES9fz2zcrXKQ19xZzsen/To3h5sNte"
+ + "cJpS00XMM24q/jDwy5NvkBP9YIfFKQ1E/0hFHXcqwlw+b/y/v6YGsZCU2h6QDzc4"
+ + "5m0+BwIDAQABo0AwPjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIE8DAeBglg"
+ + "hkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAJEu"
+ + "KiSfIwsY7SfobMLrv2v/BtLhGLi4RnmjiwzBhuv5rn4rRfBpq1ppmqQMJ2pmA67v"
+ + "UWCY+mNwuyjHyivpCCyJGsZ9d5H09g2vqxzkDBMz7X9VNMZYFH8j/R3/Cfvqks31"
+ + "z0OFslJkeKLa1I0P/dfVHsRKNkLRT3Ws5LKksErQ");
+
+ static byte[] certB = Base64.decode(
+ "MIICtTCCAh6gAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBjTEPMA0GA1UEAxMGSW50"
+ + "ZXIyMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX"
+ + "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq"
+ + "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ2Mzha"
+ + "Fw0xNzAzMzAwODQ0MDBaMIGNMQ8wDQYDVQQDEwZJbnRlcjMxCzAJBgNVBAYTAkNI"
+ + "MQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNVBAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNw"
+ + "aGVyZSBBRzEQMA4GA1UECxMHVGVzdGluZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5A"
+ + "cHJpdmFzcGhlcmUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxCXIB"
+ + "QRnmVvl2h7Q+0SsRxDLnyM1dJG9jMa+UCCmHy0k/ZHs5VirSbjEJSjkQ9BGeh9SC"
+ + "7JwbMpXO7UE+gcVc2RnWUY+MA+fWIeTV4KtkYA8WPu8wVGCXbN8wwh/StOocszxb"
+ + "g+iLvGeh8CYSRqg6QN3S/02etH3o8H4e7Z0PZwIDAQABoyMwITAPBgNVHRMBAf8E"
+ + "BTADAQH/MA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQQFAAOBgQCtWdirSsmt"
+ + "+CBBCNn6ZnbU3QqQfiiQIomjenNEHESJgaS/+PvPE5i3xWFXsunTHLW321/Km16I"
+ + "7+ZvT8Su1cqHg79NAT8QB0yke1saKSy2C0Pic4HwrNqVBWFNSxMU0hQzpx/ZXDbZ"
+ + "DqIXAp5EfyRYBy2ul+jm6Rot6aFgzuopKg==");
+
+ static byte[] certC = Base64.decode(
+ "MIICtTCCAh6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBjTEPMA0GA1UEAxMGSW50"
+ + "ZXIxMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX"
+ + "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq"
+ + "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ0Mzla"
+ + "Fw0xNzAzMzAwODQ0MDBaMIGNMQ8wDQYDVQQDEwZJbnRlcjIxCzAJBgNVBAYTAkNI"
+ + "MQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNVBAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNw"
+ + "aGVyZSBBRzEQMA4GA1UECxMHVGVzdGluZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5A"
+ + "cHJpdmFzcGhlcmUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0rLr6"
+ + "f2/ONeJzTb0q9M/NNX+MnAFMSqiQGVBkT76u5nOH4KLkpHXkzI82JI7GuQMzoT3a"
+ + "+RP1hO6FneO92ms2soC6xiOFb4EC69Dfhh87Nww5O35JxVF0bzmbmIAWd6P/7zGh"
+ + "nd2S4tKkaZcubps+C0j9Fgi0hipVicAOUVVoDQIDAQABoyMwITAPBgNVHRMBAf8E"
+ + "BTADAQH/MA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQQFAAOBgQCLPvc1IMA4"
+ + "YP+PmnEldyUoRWRnvPWjBGeu0WheBP7fdcnGBf93Nmc5j68ZN+eTZ5VMuZ99YdvH"
+ + "CXGNX6oodONLU//LlFKdLl5xjLAS5X9p1RbOEGytnalqeiEpjk4+C/7rIBG1kllO"
+ + "dItmI6LlEMV09Hkpg6ZRAUmRkb8KrM4X7A==");
+
+ static byte[] certD = Base64.decode(
+ "MIICtTCCAh6gAwIBAgIBBjANBgkqhkiG9w0BAQQFADCBjTEPMA0GA1UEAxMGSW50"
+ + "ZXIzMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX"
+ + "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq"
+ + "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ5NTNa"
+ + "Fw0xNzAzMzAwODQ0MDBaMIGNMQ8wDQYDVQQDEwZJbnRlcjExCzAJBgNVBAYTAkNI"
+ + "MQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNVBAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNw"
+ + "aGVyZSBBRzEQMA4GA1UECxMHVGVzdGluZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5A"
+ + "cHJpdmFzcGhlcmUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCae3TP"
+ + "jIVKeASqvNabaiUHAMGUgFxB7L0yUsIj39azLcLtUj4S7XkDf7SMGtYV0JY1XNaQ"
+ + "sHJAsnJivDZc50oiYvqDYfgFZx5+AsN5l5X5rjRzs/OX+Jo+k1OgsIyu6+mf9Kfb"
+ + "5IdWOVB2EcOg4f9tPjLM8CIj9Pp7RbKLyqUUgwIDAQABoyMwITAPBgNVHRMBAf8E"
+ + "BTADAQH/MA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQQFAAOBgQCgr9kUdWUT"
+ + "Lt9UcztSzR3pnHRsyvS0E/z850OKQKS5/VxLEalpFvhj+3EcZ7Y6mFxaaS2B7vXg"
+ + "2YWyqV1PRb6iF7/u9EXkpSTKGrJahwANirCa3V/HTUuPdCE2GITlnWI8h3eVA+xQ"
+ + "D4LF0PXHOkXbwmhXRSb10lW1bSGkUxE9jg==");
+
+ private void testExceptions()
+ throws Exception
+ {
+ byte[] enc = { (byte)0, (byte)2, (byte)3, (byte)4, (byte)5 };
+ MyCertPath mc = new MyCertPath(enc);
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ ByteArrayInputStream is;
+ byte[] arr;
+
+ ObjectOutputStream oOut = new ObjectOutputStream(os);
+ oOut.writeObject(mc);
+ oOut.flush();
+ oOut.close();
+
+ try
+ {
+ CertificateFactory cFac = CertificateFactory.getInstance("X.509",
+ "BC");
+ arr = os.toByteArray();
+ is = new ByteArrayInputStream(arr);
+ cFac.generateCertPath(is);
+ }
+ catch (CertificateException e)
+ {
+ // ignore okay
+ }
+
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ List certCol = new ArrayList();
+
+ certCol.add(cf.generateCertificate(new ByteArrayInputStream(certA)));
+ certCol.add(cf.generateCertificate(new ByteArrayInputStream(certB)));
+ certCol.add(cf.generateCertificate(new ByteArrayInputStream(certC)));
+ certCol.add(cf.generateCertificate(new ByteArrayInputStream(certD)));
+
+ CertPathBuilder pathBuilder = CertPathBuilder.getInstance("PKIX", "BC");
+ X509CertSelector select = new X509CertSelector();
+ select.setSubject(((X509Certificate)certCol.get(0)).getSubjectX500Principal().getEncoded());
+
+ Set trustanchors = new HashSet();
+ trustanchors.add(new TrustAnchor((X509Certificate)cf.generateCertificate(new ByteArrayInputStream(rootCertBin)), null));
+
+ CertStore certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certCol));
+
+ PKIXBuilderParameters params = new PKIXBuilderParameters(trustanchors, select);
+ params.addCertStore(certStore);
+
+ try
+ {
+ CertPathBuilderResult result = pathBuilder.build(params);
+ CertPath path = result.getCertPath();
+ fail("found cert path in circular set");
+ }
+ catch (CertPathBuilderException e)
+ {
+ // expected
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
+
+ X509Certificate rootCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(rootCertBin));
+ X509Certificate interCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(interCertBin));
+ X509Certificate finalCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(finalCertBin));
+
+ //Testing CertPath generation from List
+ List list = new ArrayList();
+ list.add(interCert);
+ CertPath certPath1 = cf.generateCertPath(list);
+
+ //Testing CertPath encoding as PkiPath
+ byte[] encoded = certPath1.getEncoded("PkiPath");
+
+ //Testing CertPath generation from InputStream
+ ByteArrayInputStream inStream = new ByteArrayInputStream(encoded);
+ CertPath certPath2 = cf.generateCertPath(inStream, "PkiPath");
+
+ //Comparing both CertPathes
+ if (!certPath2.equals(certPath1))
+ {
+ fail("CertPath differ after encoding and decoding.");
+ }
+
+ encoded = certPath1.getEncoded("PKCS7");
+
+ //Testing CertPath generation from InputStream
+ inStream = new ByteArrayInputStream(encoded);
+ certPath2 = cf.generateCertPath(inStream, "PKCS7");
+
+ //Comparing both CertPathes
+ if (!certPath2.equals(certPath1))
+ {
+ fail("CertPath differ after encoding and decoding.");
+ }
+
+ encoded = certPath1.getEncoded("PEM");
+
+ //Testing CertPath generation from InputStream
+ inStream = new ByteArrayInputStream(encoded);
+ certPath2 = cf.generateCertPath(inStream, "PEM");
+
+ //Comparing both CertPathes
+ if (!certPath2.equals(certPath1))
+ {
+ fail("CertPath differ after encoding and decoding.");
+ }
+
+ //
+ // empty list test
+ //
+ list = new ArrayList();
+
+ CertPath certPath = CertificateFactory.getInstance("X.509","BC").generateCertPath(list);
+ if (certPath.getCertificates().size() != 0)
+ {
+ fail("list wrong size.");
+ }
+
+ //
+ // exception tests
+ //
+ testExceptions();
+ }
+
+ public String getName()
+ {
+ return "CertPath";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+
+ runTest(new CertPathTest());
+ }
+
+ private static class MyCertificate extends Certificate
+ {
+ private final byte[] encoding;
+
+ public MyCertificate(String type, byte[] encoding)
+ {
+ super(type);
+ // don't copy to allow null parameter in test
+ this.encoding = encoding;
+ }
+
+ public byte[] getEncoded() throws CertificateEncodingException
+ {
+ // do copy to force NPE in test
+ return (byte[])encoding.clone();
+ }
+
+ public void verify(PublicKey key) throws CertificateException,
+ NoSuchAlgorithmException, InvalidKeyException,
+ NoSuchProviderException, SignatureException
+ {
+ }
+
+ public void verify(PublicKey key, String sigProvider)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException,
+ SignatureException
+ {
+ }
+
+ public String toString()
+ {
+ return "[My test Certificate, type: " + getType() + "]";
+ }
+
+ public PublicKey getPublicKey()
+ {
+ return new PublicKey()
+ {
+ public String getAlgorithm()
+ {
+ return "TEST";
+ }
+
+ public byte[] getEncoded()
+ {
+ return new byte[] { (byte)1, (byte)2, (byte)3 };
+ }
+
+ public String getFormat()
+ {
+ return "TEST_FORMAT";
+ }
+ };
+ }
+ }
+
+ private static class MyCertPath extends CertPath
+ {
+ private final Vector certificates;
+
+ private final Vector encodingNames;
+
+ private final byte[] encoding;
+
+ public MyCertPath(byte[] encoding)
+ {
+ super("MyEncoding");
+ this.encoding = encoding;
+ certificates = new Vector();
+ certificates.add(new MyCertificate("MyEncoding", encoding));
+ encodingNames = new Vector();
+ encodingNames.add("MyEncoding");
+ }
+
+ public List getCertificates()
+ {
+ return Collections.unmodifiableList(certificates);
+ }
+
+ public byte[] getEncoded() throws CertificateEncodingException
+ {
+ return (byte[])encoding.clone();
+ }
+
+ public byte[] getEncoded(String encoding)
+ throws CertificateEncodingException
+ {
+ if (getType().equals(encoding))
+ {
+ return (byte[])this.encoding.clone();
+ }
+ throw new CertificateEncodingException("Encoding not supported: "
+ + encoding);
+ }
+
+ public Iterator getEncodings()
+ {
+ return Collections.unmodifiableCollection(encodingNames).iterator();
+ }
+ }
+}
+
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathValidationTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathValidationTest.java
new file mode 100644
index 0000000..a99cb1c
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/test/CertPathValidationTest.java
@@ -0,0 +1,403 @@
+package org.bouncycastle.cert.path.test;
+
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.cert.X509CRLHolder;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.X509ContentVerifierProviderBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509ContentVerifierProviderBuilder;
+import org.bouncycastle.cert.path.CertPath;
+import org.bouncycastle.cert.path.CertPathValidation;
+import org.bouncycastle.cert.path.CertPathValidationResult;
+import org.bouncycastle.cert.path.validations.BasicConstraintsValidation;
+import org.bouncycastle.cert.path.validations.CRLValidation;
+import org.bouncycastle.cert.path.validations.KeyUsageValidation;
+import org.bouncycastle.cert.path.validations.ParentCertIssuedValidation;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.CollectionStore;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.test.SimpleTest;
+
+public class CertPathValidationTest
+ extends SimpleTest
+{
+ private byte[] AC_PR = Base64.decode(
+ "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFU1RDQ0F6R2dBd0lC"
+ + "QWdJQkJUQU5CZ2txaGtpRzl3MEJBUVVGQURDQnRERUxNQWtHQTFVRUJoTUNR"
+ + "bEl4DQpFekFSQmdOVkJBb1RDa2xEVUMxQ2NtRnphV3d4UFRBN0JnTlZCQXNU"
+ + "TkVsdWMzUnBkSFYwYnlCT1lXTnBiMjVoDQpiQ0JrWlNCVVpXTnViMnh2WjJs"
+ + "aElHUmhJRWx1Wm05eWJXRmpZVzhnTFNCSlZFa3hFVEFQQmdOVkJBY1RDRUp5"
+ + "DQpZWE5wYkdsaE1Rc3dDUVlEVlFRSUV3SkVSakV4TUM4R0ExVUVBeE1vUVhW"
+ + "MGIzSnBaR0ZrWlNCRFpYSjBhV1pwDQpZMkZrYjNKaElGSmhhWG9nUW5KaGMy"
+ + "bHNaV2x5WVRBZUZ3MHdNakEwTURReE9UTTVNREJhRncwd05UQTBNRFF5DQpN"
+ + "elU1TURCYU1HRXhDekFKQmdOVkJBWVRBa0pTTVJNd0VRWURWUVFLRXdwSlEx"
+ + "QXRRbkpoYzJsc01UMHdPd1lEDQpWUVFERXpSQmRYUnZjbWxrWVdSbElFTmxj"
+ + "blJwWm1sallXUnZjbUVnWkdFZ1VISmxjMmxrWlc1amFXRWdaR0VnDQpVbVZ3"
+ + "ZFdKc2FXTmhNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJD"
+ + "Z0tDQVFFQXMwc0t5NGsrDQp6b016aldyMTQxeTVYQ045UGJMZERFQXN2cjZ4"
+ + "Z0NCN1l5bEhIQ1NBYmpGR3dOQ0R5NlVxN1h0VjZ6UHdIMXpGDQpFWENlS3Jm"
+ + "UUl5YXBXSEZ4V1VKajBMblFrY1RZM1FOR1huK0JuVk9EVTZDV3M1c3NoZktH"
+ + "RXZyVlQ1Z214V1NmDQp4OFlsdDgzY1dwUE1QZzg3VDlCaHVIbHQzazh2M2Ev"
+ + "NmRPbmF2dytOYTAyZExBaDBlNzZqcCtQUS9LK0pHZlBuDQphQjVVWURrZkd0"
+ + "em5uTTNBV01tY3VJK0o0ek5OMDZaa3ZnbDFsdEo2UU1qcnZEUFlSak9ndDlT"
+ + "cklpY1NmbEo4DQptVDdHWGRRaXJnQUNXc3g1QURBSklRK253TU1vNHlyTUtx"
+ + "SlFhNFFDMHhhT0QvdkdVcG9SaDQzT0FTZFp3c3YvDQpPWFlybmVJeVAwVCs4"
+ + "UUlEQVFBQm80RzNNSUcwTUQwR0ExVWRId1EyTURRd01xQXdvQzZHTEdoMGRI"
+ + "QTZMeTloDQpZM0poYVhvdWFXTndZbkpoYzJsc0xtZHZkaTVpY2k5TVExSmhZ"
+ + "M0poYVhvdVkzSnNNQklHQTFVZElBUUxNQWt3DQpCd1lGWUV3QkFRRXdIUVlE"
+ + "VlIwT0JCWUVGREpUVFlKNE9TWVB5T09KZkVMZXhDaHppK2hiTUI4R0ExVWRJ"
+ + "d1FZDQpNQmFBRklyNjhWZUVFUk0xa0VMNlYwbFVhUTJreFBBM01BNEdBMVVk"
+ + "RHdFQi93UUVBd0lCQmpBUEJnTlZIUk1CDQpBZjhFQlRBREFRSC9NQTBHQ1Nx"
+ + "R1NJYjNEUUVCQlFVQUE0SUJBUUJRUFNoZ1lidnFjaWV2SDVVb3ZMeXhkbkYr"
+ + "DQpFcjlOeXF1SWNkMnZ3Y0N1SnpKMkQ3WDBUcWhHQ0JmUEpVVkdBVWorS0NP"
+ + "SDFCVkgva1l1OUhsVHB1MGtKWFBwDQpBQlZkb2hJUERqRHhkbjhXcFFSL0Yr"
+ + "ejFDaWtVcldIMDR4eTd1N1p6UUpLSlBuR0loY1FpOElyRm1PYkllMEc3DQpY"
+ + "WTZPTjdPRUZxY21KTFFHWWdtRzFXMklXcytQd1JwWTdENGhLVEFoVjFSNkVv"
+ + "amE1L3BPcmVDL09kZXlQWmVxDQo1SUZTOUZZZk02U0Npd2hrK3l2Q1FHbVo0"
+ + "YzE5SjM0ZjVFYkRrK1NQR2tEK25EQ0E3L3VMUWNUMlJURE14SzBaDQpuZlo2"
+ + "Nm1Sc0ZjcXRGaWdScjVFcmtKZDdoUVV6eHNOV0VrNzJEVUFIcVgvNlNjeWtt"
+ + "SkR2V0plSUpqZlcNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg==");
+
+ private byte[] AC_RAIZ_ICPBRASIL = Base64.decode(
+ "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFdURDQ0E2Q2dBd0lC"
+ + "QWdJQkJEQU5CZ2txaGtpRzl3MEJBUVVGQURDQnRERUxNQWtHQTFVRUJoTUNR"
+ + "bEl4DQpFekFSQmdOVkJBb1RDa2xEVUMxQ2NtRnphV3d4UFRBN0JnTlZCQXNU"
+ + "TkVsdWMzUnBkSFYwYnlCT1lXTnBiMjVoDQpiQ0JrWlNCVVpXTnViMnh2WjJs"
+ + "aElHUmhJRWx1Wm05eWJXRmpZVzhnTFNCSlZFa3hFVEFQQmdOVkJBY1RDRUp5"
+ + "DQpZWE5wYkdsaE1Rc3dDUVlEVlFRSUV3SkVSakV4TUM4R0ExVUVBeE1vUVhW"
+ + "MGIzSnBaR0ZrWlNCRFpYSjBhV1pwDQpZMkZrYjNKaElGSmhhWG9nUW5KaGMy"
+ + "bHNaV2x5WVRBZUZ3MHdNVEV4TXpBeE1qVTRNREJhRncweE1URXhNekF5DQpN"
+ + "elU1TURCYU1JRzBNUXN3Q1FZRFZRUUdFd0pDVWpFVE1CRUdBMVVFQ2hNS1NV"
+ + "TlFMVUp5WVhOcGJERTlNRHNHDQpBMVVFQ3hNMFNXNXpkR2wwZFhSdklFNWhZ"
+ + "Mmx2Ym1Gc0lHUmxJRlJsWTI1dmJHOW5hV0VnWkdFZ1NXNW1iM0p0DQpZV05o"
+ + "YnlBdElFbFVTVEVSTUE4R0ExVUVCeE1JUW5KaGMybHNhV0V4Q3pBSkJnTlZC"
+ + "QWdUQWtSR01URXdMd1lEDQpWUVFERXloQmRYUnZjbWxrWVdSbElFTmxjblJw"
+ + "Wm1sallXUnZjbUVnVW1GcGVpQkNjbUZ6YVd4bGFYSmhNSUlCDQpJakFOQmdr"
+ + "cWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBd1BNdWR3WC9odm0r"
+ + "VWgyYi9sUUFjSFZBDQppc2FtYUxrV2Rrd1A5L1MvdE9LSWdSckw2T3krWklH"
+ + "bE9VZGQ2dVl0azlNYS8zcFVwZ2NmTkFqMHZZbTVnc3lqDQpRbzllbXNjK3g2"
+ + "bTRWV3drOWlxTVpTQ0s1RVFrQXEvVXQ0bjdLdUxFMStnZGZ0d2RJZ3hmVXNQ"
+ + "dDRDeU5yWTUwDQpRVjU3S00yVVQ4eDVycm16RWpyN1RJQ0dwU1VBbDJnVnFl"
+ + "NnhhaWkrYm1ZUjFRcm1XYUJTQUc1OUxya3Jqcll0DQpiUmhGYm9VRGUxREsr"
+ + "NlQ4czVMNms4Yzhva3BiSHBhOXZlTXp0RFZDOXNQSjYwTVdYaDZhblZLbzFV"
+ + "Y0xjYlVSDQp5RWVOdlpuZVZSS0FBVTZvdXdkakR2d2xzYUt5ZEZLd2VkMFRv"
+ + "UTQ3Ym1VS2djbSt3VjNlVFJrMzZVT25Ud0lEDQpBUUFCbzRIU01JSFBNRTRH"
+ + "QTFVZElBUkhNRVV3UXdZRllFd0JBUUF3T2pBNEJnZ3JCZ0VGQlFjQ0FSWXNh"
+ + "SFIwDQpjRG92TDJGamNtRnBlaTVwWTNCaWNtRnphV3d1WjI5MkxtSnlMMFJR"
+ + "UTJGamNtRnBlaTV3WkdZd1BRWURWUjBmDQpCRFl3TkRBeW9EQ2dMb1lzYUhS"
+ + "MGNEb3ZMMkZqY21GcGVpNXBZM0JpY21GemFXd3VaMjkyTG1KeUwweERVbUZq"
+ + "DQpjbUZwZWk1amNtd3dIUVlEVlIwT0JCWUVGSXI2OFZlRUVSTTFrRUw2VjBs"
+ + "VWFRMmt4UEEzTUE4R0ExVWRFd0VCDQovd1FGTUFNQkFmOHdEZ1lEVlIwUEFR"
+ + "SC9CQVFEQWdFR01BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQVpBNWMxDQpV"
+ + "L2hnSWg2T2NnTEFmaUpnRldwdm1EWldxbFYzMC9iSEZwajhpQm9iSlNtNXVE"
+ + "cHQ3VGlyWWgxVXhlM2ZRYUdsDQpZakplKzl6ZCtpelBSYkJxWFBWUUEzNEVY"
+ + "Y3drNHFwV3VmMWhIcmlXZmRyeDhBY3FTcXI2Q3VRRndTcjc1Rm9zDQpTemx3"
+ + "REFEYTcwbVQ3d1pqQW1RaG5aeDJ4SjZ3ZldsVDlWUWZTLy9KWWVJYzdGdWUy"
+ + "Sk5MZDAwVU9TTU1haUsvDQp0NzllbktOSEVBMmZ1cEgzdkVpZ2Y1RWg0YlZB"
+ + "TjVWb2hyVG02TVk1M3g3WFFaWnIxTUU3YTU1bEZFblNlVDB1DQptbE9BalIy"
+ + "bUFidlNNNVg1b1NaTnJtZXRkenlUajJmbENNOENDN01MYWIwa2tkbmdSSWxV"
+ + "QkdIRjEvUzVubVBiDQpLKzlBNDZzZDMzb3FLOG44DQotLS0tLUVORCBDRVJU"
+ + "SUZJQ0FURS0tLS0tDQo=");
+
+ private byte[] schefer = Base64.decode(
+ "MIIEnDCCBAWgAwIBAgICIPAwDQYJKoZIhvcNAQEEBQAwgcAxCzAJBgNVBAYT"
+ + "AkRFMQ8wDQYDVQQIEwZIRVNTRU4xGDAWBgNVBAcTDzY1MDA4IFdpZXNiYWRl"
+ + "bjEaMBgGA1UEChMRU0NIVUZBIEhPTERJTkcgQUcxGjAYBgNVBAsTEVNDSFVG"
+ + "QSBIT0xESU5HIEFHMSIwIAYDVQQDExlJbnRlcm5ldCBCZW51dHplciBTZXJ2"
+ + "aWNlMSowKAYJKoZIhvcNAQkBFht6ZXJ0aWZpa2F0QHNjaHVmYS1vbmxpbmUu"
+ + "ZGUwHhcNMDQwMzMwMTEwODAzWhcNMDUwMzMwMTEwODAzWjCBnTELMAkGA1UE"
+ + "BhMCREUxCjAIBgNVBAcTASAxIzAhBgNVBAoTGlNIUyBJbmZvcm1hdGlvbnNz"
+ + "eXN0ZW1lIEFHMRwwGgYDVQQLExM2MDAvMDU5NDktNjAwLzA1OTQ5MRgwFgYD"
+ + "VQQDEw9TY2hldHRlciBTdGVmYW4xJTAjBgkqhkiG9w0BCQEWFlN0ZWZhbi5T"
+ + "Y2hldHRlckBzaHMuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJD0"
+ + "95Bi76fkAMjJNTGPDiLPHmZXNsmakngDeS0juzKMeJA+TjXFouhYh6QyE4Bl"
+ + "Nf18fT4mInlgLefwf4t6meIWbiseeTo7VQdM+YrbXERMx2uHsRcgZMsiMYHM"
+ + "kVfYMK3SMJ4nhCmZxrBkoTRed4gXzVA1AA8YjjTqMyyjvt4TAgMBAAGjggHE"
+ + "MIIBwDAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIEsDALBgNVHQ8EBAMC"
+ + "BNAwOQYJYIZIAYb4QgENBCwWKlplcnRpZmlrYXQgbnVyIGZ1ZXIgU0NIVUZB"
+ + "LU9ubGluZSBndWVsdGlnLjAdBgNVHQ4EFgQUXReirhBfg0Yhf6MsBWoo/nPa"
+ + "hGwwge0GA1UdIwSB5TCB4oAUf2UyCaBV9JUeG9lS1Yo6OFBUdEKhgcakgcMw"
+ + "gcAxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZIRVNTRU4xGDAWBgNVBAcTDzY1"
+ + "MDA4IFdpZXNiYWRlbjEaMBgGA1UEChMRU0NIVUZBIEhPTERJTkcgQUcxGjAY"
+ + "BgNVBAsTEVNDSFVGQSBIT0xESU5HIEFHMSIwIAYDVQQDExlJbnRlcm5ldCBC"
+ + "ZW51dHplciBTZXJ2aWNlMSowKAYJKoZIhvcNAQkBFht6ZXJ0aWZpa2F0QHNj"
+ + "aHVmYS1vbmxpbmUuZGWCAQAwIQYDVR0RBBowGIEWU3RlZmFuLlNjaGV0dGVy"
+ + "QHNocy5kZTAmBgNVHRIEHzAdgRt6ZXJ0aWZpa2F0QHNjaHVmYS1vbmxpbmUu"
+ + "ZGUwDQYJKoZIhvcNAQEEBQADgYEAWzZtN9XQ9uyrFXqSy3hViYwV751+XZr0"
+ + "YH5IFhIS+9ixNAu8orP3bxqTaMhpwoU7T/oSsyGGSkb3fhzclgUADbA2lrOI"
+ + "GkeB/m+FArTwRbwpqhCNTwZywOp0eDosgPjCX1t53BB/m/2EYkRiYdDGsot0"
+ + "kQPOVGSjQSQ4+/D+TM8=");
+
+ // circular dependency certificates
+ private static final byte[] circCA = Base64.decode(
+ "MIIDTzCCAjegAwIBAgIDARAAMA0GCSqGSIb3DQEBBQUAMDkxCzAJBgNVBAYT"
+ + "AkZSMRAwDgYDVQQKEwdHSVAtQ1BTMRgwFgYDVQQLEw9HSVAtQ1BTIEFOT05Z"
+ + "TUUwHhcNMDQxMDExMDAwMDAxWhcNMTQxMjMxMjM1OTU5WjA5MQswCQYDVQQG"
+ + "EwJGUjEQMA4GA1UEChMHR0lQLUNQUzEYMBYGA1UECxMPR0lQLUNQUyBBTk9O"
+ + "WU1FMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3WyWDwcM58aU"
+ + "hPX4ueI1mwETt3WdQtMfIdRiCXeBrjCkYCc7nIgCmGbnfTzXSplHRgKColWh"
+ + "q/Z+1rHYayje1gjAEU2+4/r1P2pnBmPgquDuguktCIbDtCcGZu0ylyKeHh37"
+ + "aeIKzkcmRSLRzvGf/eO3RdFksrvaPaSjqCVfGRXVDKK2uftE8rIFJE+bCqow"
+ + "6+WiaAaDDiJaSJPuu5hC1NA5jw0/BFodlCuAvl1GJ8A+TICkYWcSpKS9bkSC"
+ + "0i8xdGbSSk94shA1PdDvRdFMfFys8g4aupBXV8yqqEAUkBYmOtZSJckc3W4y"
+ + "2Gx53y7vY07Xh63mcgtJs2T82WJICwIDAQABo2AwXjAdBgNVHQ4EFgQU8c/P"
+ + "NNJaL0srd9SwHwgtvwPB/3cwDgYDVR0PAQH/BAQDAgIEMBkGA1UdIAQSMBAw"
+ + "DgYMKoF6AUcDBwgAAAABMBIGA1UdEwEB/wQIMAYBAf8CAQEwDQYJKoZIhvcN"
+ + "AQEFBQADggEBAHRjYDPJKlfUzID0YzajZpgR/i2ngJrJqYeaWCmwzBgNUPad"
+ + "uBKSGHmPVg21sfULMSnirnR+e90i/D0EVzLwQzcbjPDD/85rp9QDCeMxqqPe"
+ + "9ZCHGs2BpE/HOQMP0QfQ3/Kpk7SvOH/ZcpIf6+uE6lLBQYAGs5cxvtTGOzZk"
+ + "jCVFG+TrAnF4V5sNkn3maCWiYLmyqcnxtKEFSONy2bYqqudx/dBBlRrDbRfZ"
+ + "9XsCBdiXAHY1hFHldbfDs8rslmkXJi3fJC028HZYB6oiBX/JE7BbMk7bRnUf"
+ + "HSpP7Sjxeso2SY7Yit+hQDVAlqTDGmh6kLt/hQMpsOMry4vgBL6XHKw=");
+
+ private static final byte[] circCRLCA = Base64.decode(
+ "MIIDXDCCAkSgAwIBAgIDASAAMA0GCSqGSIb3DQEBBQUAMDkxCzAJBgNVBAYT"
+ + "AkZSMRAwDgYDVQQKEwdHSVAtQ1BTMRgwFgYDVQQLEw9HSVAtQ1BTIEFOT05Z"
+ + "TUUwHhcNMDQxMDExMDAwMDAxWhcNMTQxMjMxMjM1OTU5WjA5MQswCQYDVQQG"
+ + "EwJGUjEQMA4GA1UEChMHR0lQLUNQUzEYMBYGA1UECxMPR0lQLUNQUyBBTk9O"
+ + "WU1FMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwfEcFK0g7Kfo"
+ + "o5f2IBF7VEd/AG+RVGSds0Yg+u2kNYu4k04HR/+tOdBQtJvyr4W5jrQKsC5X"
+ + "skeFWMyWaFKzAjZDWB52HWp/kiMivGcxnYDuYf5piukSC+d2+vL8YaAphDzV"
+ + "HPnxEKqoM/J66uUussDTqfcL3JC/Bc7kBwn4srrsZOsamMWTQQtEqVQxNN7A"
+ + "ROSRsdiTt3hMOKditc9/NBNmjZWxgc7Twr/SaZ8CfN5wf2wuOl23knWL0QsJ"
+ + "0lSMBSBTzTcfAke4/jIT7d4nVMp3t7dsna8rt56pFK4wpRFGuCt+1P5gi51x"
+ + "xVSdI+JoNXv6zGO4o8YVaRpC5rQeGQIDAQABo20wazAfBgNVHSMEGDAWgBTx"
+ + "z8800lovSyt31LAfCC2/A8H/dzAdBgNVHQ4EFgQUGa3SbBrJx/wa2MQwhWPl"
+ + "dwLw1+IwDgYDVR0PAQH/BAQDAgECMBkGA1UdIAQSMBAwDgYMKoF6AUcDBwgA"
+ + "AAABMA0GCSqGSIb3DQEBBQUAA4IBAQAPDpYe2WPYnXTLsXSIUREBNMLmg+/7"
+ + "4Yhq9uOm5Hb5LVkDuHoEHGfmpXXEvucx5Ehu69hw+F4YSrd9wPjOiG8G6GXi"
+ + "RcrK8nE8XDvvV+E1HpJ7NKN4fSAoSb+0gliiq3aF15bvXP8nfespdd/x1xWQ"
+ + "mpYCx/mJeuqONQv2/D/7hfRKYoDBaAkWGodenPFPVs6FxwnEuH2R+KWCUdA9"
+ + "L04v8JBeL3kZiALkU7+DCCm7A0imUAgeeArbAbfIPu6eDygm+XndZ9qi7o4O"
+ + "AntPxrqbeXFIbDrQ4GV1kpxnW+XpSGDd96SWKe715gxkkDBppR5IKYJwRb6O"
+ + "1TRQIf2F+muQ");
+
+ private static final byte[] circCRL = Base64.decode(
+ "MIIB1DCBvQIBATANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGUjEQMA4G"
+ + "A1UEChMHR0lQLUNQUzEYMBYGA1UECxMPR0lQLUNQUyBBTk9OWU1FFw0xMDAx"
+ + "MDcwMzAwMTVaFw0xMDAxMTMwMzAwMTVaMACgTjBMMB8GA1UdIwQYMBaAFBmt"
+ + "0mwaycf8GtjEMIVj5XcC8NfiMAsGA1UdFAQEAgILgzAcBgNVHRIEFTATgRFh"
+ + "Yy1naXBAZ2lwLWNwcy5mcjANBgkqhkiG9w0BAQUFAAOCAQEAtF1DdFl1MQvf"
+ + "vNkbrCPuppNYcHen4+za/ZDepKuwHsH/OpKuaDJc4LndRgd5IwzfpCHkQGzt"
+ + "shK50bakN8oaYJgthKIOIJzR+fn6NMjftfR2a27Hdk2o3eQXRHQ360qMbpSy"
+ + "qPb3WfuBhxO2/DlLChJP+OxZIHtT/rNYgE0tlIv7swYi81Gq+DafzaZ9+A5t"
+ + "I0L2Gp/NUDsp5dF6PllAGiXQzl27qkcu+r50w+u0gul3nobXgbwPcMSYuWUz"
+ + "1lhA+uDn/EUWV4RSiJciCGSS10WCkFh1/YPo++mV15KDB0m+8chscrSu/bAl"
+ + "B19LxL/pCX3qr5iLE9ss3olVImyFZg==");
+
+// private void checkCircProcessing()
+// throws Exception
+// {
+// CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
+//
+// X509Certificate caCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(circCA));
+// X509Certificate crlCaCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(circCRLCA));
+// X509CRL crl = (X509CRL)cf.generateCRL(new ByteArrayInputStream(circCRL));
+//
+// List list = new ArrayList();
+//
+// list.add(caCert);
+// list.add(crlCaCert);
+// list.add(crl);
+//
+// CertStoreParameters ccsp = new CollectionCertStoreParameters(list);
+// CertStore store = CertStore.getInstance("Collection", ccsp);
+//
+// Calendar validDate = Calendar.getInstance();
+// validDate.set(2010,0,8,2,21,10);
+//
+// //validating path
+// List certchain = new ArrayList();
+//
+// certchain.add(crlCaCert);
+// CertPath cp = CertificateFactory.getInstance("X.509","BC").generateCertPath(certchain);
+//
+// Set trust = new HashSet();
+// trust.add(new TrustAnchor(caCert, null));
+//
+// CertPathValidator cpv = CertPathValidator.getInstance("PKIX","BC");
+// //PKIXParameters param = new PKIXParameters(trust);
+//
+// PKIXBuilderParameters param = new PKIXBuilderParameters(trust, null);
+// X509CertSelector certSelector = new X509CertSelector();
+// certSelector.setCertificate(crlCaCert);
+// param.setTargetCertConstraints(certSelector);
+// param.addCertStore(store);
+// param.setRevocationEnabled(true);
+// param.setDate(validDate.getTime());
+//
+// PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult)cpv.validate(cp, param);
+// }
+
+ public void performTest()
+ throws Exception
+ {
+ // initialise CertStore
+ X509CertificateHolder rootCert = new X509CertificateHolder(CertPathTest.rootCertBin);
+ X509CertificateHolder interCert = new X509CertificateHolder(CertPathTest.interCertBin);
+ X509CertificateHolder finalCert = new X509CertificateHolder(CertPathTest.finalCertBin);
+ X509CRLHolder rootCrl = new X509CRLHolder(CertPathTest.rootCrlBin);
+ X509CRLHolder interCrl = new X509CRLHolder(CertPathTest.interCrlBin);
+
+ CertPath path = new CertPath(new X509CertificateHolder[] { finalCert, interCert });
+ X509ContentVerifierProviderBuilder verifier = new JcaX509ContentVerifierProviderBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME);
+
+ CertPathValidationResult result = path.validate(new CertPathValidation[]{new ParentCertIssuedValidation(verifier), new BasicConstraintsValidation(), new KeyUsageValidation()});
+
+ if (!result.isValid())
+ {
+ fail("basic validation (1) not working");
+ }
+
+ List crlList = new ArrayList();
+
+ crlList.add(rootCrl);
+ crlList.add(interCrl);
+
+ Store crls = new CollectionStore(crlList);
+
+ result = path.validate(new CertPathValidation[]{new ParentCertIssuedValidation(verifier), new BasicConstraintsValidation(), new KeyUsageValidation(), new CRLValidation(rootCert.getSubject(), crls)});
+
+ if (!result.isValid())
+ {
+ fail("basic validation (2) not working");
+ }
+
+ result = path.validate(new CertPathValidation[]{new ParentCertIssuedValidation(verifier), new KeyUsageValidation(), new CRLValidation(rootCert.getSubject(), crls)});
+
+ if (result.isValid() || result.getUnhandledCriticalExtensionOIDs().size() != 1
+ || !result.getUnhandledCriticalExtensionOIDs().contains(Extension.basicConstraints))
+ {
+ fail("basic validation (3) not working");
+ }
+
+ result = path.validate(new CertPathValidation[]{new ParentCertIssuedValidation(verifier), new CRLValidation(rootCert.getSubject(), crls)});
+
+ if (result.isValid() || result.getUnhandledCriticalExtensionOIDs().size() != 2
+ || !result.getUnhandledCriticalExtensionOIDs().contains(Extension.basicConstraints)
+ || !result.getUnhandledCriticalExtensionOIDs().contains(Extension.keyUsage))
+ {
+ fail("basic validation (4) not working");
+ }
+
+ path = new CertPath(new X509CertificateHolder[] { interCert, finalCert });
+
+ result = path.validate(new CertPathValidation[]{new ParentCertIssuedValidation(verifier)});
+
+ if (result.isValid())
+ {
+ fail("incorrect path validated!!");
+ }
+
+
+
+// List list = new ArrayList();
+// list.add(rootCert);
+// list.add(interCert);
+// list.add(finalCert);
+// list.add(rootCrl);
+// list.add(interCrl);
+// CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list);
+// CertStore store = CertStore.getInstance("Collection", ccsp, "BC");
+// Calendar validDate = Calendar.getInstance();
+// validDate.set(2008,8,4,14,49,10);
+// //validating path
+// List certchain = new ArrayList();
+// certchain.add(finalCert);
+// certchain.add(interCert);
+// CertPath cp = CertificateFactory.getInstance("X.509","BC").generateCertPath(certchain);
+// Set trust = new HashSet();
+// trust.add(new TrustAnchor(rootCert, null));
+//
+// CertPathValidator cpv = CertPathValidator.getInstance("PKIX","BC");
+// PKIXParameters param = new PKIXParameters(trust);
+// param.addCertStore(store);
+// param.setDate(validDate.getTime());
+// MyChecker checker = new MyChecker();
+// param.addCertPathChecker(checker);
+//
+// PKIXCertPathValidatorResult result =
+// (PKIXCertPathValidatorResult) cpv.validate(cp, param);
+// PolicyNode policyTree = result.getPolicyTree();
+// PublicKey subjectPublicKey = result.getPublicKey();
+//
+// if (checker.getCount() != 2)
+// {
+// fail("checker not evaluated for each certificate");
+// }
+//
+// if (!subjectPublicKey.equals(finalCert.getPublicKey()))
+// {
+// fail("wrong public key returned");
+// }
+//
+// //
+// // invalid path containing a valid one test
+// //
+// try
+// {
+// // initialise CertStore
+// rootCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(AC_RAIZ_ICPBRASIL));
+// interCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(AC_PR));
+// finalCert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(schefer));
+//
+// list = new ArrayList();
+// list.add(rootCert);
+// list.add(interCert);
+// list.add(finalCert);
+//
+// ccsp = new CollectionCertStoreParameters(list);
+// store = CertStore.getInstance("Collection", ccsp);
+// validDate = Calendar.getInstance();
+// validDate.set(2004,2,21,2,21,10);
+//
+// //validating path
+// certchain = new ArrayList();
+// certchain.add(finalCert);
+// certchain.add(interCert);
+// cp = CertificateFactory.getInstance("X.509","BC").generateCertPath(certchain);
+// trust = new HashSet();
+// trust.add(new TrustAnchor(rootCert, null));
+//
+// cpv = CertPathValidator.getInstance("PKIX","BC");
+// param = new PKIXParameters(trust);
+// param.addCertStore(store);
+// param.setRevocationEnabled(false);
+// param.setDate(validDate.getTime());
+//
+// result =(PKIXCertPathValidatorResult) cpv.validate(cp, param);
+// policyTree = result.getPolicyTree();
+// subjectPublicKey = result.getPublicKey();
+//
+// fail("Invalid path validated");
+// }
+// catch (Exception e)
+// {
+// if (!(e instanceof CertPathValidatorException
+// && e.getMessage().startsWith("Could not validate certificate signature.")))
+// {
+// fail("unexpected exception", e);
+// }
+// }
+//
+// checkCircProcessing();
+ }
+
+ public String getName()
+ {
+ return "CertPathValidator";
+ }
+
+ public static void main(
+ String[] args)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+
+ runTest(new CertPathValidationTest());
+ }
+}
+
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/BasicConstraintsValidation.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/BasicConstraintsValidation.java
new file mode 100644
index 0000000..db4f852
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/BasicConstraintsValidation.java
@@ -0,0 +1,103 @@
+package org.bouncycastle.cert.path.validations;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.path.CertPathValidation;
+import org.bouncycastle.cert.path.CertPathValidationContext;
+import org.bouncycastle.cert.path.CertPathValidationException;
+import org.bouncycastle.util.Memoable;
+
+public class BasicConstraintsValidation
+ implements CertPathValidation
+{
+ private boolean isMandatory;
+ private BasicConstraints bc;
+ private int maxPathLength;
+
+ public BasicConstraintsValidation()
+ {
+ this(true);
+ }
+
+ public BasicConstraintsValidation(boolean isMandatory)
+ {
+ this.isMandatory = isMandatory;
+ }
+
+ public void validate(CertPathValidationContext context, X509CertificateHolder certificate)
+ throws CertPathValidationException
+ {
+ if (maxPathLength < 0)
+ {
+ throw new CertPathValidationException("BasicConstraints path length exceeded");
+ }
+
+ context.addHandledExtension(Extension.basicConstraints);
+
+ BasicConstraints certBC = BasicConstraints.fromExtensions(certificate.getExtensions());
+
+ if (certBC != null)
+ {
+ if (bc != null)
+ {
+ if (certBC.isCA())
+ {
+ BigInteger pathLengthConstraint = certBC.getPathLenConstraint();
+
+ if (pathLengthConstraint != null)
+ {
+ int plc = pathLengthConstraint.intValue();
+
+ if (plc < maxPathLength)
+ {
+ maxPathLength = plc;
+ bc = certBC;
+ }
+ }
+ }
+ }
+ else
+ {
+ bc = certBC;
+ if (certBC.isCA())
+ {
+ maxPathLength = certBC.getPathLenConstraint().intValue();
+ }
+ }
+ }
+ else
+ {
+ if (bc != null)
+ {
+ maxPathLength--;
+ }
+ }
+
+ if (isMandatory && bc == null)
+ {
+ throw new CertPathValidationException("BasicConstraints not present in path");
+ }
+ }
+
+ public Memoable copy()
+ {
+ BasicConstraintsValidation v = new BasicConstraintsValidation(isMandatory);
+
+ v.bc = this.bc;
+ v.maxPathLength = this.maxPathLength;
+
+ return v;
+ }
+
+ public void reset(Memoable other)
+ {
+ BasicConstraintsValidation v = (BasicConstraintsValidation)other;
+
+ this.isMandatory = v.isMandatory;
+ this.bc = v.bc;
+ this.maxPathLength = v.maxPathLength;
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CRLValidation.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CRLValidation.java
new file mode 100644
index 0000000..c44b7c0
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CRLValidation.java
@@ -0,0 +1,78 @@
+package org.bouncycastle.cert.path.validations;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.cert.X509CRLHolder;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.path.CertPathValidation;
+import org.bouncycastle.cert.path.CertPathValidationContext;
+import org.bouncycastle.cert.path.CertPathValidationException;
+import org.bouncycastle.util.Memoable;
+import org.bouncycastle.util.Selector;
+import org.bouncycastle.util.Store;
+
+public class CRLValidation
+ implements CertPathValidation
+{
+ private Store crls;
+ private X500Name workingIssuerName;
+
+ public CRLValidation(X500Name trustAnchorName, Store crls)
+ {
+ this.workingIssuerName = trustAnchorName;
+ this.crls = crls;
+ }
+
+ public void validate(CertPathValidationContext context, X509CertificateHolder certificate)
+ throws CertPathValidationException
+ {
+ // TODO: add handling of delta CRLs
+ Collection matches = crls.getMatches(new Selector()
+ {
+ public boolean match(Object obj)
+ {
+ X509CRLHolder crl = (X509CRLHolder)obj;
+
+ return (crl.getIssuer().equals(workingIssuerName));
+ }
+
+ public Object clone()
+ {
+ return this;
+ }
+ });
+
+ if (matches.isEmpty())
+ {
+ throw new CertPathValidationException("CRL for " + workingIssuerName + " not found");
+ }
+
+ for (Iterator it = matches.iterator(); it.hasNext();)
+ {
+ X509CRLHolder crl = (X509CRLHolder)it.next();
+
+ // TODO: not quite right!
+ if (crl.getRevokedCertificate(certificate.getSerialNumber()) != null)
+ {
+ throw new CertPathValidationException("Certificate revoked");
+ }
+ }
+
+ this.workingIssuerName = certificate.getSubject();
+ }
+
+ public Memoable copy()
+ {
+ return new CRLValidation(workingIssuerName, crls);
+ }
+
+ public void reset(Memoable other)
+ {
+ CRLValidation v = (CRLValidation)other;
+
+ this.workingIssuerName = v.workingIssuerName;
+ this.crls = v.crls;
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CertificatePoliciesValidation.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CertificatePoliciesValidation.java
new file mode 100644
index 0000000..ebaf989
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CertificatePoliciesValidation.java
@@ -0,0 +1,146 @@
+package org.bouncycastle.cert.path.validations;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.PolicyConstraints;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.path.CertPathValidation;
+import org.bouncycastle.cert.path.CertPathValidationContext;
+import org.bouncycastle.cert.path.CertPathValidationException;
+import org.bouncycastle.util.Memoable;
+
+public class CertificatePoliciesValidation
+ implements CertPathValidation
+{
+ private int explicitPolicy;
+ private int policyMapping;
+ private int inhibitAnyPolicy;
+
+ CertificatePoliciesValidation(int pathLength)
+ {
+ this(pathLength, false, false, false);
+ }
+
+ CertificatePoliciesValidation(int pathLength, boolean isExplicitPolicyRequired, boolean isAnyPolicyInhibited, boolean isPolicyMappingInhibited)
+ {
+ //
+ // (d)
+ //
+
+ if (isExplicitPolicyRequired)
+ {
+ explicitPolicy = 0;
+ }
+ else
+ {
+ explicitPolicy = pathLength + 1;
+ }
+
+ //
+ // (e)
+ //
+ if (isAnyPolicyInhibited)
+ {
+ inhibitAnyPolicy = 0;
+ }
+ else
+ {
+ inhibitAnyPolicy = pathLength + 1;
+ }
+
+ //
+ // (f)
+ //
+ if (isPolicyMappingInhibited)
+ {
+ policyMapping = 0;
+ }
+ else
+ {
+ policyMapping = pathLength + 1;
+ }
+ }
+
+ public void validate(CertPathValidationContext context, X509CertificateHolder certificate)
+ throws CertPathValidationException
+ {
+ context.addHandledExtension(Extension.policyConstraints);
+ context.addHandledExtension(Extension.inhibitAnyPolicy);
+
+ if (!context.isEndEntity())
+ {
+ if (!ValidationUtils.isSelfIssued(certificate))
+ {
+ //
+ // H (1), (2), (3)
+ //
+ explicitPolicy = countDown(explicitPolicy);
+ policyMapping = countDown(policyMapping);
+ inhibitAnyPolicy = countDown(inhibitAnyPolicy);
+
+ //
+ // I (1), (2)
+ //
+ PolicyConstraints policyConstraints = PolicyConstraints.fromExtensions(certificate.getExtensions());
+
+ if (policyConstraints != null)
+ {
+ BigInteger requireExplicitPolicyMapping = policyConstraints.getRequireExplicitPolicyMapping();
+ if (requireExplicitPolicyMapping != null)
+ {
+ if (requireExplicitPolicyMapping.intValue() < explicitPolicy)
+ {
+ explicitPolicy = requireExplicitPolicyMapping.intValue();
+ }
+ }
+
+ BigInteger inhibitPolicyMapping = policyConstraints.getInhibitPolicyMapping();
+ if (inhibitPolicyMapping != null)
+ {
+ if (inhibitPolicyMapping.intValue() < policyMapping)
+ {
+ policyMapping = inhibitPolicyMapping.intValue();
+ }
+ }
+ }
+
+ //
+ // J
+ //
+ Extension ext = certificate.getExtension(Extension.inhibitAnyPolicy);
+
+ if (ext != null)
+ {
+ int extValue = ASN1Integer.getInstance(ext.getParsedValue()).getValue().intValue();
+
+ if (extValue < inhibitAnyPolicy)
+ {
+ inhibitAnyPolicy = extValue;
+ }
+ }
+ }
+ }
+ }
+
+ private int countDown(int policyCounter)
+ {
+ if (policyCounter != 0)
+ {
+ return policyCounter - 1;
+ }
+
+ return 0;
+ }
+
+ public Memoable copy()
+ {
+ return new CertificatePoliciesValidation(0); // TODO:
+ }
+
+ public void reset(Memoable other)
+ {
+ CertificatePoliciesValidation v = (CertificatePoliciesValidation)other; // TODO:
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CertificatePoliciesValidationBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CertificatePoliciesValidationBuilder.java
new file mode 100644
index 0000000..74b622e
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/CertificatePoliciesValidationBuilder.java
@@ -0,0 +1,35 @@
+package org.bouncycastle.cert.path.validations;
+
+import org.bouncycastle.cert.path.CertPath;
+
+public class CertificatePoliciesValidationBuilder
+{
+ private boolean isExplicitPolicyRequired;
+ private boolean isAnyPolicyInhibited;
+ private boolean isPolicyMappingInhibited;
+
+ public void setAnyPolicyInhibited(boolean anyPolicyInhibited)
+ {
+ isAnyPolicyInhibited = anyPolicyInhibited;
+ }
+
+ public void setExplicitPolicyRequired(boolean explicitPolicyRequired)
+ {
+ isExplicitPolicyRequired = explicitPolicyRequired;
+ }
+
+ public void setPolicyMappingInhibited(boolean policyMappingInhibited)
+ {
+ isPolicyMappingInhibited = policyMappingInhibited;
+ }
+
+ public CertificatePoliciesValidation build(int pathLen)
+ {
+ return new CertificatePoliciesValidation(pathLen, isExplicitPolicyRequired, isAnyPolicyInhibited, isPolicyMappingInhibited);
+ }
+
+ public CertificatePoliciesValidation build(CertPath path)
+ {
+ return build(path.length());
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/KeyUsageValidation.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/KeyUsageValidation.java
new file mode 100644
index 0000000..5d9adc8
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/KeyUsageValidation.java
@@ -0,0 +1,63 @@
+package org.bouncycastle.cert.path.validations;
+
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.path.CertPathValidation;
+import org.bouncycastle.cert.path.CertPathValidationContext;
+import org.bouncycastle.cert.path.CertPathValidationException;
+import org.bouncycastle.util.Memoable;
+
+public class KeyUsageValidation
+ implements CertPathValidation
+{
+ private boolean isMandatory;
+
+ public KeyUsageValidation()
+ {
+ this(true);
+ }
+
+ public KeyUsageValidation(boolean isMandatory)
+ {
+ this.isMandatory = isMandatory;
+ }
+
+ public void validate(CertPathValidationContext context, X509CertificateHolder certificate)
+ throws CertPathValidationException
+ {
+ context.addHandledExtension(Extension.keyUsage);
+
+ if (!context.isEndEntity())
+ {
+ KeyUsage usage = KeyUsage.fromExtensions(certificate.getExtensions());
+
+ if (usage != null)
+ {
+ if (!usage.hasUsages(KeyUsage.keyCertSign))
+ {
+ throw new CertPathValidationException("Issuer certificate KeyUsage extension does not permit key signing");
+ }
+ }
+ else
+ {
+ if (isMandatory)
+ {
+ throw new CertPathValidationException("KeyUsage extension not present in CA certificate");
+ }
+ }
+ }
+ }
+
+ public Memoable copy()
+ {
+ return new KeyUsageValidation(isMandatory);
+ }
+
+ public void reset(Memoable other)
+ {
+ KeyUsageValidation v = (KeyUsageValidation)other;
+
+ this.isMandatory = v.isMandatory;
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/ParentCertIssuedValidation.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/ParentCertIssuedValidation.java
new file mode 100644
index 0000000..a21ad1c
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/ParentCertIssuedValidation.java
@@ -0,0 +1,127 @@
+package org.bouncycastle.cert.path.validations;
+
+import java.io.IOException;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Null;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.CertException;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.X509ContentVerifierProviderBuilder;
+import org.bouncycastle.cert.path.CertPathValidation;
+import org.bouncycastle.cert.path.CertPathValidationContext;
+import org.bouncycastle.cert.path.CertPathValidationException;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.util.Memoable;
+
+public class ParentCertIssuedValidation
+ implements CertPathValidation
+{
+ private X509ContentVerifierProviderBuilder contentVerifierProvider;
+
+ private X500Name workingIssuerName;
+ private SubjectPublicKeyInfo workingPublicKey;
+ private AlgorithmIdentifier workingAlgId;
+
+ public ParentCertIssuedValidation(X509ContentVerifierProviderBuilder contentVerifierProvider)
+ {
+ this.contentVerifierProvider = contentVerifierProvider;
+ }
+
+ public void validate(CertPathValidationContext context, X509CertificateHolder certificate)
+ throws CertPathValidationException
+ {
+ if (workingIssuerName != null)
+ {
+ if (!workingIssuerName.equals(certificate.getIssuer()))
+ {
+ throw new CertPathValidationException("Certificate issue does not match parent");
+ }
+ }
+
+ if (workingPublicKey != null)
+ {
+ try
+ {
+ SubjectPublicKeyInfo validatingKeyInfo;
+
+ if (workingPublicKey.getAlgorithm().equals(workingAlgId))
+ {
+ validatingKeyInfo = workingPublicKey;
+ }
+ else
+ {
+ validatingKeyInfo = new SubjectPublicKeyInfo(workingAlgId, workingPublicKey.parsePublicKey());
+ }
+
+ if (!certificate.isSignatureValid(contentVerifierProvider.build(validatingKeyInfo)))
+ {
+ throw new CertPathValidationException("Certificate signature not for public key in parent");
+ }
+ }
+ catch (OperatorCreationException e)
+ {
+ throw new CertPathValidationException("Unable to create verifier: " + e.getMessage(), e);
+ }
+ catch (CertException e)
+ {
+ throw new CertPathValidationException("Unable to validate signature: " + e.getMessage(), e);
+ }
+ catch (IOException e)
+ {
+ throw new CertPathValidationException("Unable to build public key: " + e.getMessage(), e);
+ }
+ }
+
+ workingIssuerName = certificate.getSubject();
+ workingPublicKey = certificate.getSubjectPublicKeyInfo();
+
+ if (workingAlgId != null)
+ {
+ // check for inherited parameters
+ if (workingPublicKey.getAlgorithm().getAlgorithm().equals(workingAlgId.getAlgorithm()))
+ {
+ if (!isNull(workingPublicKey.getAlgorithm().getParameters()))
+ {
+ workingAlgId = workingPublicKey.getAlgorithm();
+ }
+ }
+ else
+ {
+ workingAlgId = workingPublicKey.getAlgorithm();
+ }
+ }
+ else
+ {
+ workingAlgId = workingPublicKey.getAlgorithm();
+ }
+ }
+
+ private boolean isNull(ASN1Encodable obj)
+ {
+ return obj == null || obj instanceof ASN1Null;
+ }
+
+ public Memoable copy()
+ {
+ ParentCertIssuedValidation v = new ParentCertIssuedValidation(contentVerifierProvider);
+
+ v.workingAlgId = this.workingAlgId;
+ v.workingIssuerName = this.workingIssuerName;
+ v.workingPublicKey = this.workingPublicKey;
+
+ return v;
+ }
+
+ public void reset(Memoable other)
+ {
+ ParentCertIssuedValidation v = (ParentCertIssuedValidation)other;
+
+ this.contentVerifierProvider = v.contentVerifierProvider;
+ this.workingAlgId = v.workingAlgId;
+ this.workingIssuerName = v.workingIssuerName;
+ this.workingPublicKey = v.workingPublicKey;
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/ValidationUtils.java b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/ValidationUtils.java
new file mode 100644
index 0000000..2a58706
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/path/validations/ValidationUtils.java
@@ -0,0 +1,11 @@
+package org.bouncycastle.cert.path.validations;
+
+import org.bouncycastle.cert.X509CertificateHolder;
+
+class ValidationUtils
+{
+ static boolean isSelfIssued(X509CertificateHolder cert)
+ {
+ return cert.getSubject().equals(cert.getIssuer());
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/selector/package.html b/bcpkix/src/main/java/org/bouncycastle/cert/selector/package.html
deleted file mode 100644
index c5c4211..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cert/selector/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<body bgcolor="#ffffff">
-Specialised Selector classes for certificates, CRLs, and attribute certificates.
-</body>
-</html> \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/test/BcCertTest.java b/bcpkix/src/main/java/org/bouncycastle/cert/test/BcCertTest.java
index 5f382e0..018dde3 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/test/BcCertTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/test/BcCertTest.java
@@ -1265,7 +1265,7 @@ public class BcCertTest
private void pemTest()
throws Exception
{
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
X509Certificate cert = readPEMCert(cf, PEMData.CERTIFICATE_1);
if (cert == null)
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/test/PKCS10Test.java b/bcpkix/src/main/java/org/bouncycastle/cert/test/PKCS10Test.java
index 6146711..c3ca869 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/test/PKCS10Test.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/test/PKCS10Test.java
@@ -11,7 +11,6 @@ import java.security.Security;
import java.security.Signature;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
-import java.util.Vector;
import javax.security.auth.x500.X500Principal;
@@ -24,11 +23,11 @@ import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.bouncycastle.jce.ECGOST3410NamedCurveTable;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.interfaces.ECPointEncoder;
@@ -50,7 +49,6 @@ import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.SimpleTest;
-import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
/**
**/
@@ -463,28 +461,23 @@ public class PKCS10Test
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "BC");
keyGen.initialize(1024, new SecureRandom());
KeyPair pair = keyGen.generateKeyPair();
+ JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
- Vector oids = new Vector();
- Vector values = new Vector();
- oids.add(X509Extension.basicConstraints);
- values.add(new X509Extension(true, new DEROctetString(new BasicConstraints(true))));
- oids.add(X509Extension.keyUsage);
- values.add(new X509Extension(true, new DEROctetString(
- new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign))));
- SubjectKeyIdentifier subjectKeyIdentifier = new SubjectKeyIdentifierStructure(pair.getPublic());
- X509Extension ski = new X509Extension(false, new DEROctetString(subjectKeyIdentifier));
- oids.add(X509Extension.subjectKeyIdentifier);
- values.add(ski);
+ Extension[] ext = new Extension[] {
+ new Extension(Extension.basicConstraints, true, new DEROctetString(new BasicConstraints(true))),
+ new Extension(Extension.keyUsage, true, new DEROctetString(new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign))),
+ new Extension(Extension.subjectKeyIdentifier, false, new DEROctetString(extUtils.createSubjectKeyIdentifier(pair.getPublic())))
+ };
PKCS10CertificationRequest p1 = new JcaPKCS10CertificationRequestBuilder(
new X500Name("cn=csr"),
pair.getPublic())
- .addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, new X509Extensions(oids, values))
+ .addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, new Extensions(ext))
.build(new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(pair.getPrivate()));
PKCS10CertificationRequest p2 = new JcaPKCS10CertificationRequestBuilder(
new X500Name("cn=csr"),
pair.getPublic())
- .addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, new X509Extensions(oids, values))
+ .addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, new Extensions(ext))
.build(new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(pair.getPrivate()));
if (!p1.equals(p2))
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java
index ec5fcfb..bd9d544 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedData.java
@@ -2,9 +2,6 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.InputStream;
-import java.security.AlgorithmParameters;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1OctetString;
@@ -14,7 +11,6 @@ import org.bouncycastle.asn1.cms.AuthenticatedData;
import org.bouncycastle.asn1.cms.CMSAttributes;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceAlgorithmIdentifierConverter;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.util.Arrays;
@@ -180,7 +176,7 @@ public class CMSAuthenticatedData
*/
public String getMacAlgOID()
{
- return macAlg.getObjectId().getId();
+ return macAlg.getAlgorithm().getId();
}
/**
@@ -200,39 +196,6 @@ public class CMSAuthenticatedData
}
/**
- * Return an AlgorithmParameters object giving the MAC parameters
- * used to digest the message content.
- *
- * @param provider the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws org.bouncycastle.cms.CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @throws java.security.NoSuchProviderException if the provider cannot be found.
- * @deprecated use getMacAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getMacAlgorithmParameters(
- String provider)
- throws CMSException, NoSuchProviderException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(macAlg);
- }
-
- /**
- * Return an AlgorithmParameters object giving the MAC parameters
- * used to digest the message content.
- *
- * @param provider the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws org.bouncycastle.cms.CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @deprecated use getMacAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getMacAlgorithmParameters(
- Provider provider)
- throws CMSException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(macAlg);
- }
-
- /**
* return a store of the intended recipients for this message
*/
public RecipientInformationStore getRecipientInfos()
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java
index 3c3185f..82f8294 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java
@@ -3,20 +3,13 @@ package org.bouncycastle.cms;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.SecureRandom;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
-import javax.crypto.KeyGenerator;
-
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.BEROctetString;
@@ -27,7 +20,6 @@ import org.bouncycastle.asn1.cms.AuthenticatedData;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceCMSMacCalculatorBuilder;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.MacCalculator;
@@ -186,81 +178,4 @@ public class CMSAuthenticatedDataGenerator
}
});
}
-
- /**
- * constructor allowing specific source of randomness
- * @param rand instance of SecureRandom to use
- * @deprecated no longer required, use simple constructor.
- */
- public CMSAuthenticatedDataGenerator(
- SecureRandom rand)
- {
- super(rand);
- }
-
- /**
- * generate an authenticated object that contains an CMS Authenticated Data
- * object using the given provider and the passed in key generator.
- * @deprecated
- */
- private CMSAuthenticatedData generate(
- final CMSProcessable content,
- String macOID,
- KeyGenerator keyGen,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException
- {
- Provider encProvider = keyGen.getProvider();
-
- convertOldRecipients(rand, provider);
-
- return generate(new CMSTypedData()
- {
- public ASN1ObjectIdentifier getContentType()
- {
- return CMSObjectIdentifiers.data;
- }
-
- public void write(OutputStream out)
- throws IOException, CMSException
- {
- content.write(out);
- }
-
- public Object getContent()
- {
- return content;
- }
- }, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(macOID)).setProvider(encProvider).setSecureRandom(rand).build());
- }
-
- /**
- * generate an authenticated object that contains an CMS Authenticated Data
- * object using the given provider.
- * @deprecated use addRecipientInfoGenerator method.
- */
- public CMSAuthenticatedData generate(
- CMSProcessable content,
- String macOID,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return generate(content, macOID, CMSUtils.getProvider(provider));
- }
-
- /**
- * generate an authenticated object that contains an CMS Authenticated Data
- * object using the given provider
- * @deprecated use addRecipientInfoGenerator method..
- */
- public CMSAuthenticatedData generate(
- CMSProcessable content,
- String encryptionOID,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException
- {
- KeyGenerator keyGen = CMSEnvelopedHelper.INSTANCE.createSymmetricKeyGenerator(encryptionOID, provider);
-
- return generate(content, encryptionOID, keyGen, provider);
- }
} \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataParser.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataParser.java
index cae9988..57ea305 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataParser.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataParser.java
@@ -3,9 +3,6 @@ package org.bouncycastle.cms;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.security.AlgorithmParameters;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
@@ -22,7 +19,6 @@ import org.bouncycastle.asn1.cms.CMSAttributes;
import org.bouncycastle.asn1.cms.ContentInfoParser;
import org.bouncycastle.asn1.cms.OriginatorInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceAlgorithmIdentifierConverter;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.util.Arrays;
@@ -143,7 +139,7 @@ public class CMSAuthenticatedDataParser
//
// read the authenticated content info
//
- ContentInfoParser data = authData.getEnapsulatedContentInfo();
+ ContentInfoParser data = authData.getEncapsulatedContentInfo();
CMSReadable readable = new CMSProcessableInputStream(
((ASN1OctetStringParser)data.getContent(BERTags.OCTET_STRING)).getOctetStream());
@@ -176,7 +172,7 @@ public class CMSAuthenticatedDataParser
//
// read the authenticated content info
//
- ContentInfoParser data = authData.getEnapsulatedContentInfo();
+ ContentInfoParser data = authData.getEncapsulatedContentInfo();
CMSReadable readable = new CMSProcessableInputStream(
((ASN1OctetStringParser)data.getContent(BERTags.OCTET_STRING)).getOctetStream());
@@ -233,39 +229,6 @@ public class CMSAuthenticatedDataParser
}
/**
- * Return an AlgorithmParameters object giving the encryption parameters
- * used to encrypt the message content.
- *
- * @param provider the name of the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws org.bouncycastle.cms.CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @throws java.security.NoSuchProviderException if the provider cannot be found.
- * @deprecated use getMacAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getMacAlgorithmParameters(
- String provider)
- throws CMSException, NoSuchProviderException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(macAlg);
- }
-
- /**
- * Return an AlgorithmParameters object giving the encryption parameters
- * used to encrypt the message content.
- *
- * @param provider the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws org.bouncycastle.cms.CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @deprecated use getMacAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getMacAlgorithmParameters(
- Provider provider)
- throws CMSException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(macAlg);
- }
-
- /**
* return a store of the intended recipients for this message
*/
public RecipientInformationStore getRecipientInfos()
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java
index 3bdd450..87afd70 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java
@@ -2,10 +2,6 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.SecureRandom;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@@ -24,7 +20,6 @@ import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.cms.AuthenticatedData;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceCMSMacCalculatorBuilder;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.MacCalculator;
import org.bouncycastle.util.io.TeeOutputStream;
@@ -312,81 +307,4 @@ public class CMSAuthenticatedDataStreamGenerator
cGen.close();
}
}
-
-
- /**
- * constructor allowing specific source of randomness
- * @param rand instance of SecureRandom to use
- * @deprecated no longer of any use, use basic constructor.
- */
- public CMSAuthenticatedDataStreamGenerator(
- SecureRandom rand)
- {
- super(rand);
- }
-
- /**
- * generate an authenticated object that contains an CMS Authenticated Data
- * object using the given provider.
- * @throws java.io.IOException
- * @deprecated use open(out, MacCalculator)
- */
- public OutputStream open(
- OutputStream out,
- String encryptionOID,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, IOException
- {
- convertOldRecipients(rand, CMSUtils.getProvider(provider));
-
- return open(out, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(encryptionOID)).setSecureRandom(rand).setProvider(provider).build());
- }
-
- /**
- * @deprecated use open(out, MacCalculator)
- */
- public OutputStream open(
- OutputStream out,
- String encryptionOID,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException, IOException
- {
- convertOldRecipients(rand, provider);
-
- return open(out, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(encryptionOID)).setSecureRandom(rand).setProvider(provider).build());
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider.
- * @deprecated use open(out, MacCalculator)
- */
- public OutputStream open(
- OutputStream out,
- String encryptionOID,
- int keySize,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, IOException
- {
- convertOldRecipients(rand, CMSUtils.getProvider(provider));
-
- return open(out, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(encryptionOID), keySize).setSecureRandom(rand).setProvider(provider).build());
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider.
- * @deprecated use open(out, MacCalculator)
- */
- public OutputStream open(
- OutputStream out,
- String encryptionOID,
- int keySize,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException, IOException
- {
- convertOldRecipients(rand, provider);
-
- return open(out, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(encryptionOID), keySize).setSecureRandom(rand).setProvider(provider).build());
- }
} \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedGenerator.java
index 064f996..4022c8e 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAuthenticatedGenerator.java
@@ -1,6 +1,5 @@
package org.bouncycastle.cms;
-import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
@@ -20,17 +19,6 @@ public class CMSAuthenticatedGenerator
{
}
- /**
- * constructor allowing specific source of randomness
- *
- * @param rand instance of SecureRandom to use
- */
- public CMSAuthenticatedGenerator(
- SecureRandom rand)
- {
- super(rand);
- }
-
public void setAuthenticatedAttributeGenerator(CMSAttributeTableGenerator authGen)
{
this.authGen = authGen;
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedData.java
index 5a02ea9..3e44908 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedData.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedData.java
@@ -2,7 +2,6 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.InputStream;
-import java.util.zip.InflaterInputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
@@ -58,61 +57,6 @@ public class CMSCompressedData
}
}
- /**
- * Return the uncompressed content.
- *
- * @return the uncompressed content
- * @throws CMSException if there is an exception uncompressing the data.
- * @deprecated use getContent(InputExpanderProvider)
- */
- public byte[] getContent()
- throws CMSException
- {
- ContentInfo content = comData.getEncapContentInfo();
-
- ASN1OctetString bytes = (ASN1OctetString)content.getContent();
-
- InflaterInputStream zIn = new InflaterInputStream(bytes.getOctetStream());
-
- try
- {
- return CMSUtils.streamToByteArray(zIn);
- }
- catch (IOException e)
- {
- throw new CMSException("exception reading compressed stream.", e);
- }
- }
-
- /**
- * Return the uncompressed content, throwing an exception if the data size
- * is greater than the passed in limit. If the content is exceeded getCause()
- * on the CMSException will contain a StreamOverflowException
- *
- * @param limit maximum number of bytes to read
- * @return the content read
- * @throws CMSException if there is an exception uncompressing the data.
- * @deprecated use getContent(InputExpanderProvider)
- */
- public byte[] getContent(int limit)
- throws CMSException
- {
- ContentInfo content = comData.getEncapContentInfo();
-
- ASN1OctetString bytes = (ASN1OctetString)content.getContent();
-
- InflaterInputStream zIn = new InflaterInputStream(bytes.getOctetStream());
-
- try
- {
- return CMSUtils.streamToByteArray(zIn, limit);
- }
- catch (IOException e)
- {
- throw new CMSException("exception reading compressed stream.", e);
- }
- }
-
public ASN1ObjectIdentifier getContentType()
{
return contentInfo.getContentType();
@@ -145,15 +89,6 @@ public class CMSCompressedData
}
/**
- * return the ContentInfo
- * @deprecated use toASN1Structure()
- */
- public ContentInfo getContentInfo()
- {
- return contentInfo;
- }
-
- /**
* return the ContentInfo
*/
public ContentInfo toASN1Structure()
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataGenerator.java
index d2b497b..d50391a 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataGenerator.java
@@ -3,9 +3,7 @@ package org.bouncycastle.cms;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.util.zip.DeflaterOutputStream;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.BEROctetString;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
@@ -38,45 +36,6 @@ public class CMSCompressedDataGenerator
/**
* generate an object that contains an CMS Compressed Data
- * @deprecated use generate(CMSTypedData, OutputCompressor)
- */
- public CMSCompressedData generate(
- CMSProcessable content,
- String compressionOID)
- throws CMSException
- {
- AlgorithmIdentifier comAlgId;
- ASN1OctetString comOcts;
-
- try
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DeflaterOutputStream zOut = new DeflaterOutputStream(bOut);
-
- content.write(zOut);
-
- zOut.close();
-
- comAlgId = new AlgorithmIdentifier(new ASN1ObjectIdentifier(compressionOID));
- comOcts = new BEROctetString(bOut.toByteArray());
- }
- catch (IOException e)
- {
- throw new CMSException("exception encoding data.", e);
- }
-
- ContentInfo comContent = new ContentInfo(
- CMSObjectIdentifiers.data, comOcts);
-
- ContentInfo contentInfo = new ContentInfo(
- CMSObjectIdentifiers.compressedData,
- new CompressedData(comAlgId, comContent));
-
- return new CMSCompressedData(contentInfo);
- }
-
- /**
- * generate an object that contains an CMS Compressed Data
*/
public CMSCompressedData generate(
CMSTypedData content,
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataParser.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataParser.java
index 910b3f0..c3da87b 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataParser.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataParser.java
@@ -3,7 +3,6 @@ package org.bouncycastle.cms;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.zip.InflaterInputStream;
import org.bouncycastle.asn1.ASN1OctetStringParser;
import org.bouncycastle.asn1.ASN1SequenceParser;
@@ -45,27 +44,6 @@ public class CMSCompressedDataParser
}
/**
- * @deprecated use getContent(InputExpandedProvider)
- */
- public CMSTypedStream getContent()
- throws CMSException
- {
- try
- {
- CompressedDataParser comData = new CompressedDataParser((ASN1SequenceParser)_contentInfo.getContent(BERTags.SEQUENCE));
- ContentInfoParser content = comData.getEncapContentInfo();
-
- ASN1OctetStringParser bytes = (ASN1OctetStringParser)content.getContent(BERTags.OCTET_STRING);
-
- return new CMSTypedStream(content.getContentType().toString(), new InflaterInputStream(bytes.getOctetStream()));
- }
- catch (IOException e)
- {
- throw new CMSException("IOException reading compressed content.", e);
- }
- }
-
- /**
* Return a typed stream which will allow the reading of the compressed content in
* expanded form.
*
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataStreamGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataStreamGenerator.java
index bb917d0..8a34eb0 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataStreamGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSCompressedDataStreamGenerator.java
@@ -2,12 +2,10 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.OutputStream;
-import java.util.zip.DeflaterOutputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.BERSequenceGenerator;
-import org.bouncycastle.asn1.DERSequenceGenerator;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.operator.OutputCompressor;
@@ -51,60 +49,14 @@ public class CMSCompressedDataStreamGenerator
}
/**
- * @deprecated use open(OutputStream, ContentCompressor)
- */
- public OutputStream open(
- OutputStream out,
- String compressionOID)
- throws IOException
- {
- return open(out, CMSObjectIdentifiers.data.getId(), compressionOID);
- }
-
- /**
- * @deprecated use open(OutputStream, ASN1ObjectIdentifier, ContentCompressor)
+ * Open a compressing output stream with the PKCS#7 content type OID of "data".
+ *
+ * @param out the stream to encode to.
+ * @param compressor the type of compressor to use.
+ * @return an output stream to write the data be compressed to.
+ * @throws IOException
*/
public OutputStream open(
- OutputStream out,
- String contentOID,
- String compressionOID)
- throws IOException
- {
- BERSequenceGenerator sGen = new BERSequenceGenerator(out);
-
- sGen.addObject(CMSObjectIdentifiers.compressedData);
-
- //
- // Compressed Data
- //
- BERSequenceGenerator cGen = new BERSequenceGenerator(sGen.getRawOutputStream(), 0, true);
-
- cGen.addObject(new ASN1Integer(0));
-
- //
- // AlgorithmIdentifier
- //
- DERSequenceGenerator algGen = new DERSequenceGenerator(cGen.getRawOutputStream());
-
- algGen.addObject(new ASN1ObjectIdentifier(ZLIB));
-
- algGen.close();
-
- //
- // Encapsulated ContentInfo
- //
- BERSequenceGenerator eiGen = new BERSequenceGenerator(cGen.getRawOutputStream());
-
- eiGen.addObject(new ASN1ObjectIdentifier(contentOID));
-
- OutputStream octetStream = CMSUtils.createBEROctetOutputStream(
- eiGen.getRawOutputStream(), 0, true, _bufferSize);
-
- return new CmsCompressedOutputStream(
- new DeflaterOutputStream(octetStream), sGen, cGen, eiGen);
- }
-
- public OutputStream open(
OutputStream out,
OutputCompressor compressor)
throws IOException
@@ -115,10 +67,10 @@ public class CMSCompressedDataStreamGenerator
/**
* Open a compressing output stream.
*
- * @param contentOID
- * @param out
- * @param compressor
- * @return
+ * @param contentOID the content type OID.
+ * @param out the stream to encode to.
+ * @param compressor the type of compressor to use.
+ * @return an output stream to write the data be compressed to.
* @throws IOException
*/
public OutputStream open(
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedData.java
index 131faec..56b9663 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedData.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedData.java
@@ -2,9 +2,6 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.InputStream;
-import java.security.AlgorithmParameters;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Set;
@@ -13,7 +10,6 @@ import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.EncryptedContentInfo;
import org.bouncycastle.asn1.cms.EnvelopedData;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceAlgorithmIdentifierConverter;
/**
* containing class for an CMS Enveloped Data object
@@ -170,39 +166,6 @@ public class CMSEnvelopedData
}
/**
- * Return an AlgorithmParameters object giving the encryption parameters
- * used to encrypt the message content.
- *
- * @param provider the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @throws NoSuchProviderException if the provider cannot be found.
- * @deprecated use getContentEncryptionAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getEncryptionAlgorithmParameters(
- String provider)
- throws CMSException, NoSuchProviderException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(encAlg);
- }
-
- /**
- * Return an AlgorithmParameters object giving the encryption parameters
- * used to encrypt the message content.
- *
- * @param provider the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @deprecated use getContentEncryptionAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getEncryptionAlgorithmParameters(
- Provider provider)
- throws CMSException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(encAlg);
- }
-
- /**
* return a store of the intended recipients for this message
*/
public RecipientInformationStore getRecipientInfos()
@@ -212,15 +175,6 @@ public class CMSEnvelopedData
/**
* return the ContentInfo
- * @deprecated use toASN1Structure()
- */
- public ContentInfo getContentInfo()
- {
- return contentInfo;
- }
-
- /**
- * return the ContentInfo
*/
public ContentInfo toASN1Structure()
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataGenerator.java
index 135367e..0038f90 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataGenerator.java
@@ -3,17 +3,10 @@ package org.bouncycastle.cms;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Iterator;
-import javax.crypto.KeyGenerator;
-
import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.BEROctetString;
@@ -25,7 +18,6 @@ import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.EncryptedContentInfo;
import org.bouncycastle.asn1.cms.EnvelopedData;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
import org.bouncycastle.operator.GenericKey;
import org.bouncycastle.operator.OutputEncryptor;
@@ -58,65 +50,6 @@ public class CMSEnvelopedDataGenerator
{
}
- /**
- * constructor allowing specific source of randomness
- * @param rand instance of SecureRandom to use
- * @deprecated use no args constructor.
- */
- public CMSEnvelopedDataGenerator(
- SecureRandom rand)
- {
- super(rand);
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider and the passed in key generator.
- */
- private CMSEnvelopedData generate(
- final CMSProcessable content,
- String encryptionOID,
- int keySize,
- Provider encProvider,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException
- {
- convertOldRecipients(rand, provider);
-
- JceCMSContentEncryptorBuilder builder;
-
- if (keySize != -1)
- {
- builder = new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(encryptionOID), keySize);
- }
- else
- {
- builder = new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(encryptionOID));
- }
-
- builder.setProvider(encProvider);
- builder.setSecureRandom(rand);
-
- return doGenerate(new CMSTypedData()
- {
- public ASN1ObjectIdentifier getContentType()
- {
- return CMSObjectIdentifiers.data;
- }
-
- public void write(OutputStream out)
- throws IOException, CMSException
- {
- content.write(out);
- }
-
- public Object getContent()
- {
- return content;
- }
- }, builder.build());
- }
-
private CMSEnvelopedData doGenerate(
CMSTypedData content,
OutputEncryptor contentEncryptor)
@@ -184,68 +117,6 @@ public class CMSEnvelopedDataGenerator
/**
* generate an enveloped object that contains an CMS Enveloped Data
* object using the given provider.
- * @deprecated use OutputEncryptor method.
- */
- public CMSEnvelopedData generate(
- CMSProcessable content,
- String encryptionOID,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return generate(content, encryptionOID, CMSUtils.getProvider(provider));
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider.
- * @deprecated use OutputEncryptor method.
- */
- public CMSEnvelopedData generate(
- CMSProcessable content,
- String encryptionOID,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException
- {
- KeyGenerator keyGen = CMSEnvelopedHelper.INSTANCE.createSymmetricKeyGenerator(encryptionOID, provider);
-
- return generate(content, encryptionOID, -1, keyGen.getProvider(), provider);
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider.
- * @deprecated use OutputEncryptor method.
- */
- public CMSEnvelopedData generate(
- CMSProcessable content,
- String encryptionOID,
- int keySize,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return generate(content, encryptionOID, keySize, CMSUtils.getProvider(provider));
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider.
- * @deprecated use OutputEncryptor method.
- */
- public CMSEnvelopedData generate(
- CMSProcessable content,
- String encryptionOID,
- int keySize,
- Provider provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- KeyGenerator keyGen = CMSEnvelopedHelper.INSTANCE.createSymmetricKeyGenerator(encryptionOID, provider);
-
- return generate(content, encryptionOID, keySize, keyGen.getProvider(), provider);
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider.
*
* @param content the content to be encrypted
* @param contentEncryptor the symmetric key based encryptor to encrypt the content with.
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataParser.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataParser.java
index 627b0ca..defd2f7 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataParser.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataParser.java
@@ -3,9 +3,6 @@ package org.bouncycastle.cms;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.security.AlgorithmParameters;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
@@ -20,7 +17,6 @@ import org.bouncycastle.asn1.cms.EncryptedContentInfoParser;
import org.bouncycastle.asn1.cms.EnvelopedDataParser;
import org.bouncycastle.asn1.cms.OriginatorInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceAlgorithmIdentifierConverter;
/**
* Parsing class for an CMS Enveloped Data object from an input stream.
@@ -148,39 +144,6 @@ public class CMSEnvelopedDataParser
}
/**
- * Return an AlgorithmParameters object giving the encryption parameters
- * used to encrypt the message content.
- *
- * @param provider the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @throws NoSuchProviderException if the provider cannot be found.
- * @deprecated use getContentEncryptionAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getEncryptionAlgorithmParameters(
- String provider)
- throws CMSException, NoSuchProviderException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(encAlg);
- }
-
- /**
- * Return an AlgorithmParameters object giving the encryption parameters
- * used to encrypt the message content.
- *
- * @param provider the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @deprecated use getContentEncryptionAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getEncryptionAlgorithmParameters(
- Provider provider)
- throws CMSException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(encAlg);
- }
-
- /**
* Return the originator information associated with this message if present.
*
* @return OriginatorInformation, null if not present.
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataStreamGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataStreamGenerator.java
index 072a1da..92abca0 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataStreamGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedDataStreamGenerator.java
@@ -2,15 +2,9 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Iterator;
-import javax.crypto.KeyGenerator;
-
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -23,7 +17,6 @@ import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.EnvelopedData;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
import org.bouncycastle.operator.GenericKey;
import org.bouncycastle.operator.OutputEncryptor;
@@ -61,17 +54,6 @@ public class CMSEnvelopedDataStreamGenerator
}
/**
- * constructor allowing specific source of randomness
- * @param rand instance of SecureRandom to use
- * @deprecated no longer required - specify randomness via RecipientInfoGenerator or ContentEncryptor.
- */
- public CMSEnvelopedDataStreamGenerator(
- SecureRandom rand)
- {
- super(rand);
- }
-
- /**
* Set the underlying string size for encapsulated data
*
* @param bufferSize length of octet strings to buffer the data.
@@ -102,39 +84,6 @@ public class CMSEnvelopedDataStreamGenerator
return new ASN1Integer(0);
}
}
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider and the passed in key generator.
- * @throws IOException
- * @deprecated
- */
- private OutputStream open(
- OutputStream out,
- String encryptionOID,
- int keySize,
- Provider encProvider,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException, IOException
- {
- convertOldRecipients(rand, provider);
-
- JceCMSContentEncryptorBuilder builder;
-
- if (keySize != -1)
- {
- builder = new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(encryptionOID), keySize);
- }
- else
- {
- builder = new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(encryptionOID));
- }
-
- builder.setProvider(encProvider);
- builder.setSecureRandom(rand);
-
- return doOpen(CMSObjectIdentifiers.data, out, builder.build());
- }
private OutputStream doOpen(
ASN1ObjectIdentifier dataType,
@@ -267,71 +216,6 @@ public class CMSEnvelopedDataStreamGenerator
/**
* generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider.
- * @throws IOException
- * @deprecated
- */
- public OutputStream open(
- OutputStream out,
- String encryptionOID,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, IOException
- {
- return open(out, encryptionOID, CMSUtils.getProvider(provider));
- }
-
- /**
- * @deprecated
- */
- public OutputStream open(
- OutputStream out,
- String encryptionOID,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException, IOException
- {
- KeyGenerator keyGen = CMSEnvelopedHelper.INSTANCE.createSymmetricKeyGenerator(encryptionOID, provider);
-
- keyGen.init(rand);
-
- return open(out, encryptionOID, -1, keyGen.getProvider(), provider);
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider.
- * @deprecated
- */
- public OutputStream open(
- OutputStream out,
- String encryptionOID,
- int keySize,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, IOException
- {
- return open(out, encryptionOID, keySize, CMSUtils.getProvider(provider));
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
- * object using the given provider.
- * @deprecated
- */
- public OutputStream open(
- OutputStream out,
- String encryptionOID,
- int keySize,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException, IOException
- {
- KeyGenerator keyGen = CMSEnvelopedHelper.INSTANCE.createSymmetricKeyGenerator(encryptionOID, provider);
-
- keyGen.init(keySize, rand);
-
- return open(out, encryptionOID, -1, keyGen.getProvider(), provider);
- }
-
- /**
- * generate an enveloped object that contains an CMS Enveloped Data
* object using the given encryptor.
*/
public OutputStream open(
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedGenerator.java
index aeda9a1..012b440 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedGenerator.java
@@ -1,39 +1,14 @@
package org.bouncycastle.cms;
-import java.io.IOException;
-import java.security.AlgorithmParameters;
-import java.security.InvalidKeyException;
-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.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
-import javax.crypto.SecretKey;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.cms.KEKIdentifier;
import org.bouncycastle.asn1.cms.OriginatorInfo;
import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.cms.jcajce.JceKEKRecipientInfoGenerator;
-import org.bouncycastle.cms.jcajce.JceKeyAgreeRecipientInfoGenerator;
-import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
-import org.bouncycastle.cms.jcajce.JcePasswordRecipientInfoGenerator;
/**
* General class for generating a CMS enveloped-data message.
@@ -69,7 +44,6 @@ public class CMSEnvelopedGenerator
protected CMSAttributeTableGenerator unprotectedAttributeGenerator = null;
- final SecureRandom rand;
protected OriginatorInfo originatorInfo;
/**
@@ -77,17 +51,6 @@ public class CMSEnvelopedGenerator
*/
public CMSEnvelopedGenerator()
{
- this(new SecureRandom());
- }
-
- /**
- * constructor allowing specific source of randomness
- * @param rand instance of SecureRandom to use
- */
- public CMSEnvelopedGenerator(
- SecureRandom rand)
- {
- this.rand = rand;
}
public void setUnprotectedAttributeGenerator(CMSAttributeTableGenerator unprotectedAttributeGenerator)
@@ -95,212 +58,12 @@ public class CMSEnvelopedGenerator
this.unprotectedAttributeGenerator = unprotectedAttributeGenerator;
}
-
public void setOriginatorInfo(OriginatorInformation originatorInfo)
{
this.originatorInfo = originatorInfo.toASN1Structure();
}
/**
- * add a recipient.
- *
- * @deprecated use the addRecipientGenerator and JceKeyTransRecipientInfoGenerator
- * @param cert recipient's public key certificate
- * @exception IllegalArgumentException if there is a problem with the certificate
- */
- public void addKeyTransRecipient(
- X509Certificate cert)
- throws IllegalArgumentException
- {
- try
- {
- oldRecipientInfoGenerators.add(new JceKeyTransRecipientInfoGenerator(cert));
- }
- catch (CertificateEncodingException e)
- {
- throw new IllegalArgumentException("unable to encode certificate: " + e.getMessage());
- }
- }
-
- /**
- * add a recipient
- *
- * @deprecated use the addRecipientGenerator and JceKeyTransRecipientInfoGenerator
- * @param key the public key used by the recipient
- * @param subKeyId the identifier for the recipient's public key
- * @exception IllegalArgumentException if there is a problem with the key
- */
- public void addKeyTransRecipient(
- PublicKey key,
- byte[] subKeyId)
- throws IllegalArgumentException
- {
- oldRecipientInfoGenerators.add(new JceKeyTransRecipientInfoGenerator(subKeyId, key));
- }
-
- /**
- * add a KEK recipient.
- *
- * @deprecated use the addRecipientGenerator and JceKEKRecipientInfoGenerator
- * @param key the secret key to use for wrapping
- * @param keyIdentifier the byte string that identifies the key
- */
- public void addKEKRecipient(
- SecretKey key,
- byte[] keyIdentifier)
- {
- addKEKRecipient(key, new KEKIdentifier(keyIdentifier, null, null));
- }
-
- /**
- * add a KEK recipient.
- *
- * @deprecated use the addRecipientGenerator and JceKEKRecipientInfoGenerator
- * @param key the secret key to use for wrapping
- * @param kekIdentifier a KEKIdentifier structure (identifies the key)
- */
- public void addKEKRecipient(
- SecretKey key,
- KEKIdentifier kekIdentifier)
- {
- oldRecipientInfoGenerators.add(new JceKEKRecipientInfoGenerator(kekIdentifier, key));
- }
-
- /**
- * @deprecated use addRecipientGenerator and JcePasswordRecipientInfoGenerator
- * @param pbeKey PBE key
- * @param kekAlgorithmOid key encryption algorithm to use.
- */
- public void addPasswordRecipient(
- CMSPBEKey pbeKey,
- String kekAlgorithmOid)
- {
- oldRecipientInfoGenerators.add(new JcePasswordRecipientInfoGenerator(new ASN1ObjectIdentifier(kekAlgorithmOid), pbeKey.getPassword())
- .setSaltAndIterationCount(pbeKey.getSalt(), pbeKey.getIterationCount())
- .setPasswordConversionScheme((pbeKey instanceof PKCS5Scheme2UTF8PBEKey) ? PasswordRecipient.PKCS5_SCHEME2_UTF8 : PasswordRecipient.PKCS5_SCHEME2));
- }
-
- /**
- * Add a key agreement based recipient.
- *
- * @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
- * @param agreementAlgorithm key agreement algorithm to use.
- * @param senderPrivateKey private key to initialise sender side of agreement with.
- * @param senderPublicKey sender public key to include with message.
- * @param recipientCert recipient's public key certificate.
- * @param cekWrapAlgorithm OID for key wrapping algorithm to use.
- * @param provider provider to use for the agreement calculation.
- * @exception NoSuchProviderException if the specified provider cannot be found
- * @exception NoSuchAlgorithmException if the algorithm requested cannot be found
- * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
- */
- public void addKeyAgreementRecipient(
- String agreementAlgorithm,
- PrivateKey senderPrivateKey,
- PublicKey senderPublicKey,
- X509Certificate recipientCert,
- String cekWrapAlgorithm,
- String provider)
- throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException
- {
- addKeyAgreementRecipient(agreementAlgorithm, senderPrivateKey, senderPublicKey, recipientCert, cekWrapAlgorithm, CMSUtils.getProvider(provider));
- }
-
- /**
- * Add a key agreement based recipient.
- *
- * @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
- * @param agreementAlgorithm key agreement algorithm to use.
- * @param senderPrivateKey private key to initialise sender side of agreement with.
- * @param senderPublicKey sender public key to include with message.
- * @param recipientCert recipient's public key certificate.
- * @param cekWrapAlgorithm OID for key wrapping algorithm to use.
- * @param provider provider to use for the agreement calculation.
- * @exception NoSuchAlgorithmException if the algorithm requested cannot be found
- * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
- */
- public void addKeyAgreementRecipient(
- String agreementAlgorithm,
- PrivateKey senderPrivateKey,
- PublicKey senderPublicKey,
- X509Certificate recipientCert,
- String cekWrapAlgorithm,
- Provider provider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- List recipients = new ArrayList();
-
- recipients.add(recipientCert);
-
- addKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey,
- recipients, cekWrapAlgorithm, provider);
- }
-
- /**
- * Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
- *
- * @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
- * @param agreementAlgorithm key agreement algorithm to use.
- * @param senderPrivateKey private key to initialise sender side of agreement with.
- * @param senderPublicKey sender public key to include with message.
- * @param recipientCerts recipients' public key certificates.
- * @param cekWrapAlgorithm OID for key wrapping algorithm to use.
- * @param provider provider to use for the agreement calculation.
- * @exception NoSuchAlgorithmException if the algorithm requested cannot be found
- * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
- */
- public void addKeyAgreementRecipients(
- String agreementAlgorithm,
- PrivateKey senderPrivateKey,
- PublicKey senderPublicKey,
- Collection recipientCerts,
- String cekWrapAlgorithm,
- String provider)
- throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException
- {
- addKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey, recipientCerts, cekWrapAlgorithm, CMSUtils.getProvider(provider));
- }
-
- /**
- * Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
- *
- * @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
- * @param agreementAlgorithm key agreement algorithm to use.
- * @param senderPrivateKey private key to initialise sender side of agreement with.
- * @param senderPublicKey sender public key to include with message.
- * @param recipientCerts recipients' public key certificates.
- * @param cekWrapAlgorithm OID for key wrapping algorithm to use.
- * @param provider provider to use for the agreement calculation.
- * @exception NoSuchAlgorithmException if the algorithm requested cannot be found
- * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
- */
- public void addKeyAgreementRecipients(
- String agreementAlgorithm,
- PrivateKey senderPrivateKey,
- PublicKey senderPublicKey,
- Collection recipientCerts,
- String cekWrapAlgorithm,
- Provider provider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- JceKeyAgreeRecipientInfoGenerator recipientInfoGenerator = new JceKeyAgreeRecipientInfoGenerator(new ASN1ObjectIdentifier(agreementAlgorithm), senderPrivateKey, senderPublicKey, new ASN1ObjectIdentifier(cekWrapAlgorithm)).setProvider(provider);
-
- for (Iterator it = recipientCerts.iterator(); it.hasNext();)
- {
- try
- {
- recipientInfoGenerator.addRecipient((X509Certificate)it.next());
- }
- catch (CertificateEncodingException e)
- {
- throw new IllegalArgumentException("unable to encode certificate: " + e.getMessage());
- }
- }
-
- oldRecipientInfoGenerators.add(recipientInfoGenerator);
- }
-
- /**
* Add a generator to produce the recipient info required.
*
* @param recipientGenerator a generator of a recipient info object.
@@ -309,82 +72,4 @@ public class CMSEnvelopedGenerator
{
recipientInfoGenerators.add(recipientGenerator);
}
-
- protected AlgorithmIdentifier getAlgorithmIdentifier(String encryptionOID, AlgorithmParameters params) throws IOException
- {
- ASN1Encodable asn1Params;
- if (params != null)
- {
- asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
- }
- else
- {
- asn1Params = DERNull.INSTANCE;
- }
-
- return new AlgorithmIdentifier(
- new ASN1ObjectIdentifier(encryptionOID),
- asn1Params);
- }
-
- protected void convertOldRecipients(SecureRandom rand, Provider provider)
- {
- for (Iterator it = oldRecipientInfoGenerators.iterator(); it.hasNext();)
- {
- Object recipient = it.next();
-
- if (recipient instanceof JceKeyTransRecipientInfoGenerator)
- {
- JceKeyTransRecipientInfoGenerator recip = (JceKeyTransRecipientInfoGenerator)recipient;
-
- if (provider != null)
- {
- recip.setProvider(provider);
- }
-
- recipientInfoGenerators.add(recip);
- }
- else if (recipient instanceof KEKRecipientInfoGenerator)
- {
- JceKEKRecipientInfoGenerator recip = (JceKEKRecipientInfoGenerator)recipient;
-
- if (provider != null)
- {
- recip.setProvider(provider);
- }
-
- recip.setSecureRandom(rand);
-
- recipientInfoGenerators.add(recip);
- }
- else if (recipient instanceof JcePasswordRecipientInfoGenerator)
- {
- JcePasswordRecipientInfoGenerator recip = (JcePasswordRecipientInfoGenerator)recipient;
-
- if (provider != null)
- {
- recip.setProvider(provider);
- }
-
- recip.setSecureRandom(rand);
-
- recipientInfoGenerators.add(recip);
- }
- else if (recipient instanceof JceKeyAgreeRecipientInfoGenerator)
- {
- JceKeyAgreeRecipientInfoGenerator recip = (JceKeyAgreeRecipientInfoGenerator)recipient;
-
- if (provider != null)
- {
- recip.setProvider(provider);
- }
-
- recip.setSecureRandom(rand);
-
- recipientInfoGenerators.add(recip);
- }
- }
-
- oldRecipientInfoGenerators.clear();
- }
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedHelper.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedHelper.java
index fcb662b..9172706 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedHelper.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSEnvelopedHelper.java
@@ -3,15 +3,11 @@ package org.bouncycastle.cms;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.Provider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.crypto.KeyGenerator;
-
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.cms.KEKRecipientInfo;
@@ -55,36 +51,7 @@ class CMSEnvelopedHelper
MAC_ALG_NAMES.put(CMSEnvelopedGenerator.AES256_CBC, "AESMac");
}
- KeyGenerator createSymmetricKeyGenerator(
- String encryptionOID,
- Provider provider)
- throws NoSuchAlgorithmException
- {
- try
- {
- return createKeyGenerator(encryptionOID, provider);
- }
- catch (NoSuchAlgorithmException e)
- {
- try
- {
- String algName = (String)BASE_CIPHER_NAMES.get(encryptionOID);
- if (algName != null)
- {
- return createKeyGenerator(algName, provider);
- }
- }
- catch (NoSuchAlgorithmException ex)
- {
- // ignore
- }
- if (provider != null)
- {
- return createSymmetricKeyGenerator(encryptionOID, null);
- }
- throw e;
- }
- }
+
int getKeySize(String oid)
{
@@ -98,20 +65,7 @@ class CMSEnvelopedHelper
return keySize.intValue();
}
- private KeyGenerator createKeyGenerator(
- String algName,
- Provider provider)
- throws NoSuchAlgorithmException
- {
- if (provider != null)
- {
- return KeyGenerator.getInstance(algName, provider);
- }
- else
- {
- return KeyGenerator.getInstance(algName);
- }
- }
+
static RecipientInformationStore buildRecipientInformationStore(
ASN1Set recipientInfos, AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable)
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSPBEKey.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSPBEKey.java
deleted file mode 100644
index d37bb31..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSPBEKey.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.bouncycastle.cms;
-
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.spec.InvalidParameterSpecException;
-
-import javax.crypto.interfaces.PBEKey;
-import javax.crypto.spec.PBEParameterSpec;
-
-public abstract class CMSPBEKey
- implements PBEKey
-{
- private char[] password;
- private byte[] salt;
- private int iterationCount;
-
- protected static PBEParameterSpec getParamSpec(AlgorithmParameters algParams)
- throws InvalidAlgorithmParameterException
- {
- try
- {
- return (PBEParameterSpec)algParams.getParameterSpec(PBEParameterSpec.class);
- }
- catch (InvalidParameterSpecException e)
- {
- throw new InvalidAlgorithmParameterException("cannot process PBE spec: " + e.getMessage());
- }
- }
-
- public CMSPBEKey(char[] password, byte[] salt, int iterationCount)
- {
- this.password = password;
- this.salt = salt;
- this.iterationCount = iterationCount;
- }
-
- public CMSPBEKey(char[] password, PBEParameterSpec pbeSpec)
- {
- this(password, pbeSpec.getSalt(), pbeSpec.getIterationCount());
- }
-
- public char[] getPassword()
- {
- return password;
- }
-
- public byte[] getSalt()
- {
- return salt;
- }
-
- public int getIterationCount()
- {
- return iterationCount;
- }
-
- public String getAlgorithm()
- {
- return "PKCS5S2";
- }
-
- public String getFormat()
- {
- return "RAW";
- }
-
- public byte[] getEncoded()
- {
- return null;
- }
-
- abstract byte[] getEncoded(String algorithmOid);
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java
index 7a3cb4b..0465b77 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java
@@ -3,11 +3,6 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
@@ -25,13 +20,10 @@ import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.SignedData;
import org.bouncycastle.asn1.cms.SignerInfo;
-import org.bouncycastle.cert.jcajce.JcaCertStoreBuilder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.SignatureAlgorithmIdentifierFinder;
import org.bouncycastle.util.Store;
-import org.bouncycastle.x509.NoSuchStoreException;
-import org.bouncycastle.x509.X509Store;
/**
* general class for handling a pkcs7-signature message.
@@ -69,9 +61,7 @@ public class CMSSignedData
ContentInfo contentInfo;
CMSTypedData signedContent;
SignerInformationStore signerInfoStore;
- X509Store attributeStore;
- X509Store certificateStore;
- X509Store crlStore;
+
private Map hashes;
private CMSSignedData(
@@ -266,192 +256,6 @@ public class CMSSignedData
}
/**
- * return a X509Store containing the attribute certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider name of provider to use
- * @return a store of attribute certificates
- * @exception NoSuchProviderException if the provider requested isn't available.
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use base Store returning method
- */
- public X509Store getAttributeCertificates(
- String type,
- String provider)
- throws NoSuchStoreException, NoSuchProviderException, CMSException
- {
- return getAttributeCertificates(type, CMSUtils.getProvider(provider));
- }
-
- /**
- * return a X509Store containing the attribute certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider provider to use
- * @return a store of attribute certificates
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use base Store returning method
- */
- public X509Store getAttributeCertificates(
- String type,
- Provider provider)
- throws NoSuchStoreException, CMSException
- {
- if (attributeStore == null)
- {
- attributeStore = HELPER.createAttributeStore(type, provider, this.getAttributeCertificates());
- }
-
- return attributeStore;
- }
-
- /**
- * return a X509Store containing the public key certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider name of provider to use
- * @return a store of public key certificates
- * @exception NoSuchProviderException if the provider requested isn't available.
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use base Store returning method
- */
- public X509Store getCertificates(
- String type,
- String provider)
- throws NoSuchStoreException, NoSuchProviderException, CMSException
- {
- return getCertificates(type, CMSUtils.getProvider(provider));
- }
-
- /**
- * return a X509Store containing the public key certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider provider to use
- * @return a store of public key certificates
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use base Store returning method
- */
- public X509Store getCertificates(
- String type,
- Provider provider)
- throws NoSuchStoreException, CMSException
- {
- if (certificateStore == null)
- {
- certificateStore = HELPER.createCertificateStore(type, provider, this.getCertificates());
- }
-
- return certificateStore;
- }
-
- /**
- * return a X509Store containing CRLs, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider name of provider to use
- * @return a store of CRLs
- * @exception NoSuchProviderException if the provider requested isn't available.
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use base Store returning method
- */
- public X509Store getCRLs(
- String type,
- String provider)
- throws NoSuchStoreException, NoSuchProviderException, CMSException
- {
- return getCRLs(type, CMSUtils.getProvider(provider));
- }
-
- /**
- * return a X509Store containing CRLs, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider provider to use
- * @return a store of CRLs
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use base Store returning method
- */
- public X509Store getCRLs(
- String type,
- Provider provider)
- throws NoSuchStoreException, CMSException
- {
- if (crlStore == null)
- {
- crlStore = HELPER.createCRLsStore(type, provider, getCRLs());
- }
-
- return crlStore;
- }
-
- /**
- * return a CertStore containing the certificates and CRLs associated with
- * this message.
- *
- * @exception NoSuchProviderException if the provider requested isn't available.
- * @exception NoSuchAlgorithmException if the cert store isn't available.
- * @exception CMSException if a general exception prevents creation of the CertStore
- * @deprecated use base Store returning method and org.bouncycastle.cert.jcajce.JcaCertStoreBuilder
- */
- public CertStore getCertificatesAndCRLs(
- String type,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return getCertificatesAndCRLs(type, CMSUtils.getProvider(provider));
- }
-
- /**
- * return a CertStore containing the certificates and CRLs associated with
- * this message.
- *
- * @exception NoSuchAlgorithmException if the cert store isn't available.
- * @exception CMSException if a general exception prevents creation of the CertStore
- * @deprecated use base Store returning method and org.bouncycastle.cert.jcajce.JcaCertStoreBuilder
- */
- public CertStore getCertificatesAndCRLs(
- String type,
- Provider provider)
- throws NoSuchAlgorithmException, CMSException
- {
- try
- {
- JcaCertStoreBuilder certStoreBuilder = new JcaCertStoreBuilder().setType(type);
-
- if (provider != null)
- {
- certStoreBuilder.setProvider(provider);
- }
-
- certStoreBuilder.addCertificates(this.getCertificates());
- certStoreBuilder.addCRLs(this.getCRLs());
-
- return certStoreBuilder.build();
- }
- catch (NoSuchAlgorithmException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new CMSException("exception creating CertStore: " + e.getMessage(), e);
- }
- }
-
- /**
* Return any X.509 certificate objects in this SignedData structure as a Store of X509CertificateHolder objects.
*
* @return a Store of X509CertificateHolder objects.
@@ -512,15 +316,6 @@ public class CMSSignedData
/**
* return the ContentInfo
- * @deprecated use toASN1Structure()
- */
- public ContentInfo getContentInfo()
- {
- return contentInfo;
- }
-
- /**
- * return the ContentInfo
*/
public ContentInfo toASN1Structure()
{
@@ -672,77 +467,6 @@ public class CMSSignedData
/**
* Replace the certificate and CRL information associated with this
* CMSSignedData object with the new one passed in.
- *
- * @param signedData the signed data object to be used as a base.
- * @param certsAndCrls the new certificates and CRLs to be used.
- * @return a new signed data object.
- * @exception CMSException if there is an error processing the CertStore
- * @deprecated use method taking Store arguments.
- */
- public static CMSSignedData replaceCertificatesAndCRLs(
- CMSSignedData signedData,
- CertStore certsAndCrls)
- throws CMSException
- {
- //
- // copy
- //
- CMSSignedData cms = new CMSSignedData(signedData);
-
- //
- // replace the certs and crls in the SignedData object
- //
- ASN1Set certs = null;
- ASN1Set crls = null;
-
- try
- {
- ASN1Set set = CMSUtils.createBerSetFromList(CMSUtils.getCertificatesFromStore(certsAndCrls));
-
- if (set.size() != 0)
- {
- certs = set;
- }
- }
- catch (CertStoreException e)
- {
- throw new CMSException("error getting certs from certStore", e);
- }
-
- try
- {
- ASN1Set set = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(certsAndCrls));
-
- if (set.size() != 0)
- {
- crls = set;
- }
- }
- catch (CertStoreException e)
- {
- throw new CMSException("error getting crls from certStore", e);
- }
-
- //
- // replace the CMS structure.
- //
- cms.signedData = new SignedData(signedData.signedData.getDigestAlgorithms(),
- signedData.signedData.getEncapContentInfo(),
- certs,
- crls,
- signedData.signedData.getSignerInfos());
-
- //
- // replace the contentInfo with the new one
- //
- cms.contentInfo = new ContentInfo(cms.contentInfo.getContentType(), cms.signedData);
-
- return cms;
- }
-
- /**
- * Replace the certificate and CRL information associated with this
- * CMSSignedData object with the new one passed in.
*
* @param signedData the signed data object to be used as a base.
* @param certificates the new certificates to be used.
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java
index 9692e15..eea8a1a 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java
@@ -3,13 +3,6 @@ package org.bouncycastle.cms;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.Provider;
-import java.security.SecureRandom;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -20,16 +13,10 @@ import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.BEROctetString;
import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.SignedData;
import org.bouncycastle.asn1.cms.SignerInfo;
-import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
/**
* general class for generating a pkcs7-signature message.
@@ -62,80 +49,6 @@ public class CMSSignedDataGenerator
{
private List signerInfs = new ArrayList();
- private class SignerInf
- {
- final PrivateKey key;
- final Object signerIdentifier;
- final String digestOID;
- final String encOID;
- final CMSAttributeTableGenerator sAttr;
- final CMSAttributeTableGenerator unsAttr;
- final AttributeTable baseSignedTable;
-
- SignerInf(
- PrivateKey key,
- Object signerIdentifier,
- String digestOID,
- String encOID,
- CMSAttributeTableGenerator sAttr,
- CMSAttributeTableGenerator unsAttr,
- AttributeTable baseSignedTable)
- {
- this.key = key;
- this.signerIdentifier = signerIdentifier;
- this.digestOID = digestOID;
- this.encOID = encOID;
- this.sAttr = sAttr;
- this.unsAttr = unsAttr;
- this.baseSignedTable = baseSignedTable;
- }
-
- SignerInfoGenerator toSignerInfoGenerator(
- SecureRandom random,
- Provider sigProvider,
- boolean addDefaultAttributes)
- throws IOException, CertificateEncodingException, CMSException, OperatorCreationException, NoSuchAlgorithmException
- {
- String digestName = CMSSignedHelper.INSTANCE.getDigestAlgName(digestOID);
- String signatureName = digestName + "with" + CMSSignedHelper.INSTANCE.getEncryptionAlgName(encOID);
-
- JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new BcDigestCalculatorProvider());
-
- if (addDefaultAttributes)
- {
- builder.setSignedAttributeGenerator(sAttr);
- }
- builder.setDirectSignature(!addDefaultAttributes);
-
- builder.setUnsignedAttributeGenerator(unsAttr);
-
- JcaContentSignerBuilder signerBuilder;
-
- try
- {
- signerBuilder = new JcaContentSignerBuilder(signatureName).setSecureRandom(random);
- }
- catch (IllegalArgumentException e)
- {
- throw new NoSuchAlgorithmException(e.getMessage());
- }
-
- if (sigProvider != null)
- {
- signerBuilder.setProvider(sigProvider);
- }
-
- ContentSigner contentSigner = signerBuilder.build(key);
- if (signerIdentifier instanceof X509Certificate)
- {
- return builder.build(contentSigner, (X509Certificate)signerIdentifier);
- }
- else
- {
- return builder.build(contentSigner, (byte[])signerIdentifier);
- }
- }
- }
/**
* base constructor
*/
@@ -144,463 +57,24 @@ public class CMSSignedDataGenerator
}
/**
- * constructor allowing specific source of randomness
- * @param rand instance of SecureRandom to use
- * @deprecated rand ignored in new API, use base constructor.
- */
- public CMSSignedDataGenerator(
- SecureRandom rand)
- {
- super(rand);
- }
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here.
- *
- * @param key signing key to use
- * @param cert certificate containing corresponding public key
- * @param digestOID digest algorithm OID
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String digestOID)
- throws IllegalArgumentException
- {
- addSigner(key, cert, getEncOID(key, digestOID), digestOID);
- }
-
- /**
- * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
- * provided here.
- *
- * @param key signing key to use
- * @param cert certificate containing corresponding public key
- * @param encryptionOID digest encryption algorithm OID
- * @param digestOID digest algorithm OID
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID)
- throws IllegalArgumentException
- {
- doAddSigner(key, cert, encryptionOID, digestOID,
- new DefaultSignedAttributeTableGenerator(), null, null);
- }
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here.
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String digestOID)
- throws IllegalArgumentException
- {
- addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID);
- }
-
- /**
- * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
- * provided here.
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String encryptionOID,
- String digestOID)
- throws IllegalArgumentException
- {
- doAddSigner(key, subjectKeyID, encryptionOID, digestOID,
- new DefaultSignedAttributeTableGenerator(), null, null);
- }
-
- /**
- * add a signer with extra signed/unsigned attributes.
+ * Generate a CMS Signed Data object carrying a detached CMS signature.
*
- * @param key signing key to use
- * @param cert certificate containing corresponding public key
- * @param digestOID digest algorithm OID
- * @param signedAttr table of attributes to be included in signature
- * @param unsignedAttr table of attributes to be included as unsigned
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr)
- throws IllegalArgumentException
- {
- addSigner(key, cert, getEncOID(key, digestOID), digestOID, signedAttr, unsignedAttr);
- }
-
- /**
- * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
- *
- * @param key signing key to use
- * @param cert certificate containing corresponding public key
- * @param encryptionOID digest encryption algorithm OID
- * @param digestOID digest algorithm OID
- * @param signedAttr table of attributes to be included in signature
- * @param unsignedAttr table of attributes to be included as unsigned
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr)
- throws IllegalArgumentException
- {
- doAddSigner(key, cert, encryptionOID, digestOID,
- new DefaultSignedAttributeTableGenerator(signedAttr),
- new SimpleAttributeTableGenerator(unsignedAttr), signedAttr);
- }
-
- /**
- * add a signer with extra signed/unsigned attributes.
- *
- * @param key signing key to use
- * @param subjectKeyID subjectKeyID of corresponding public key
- * @param digestOID digest algorithm OID
- * @param signedAttr table of attributes to be included in signature
- * @param unsignedAttr table of attributes to be included as unsigned
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr)
- throws IllegalArgumentException
- {
- addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID, signedAttr,
- unsignedAttr);
- }
-
- /**
- * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
- *
- * @param key signing key to use
- * @param subjectKeyID subjectKeyID of corresponding public key
- * @param encryptionOID digest encryption algorithm OID
- * @param digestOID digest algorithm OID
- * @param signedAttr table of attributes to be included in signature
- * @param unsignedAttr table of attributes to be included as unsigned
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String encryptionOID,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr)
- throws IllegalArgumentException
- {
- doAddSigner(key, subjectKeyID, encryptionOID, digestOID,
- new DefaultSignedAttributeTableGenerator(signedAttr),
- new SimpleAttributeTableGenerator(unsignedAttr), signedAttr);
- }
-
- /**
- * add a signer with extra signed/unsigned attributes based on generators.
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGen,
- CMSAttributeTableGenerator unsignedAttrGen)
- throws IllegalArgumentException
- {
- addSigner(key, cert, getEncOID(key, digestOID), digestOID, signedAttrGen, unsignedAttrGen);
- }
-
- /**
- * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGen,
- CMSAttributeTableGenerator unsignedAttrGen)
- throws IllegalArgumentException
- {
- doAddSigner(key, cert, encryptionOID, digestOID, signedAttrGen,
- unsignedAttrGen, null);
- }
-
- /**
- * add a signer with extra signed/unsigned attributes based on generators.
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGen,
- CMSAttributeTableGenerator unsignedAttrGen)
- throws IllegalArgumentException
- {
- addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID, signedAttrGen,
- unsignedAttrGen);
- }
-
- /**
- * add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String encryptionOID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGen,
- CMSAttributeTableGenerator unsignedAttrGen)
- throws IllegalArgumentException
- {
- doAddSigner(key, subjectKeyID, encryptionOID, digestOID,
- signedAttrGen, unsignedAttrGen, null);
- }
-
- private void doAddSigner(
- PrivateKey key,
- Object signerIdentifier,
- String encryptionOID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGen,
- CMSAttributeTableGenerator unsignedAttrGen,
- AttributeTable baseSignedTable)
- throws IllegalArgumentException
- {
- signerInfs.add(new SignerInf(key, signerIdentifier, digestOID, encryptionOID,
- signedAttrGen, unsignedAttrGen, baseSignedTable));
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object using the given provider.
- * @deprecated use generate() method not taking provider.
+ * @param content the content to be signed.
*/
public CMSSignedData generate(
- CMSProcessable content,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return generate(content, CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object using the given provider.
- * @deprecated use generate() method not taking provider.
- */
- public CMSSignedData generate(
- CMSProcessable content,
- Provider sigProvider)
- throws NoSuchAlgorithmException, CMSException
- {
- return generate(content, false, sigProvider);
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object using the given provider - if encapsulate is true a copy
- * of the message will be included in the signature. The content type
- * is set according to the OID represented by the string signedContentType.
- * @deprecated use generate(CMSTypedData, boolean)
- */
- public CMSSignedData generate(
- String eContentType,
- CMSProcessable content,
- boolean encapsulate,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return generate(eContentType, content, encapsulate, CMSUtils.getProvider(sigProvider),
- true);
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object using the given provider - if encapsulate is true a copy
- * of the message will be included in the signature. The content type
- * is set according to the OID represented by the string signedContentType.
- * @deprecated use generate(CMSTypedData, boolean)
- */
- public CMSSignedData generate(
- String eContentType,
- CMSProcessable content,
- boolean encapsulate,
- Provider sigProvider)
- throws NoSuchAlgorithmException, CMSException
- {
- return generate(eContentType, content, encapsulate, sigProvider, true);
- }
-
- /**
- * Similar method to the other generate methods. The additional argument
- * addDefaultAttributes indicates whether or not a default set of signed attributes
- * need to be added automatically. If the argument is set to false, no
- * attributes will get added at all.
- * @deprecated use generate(CMSTypedData, boolean)
- */
- public CMSSignedData generate(
- String eContentType,
- CMSProcessable content,
- boolean encapsulate,
- String sigProvider,
- boolean addDefaultAttributes)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return generate(eContentType, content, encapsulate, CMSUtils.getProvider(sigProvider),
- addDefaultAttributes);
- }
-
- /**
- * Similar method to the other generate methods. The additional argument
- * addDefaultAttributes indicates whether or not a default set of signed attributes
- * need to be added automatically. If the argument is set to false, no
- * attributes will get added at all.
- * @deprecated use setDirectSignature() on SignerInformationGenerator.
- */
- public CMSSignedData generate(
- String eContentType,
- final CMSProcessable content,
- boolean encapsulate,
- Provider sigProvider,
- boolean addDefaultAttributes)
- throws NoSuchAlgorithmException, CMSException
- {
- boolean isCounterSignature = (eContentType == null);
-
- final ASN1ObjectIdentifier contentTypeOID = isCounterSignature
- ? null
- : new ASN1ObjectIdentifier(eContentType);
-
- for (Iterator it = signerInfs.iterator(); it.hasNext();)
- {
- SignerInf signer = (SignerInf)it.next();
-
- try
- {
- signerGens.add(signer.toSignerInfoGenerator(rand, sigProvider,
- addDefaultAttributes));
- }
- catch (OperatorCreationException e)
- {
- throw new CMSException("exception creating signerInf", e);
- }
- catch (IOException e)
- {
- throw new CMSException("exception encoding attributes", e);
- }
- catch (CertificateEncodingException e)
- {
- throw new CMSException("error creating sid.", e);
- }
- }
-
- signerInfs.clear();
-
- if (content != null)
- {
- return generate(new CMSTypedData()
- {
- public ASN1ObjectIdentifier getContentType()
- {
- return contentTypeOID;
- }
-
- public void write(OutputStream out)
- throws IOException, CMSException
- {
- content.write(out);
- }
-
- public Object getContent()
- {
- return content.getContent();
- }
- }, encapsulate);
- }
- else
- {
- return generate(new CMSAbsentContent(contentTypeOID), encapsulate);
- }
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object using the given provider - if encapsulate is true a copy
- * of the message will be included in the signature with the
- * default content type "data".
- * @deprecated use generate(CMSTypedData, boolean)
- */
- public CMSSignedData generate(
- CMSProcessable content,
- boolean encapsulate,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- if (content instanceof CMSTypedData)
- {
- return this.generate(((CMSTypedData)content).getContentType().getId(), content, encapsulate, sigProvider);
- }
- else
- {
- return this.generate(DATA, content, encapsulate, sigProvider);
- }
- }
-
- /**
- * generate a signed object that for a CMS Signed Data
- * object using the given provider - if encapsulate is true a copy
- * of the message will be included in the signature with the
- * default content type "data".
- * @deprecated use generate(CMSTypedData, boolean)
- */
- public CMSSignedData generate(
- CMSProcessable content,
- boolean encapsulate,
- Provider sigProvider)
- throws NoSuchAlgorithmException, CMSException
- {
- if (content instanceof CMSTypedData)
- {
- return this.generate(((CMSTypedData)content).getContentType().getId(), content, encapsulate, sigProvider);
- }
- else
- {
- return this.generate(DATA, content, encapsulate, sigProvider);
- }
- }
-
- public CMSSignedData generate(
CMSTypedData content)
throws CMSException
{
return generate(content, false);
}
+ /**
+ * Generate a CMS Signed Data object which can be carrying a detached CMS signature, or have encapsulated data, depending on the value
+ * of the encapsulated parameter.
+ *
+ * @param content the content to be signed.
+ * @param encapsulate true if the content should be encapsulated in the signature, false otherwise.
+ */
public CMSSignedData generate(
// FIXME Avoid accessing more than once to support CMSProcessableInputStream
CMSTypedData content,
@@ -747,36 +221,6 @@ public class CMSSignedDataGenerator
* the passed in SignerInformation object.
*
* @param signer the signer to be countersigned
- * @param sigProvider the provider to be used for counter signing.
- * @return a store containing the signers.
- * @deprecated use generateCounterSigners(SignerInformation)
- */
- public SignerInformationStore generateCounterSigners(SignerInformation signer, Provider sigProvider)
- throws NoSuchAlgorithmException, CMSException
- {
- return this.generate(null, new CMSProcessableByteArray(signer.getSignature()), false, sigProvider).getSignerInfos();
- }
-
- /**
- * generate a set of one or more SignerInformation objects representing counter signatures on
- * the passed in SignerInformation object.
- *
- * @param signer the signer to be countersigned
- * @param sigProvider the provider to be used for counter signing.
- * @return a store containing the signers.
- * @deprecated use generateCounterSigners(SignerInformation)
- */
- public SignerInformationStore generateCounterSigners(SignerInformation signer, String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return this.generate(null, new CMSProcessableByteArray(signer.getSignature()), false, CMSUtils.getProvider(sigProvider)).getSignerInfos();
- }
-
- /**
- * generate a set of one or more SignerInformation objects representing counter signatures on
- * the passed in SignerInformation object.
- *
- * @param signer the signer to be countersigned
* @return a store containing the signers.
*/
public SignerInformationStore generateCounterSigners(SignerInformation signer)
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java
index 6c80bb4..329f089 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java
@@ -4,11 +4,6 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -35,15 +30,11 @@ import org.bouncycastle.asn1.cms.ContentInfoParser;
import org.bouncycastle.asn1.cms.SignedDataParser;
import org.bouncycastle.asn1.cms.SignerInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cert.jcajce.JcaCertStoreBuilder;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
import org.bouncycastle.util.Store;
import org.bouncycastle.util.io.Streams;
-import org.bouncycastle.x509.NoSuchStoreException;
-import org.bouncycastle.x509.X509Store;
/**
* Parsing class for an CMS Signed Data object from an input stream.
@@ -100,22 +91,8 @@ public class CMSSignedDataParser
private Map digests;
private SignerInformationStore _signerInfoStore;
- private X509Store _attributeStore;
private ASN1Set _certSet, _crlSet;
private boolean _isCertCrlParsed;
- private X509Store _certificateStore;
- private X509Store _crlStore;
-
- /**
- * @deprecated use method taking a DigestCalculatorProvider
- */
- public CMSSignedDataParser(
- byte[] sigBlock)
- throws CMSException
- {
- this(createDefaultDigestProvider(), new ByteArrayInputStream(sigBlock));
- }
-
public CMSSignedDataParser(
DigestCalculatorProvider digestCalculatorProvider,
@@ -125,20 +102,6 @@ public class CMSSignedDataParser
this(digestCalculatorProvider, new ByteArrayInputStream(sigBlock));
}
- /**
- * @deprecated use method taking digest calculator provider.
- * @param signedContent
- * @param sigBlock
- * @throws CMSException
- */
- public CMSSignedDataParser(
- CMSTypedStream signedContent,
- byte[] sigBlock)
- throws CMSException
- {
- this(createDefaultDigestProvider(), signedContent, new ByteArrayInputStream(sigBlock));
- }
-
public CMSSignedDataParser(
DigestCalculatorProvider digestCalculatorProvider,
CMSTypedStream signedContent,
@@ -148,26 +111,8 @@ public class CMSSignedDataParser
this(digestCalculatorProvider, signedContent, new ByteArrayInputStream(sigBlock));
}
- private static DigestCalculatorProvider createDefaultDigestProvider()
- throws CMSException
- {
- return new BcDigestCalculatorProvider();
- }
-
/**
* base constructor - with encapsulated content
- *
- * @deprecated use method taking a DigestCalculatorProvider
- */
- public CMSSignedDataParser(
- InputStream sigData)
- throws CMSException
- {
- this(createDefaultDigestProvider(), null, sigData);
- }
-
- /**
- * base constructor - with encapsulated content
*/
public CMSSignedDataParser(
DigestCalculatorProvider digestCalculatorProvider,
@@ -180,22 +125,6 @@ public class CMSSignedDataParser
/**
* base constructor
*
- * @param signedContent the content that was signed.
- * @param sigData the signature object stream.
- * *
- * @deprecated use method taking a DigestCalculatorProvider
- */
- public CMSSignedDataParser(
- CMSTypedStream signedContent,
- InputStream sigData)
- throws CMSException
- {
- this(createDefaultDigestProvider(), signedContent, sigData);
- }
-
- /**
- * base constructor
- *
* @param digestCalculatorProvider for generating accumulating digests
* @param signedContent the content that was signed.
* @param sigData the signature object stream.
@@ -273,11 +202,6 @@ public class CMSSignedDataParser
{
throw new CMSException("io exception: " + e.getMessage(), e);
}
-
- if (digests.isEmpty())
- {
- throw new CMSException("no digests could be created for message.");
- }
}
/**
@@ -339,201 +263,6 @@ public class CMSSignedDataParser
}
/**
- * return a X509Store containing the attribute certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider name of provider to use
- * @return a store of attribute certificates
- * @exception NoSuchProviderException if the provider requested isn't available.
- * @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use getAttributeCertificates()
- */
- public X509Store getAttributeCertificates(
- String type,
- String provider)
- throws NoSuchStoreException, NoSuchProviderException, CMSException
- {
- return getAttributeCertificates(type, CMSUtils.getProvider(provider));
- }
-
- /**
- * return a X509Store containing the attribute certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider provider to use
- * @return a store of attribute certificates
- * @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use getAttributeCertificates()
- */
- public X509Store getAttributeCertificates(
- String type,
- Provider provider)
- throws NoSuchStoreException, CMSException
- {
- if (_attributeStore == null)
- {
- populateCertCrlSets();
-
- _attributeStore = HELPER.createAttributeStore(type, provider, this.getAttributeCertificates());
- }
-
- return _attributeStore;
- }
-
- /**
- * return a X509Store containing the public key certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider provider to use
- * @return a store of public key certificates
- * @exception NoSuchProviderException if the provider requested isn't available.
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use getCertificates()
- */
- public X509Store getCertificates(
- String type,
- String provider)
- throws NoSuchStoreException, NoSuchProviderException, CMSException
- {
- return getCertificates(type, CMSUtils.getProvider(provider));
- }
-
- /**
- * return a X509Store containing the public key certificates, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider provider to use
- * @return a store of public key certificates
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use getCertificates()
- */
- public X509Store getCertificates(
- String type,
- Provider provider)
- throws NoSuchStoreException, CMSException
- {
- if (_certificateStore == null)
- {
- populateCertCrlSets();
-
- _certificateStore = HELPER.createCertificateStore(type, provider, this.getCertificates());
- }
-
- return _certificateStore;
- }
-
- /**
- * return a X509Store containing CRLs, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider name of provider to use
- * @return a store of CRLs
- * @exception NoSuchProviderException if the provider requested isn't available.
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use getCRLs()
- */
- public X509Store getCRLs(
- String type,
- String provider)
- throws NoSuchStoreException, NoSuchProviderException, CMSException
- {
- return getCRLs(type, CMSUtils.getProvider(provider));
- }
-
- /**
- * return a X509Store containing CRLs, if any, contained
- * in this message.
- *
- * @param type type of store to create
- * @param provider provider to use
- * @return a store of CRLs
- * @exception NoSuchStoreException if the store type isn't available.
- * @exception CMSException if a general exception prevents creation of the X509Store
- * @deprecated use getCRLs()
- */
- public X509Store getCRLs(
- String type,
- Provider provider)
- throws NoSuchStoreException, CMSException
- {
- if (_crlStore == null)
- {
- populateCertCrlSets();
-
- _crlStore = HELPER.createCRLsStore(type, provider, getCRLs());
- }
-
- return _crlStore;
- }
-
- /**
- * return a CertStore containing the certificates and CRLs associated with
- * this message.
- *
- * @exception NoSuchProviderException if the provider requested isn't available.
- * @exception NoSuchAlgorithmException if the cert store isn't available.
- * @exception CMSException if a general exception prevents creation of the CertStore
- * @deprecated use getCertificates() and org.bouncycastle.cert.jcajce.JcaCertStoreBuilder
- */
- public CertStore getCertificatesAndCRLs(
- String type,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return getCertificatesAndCRLs(type, CMSUtils.getProvider(provider));
- }
-
- /**
- * return a CertStore containing the certificates and CRLs associated with
- * this message.
- *
- * @exception NoSuchProviderException if the provider requested isn't available.
- * @exception NoSuchAlgorithmException if the cert store isn't available.
- * @exception CMSException if a general exception prevents creation of the CertStore
- * @deprecated use getCertificates() and org.bouncycastle.cert.jcajce.JcaCertStoreBuilder
- */
- public CertStore getCertificatesAndCRLs(
- String type,
- Provider provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- populateCertCrlSets();
-
- try
- {
- JcaCertStoreBuilder certStoreBuilder = new JcaCertStoreBuilder().setType(type);
-
- if (provider != null)
- {
- certStoreBuilder.setProvider(provider);
- }
-
- certStoreBuilder.addCertificates(this.getCertificates());
- certStoreBuilder.addCRLs(this.getCRLs());
-
- return certStoreBuilder.build();
- }
- catch (NoSuchAlgorithmException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new CMSException("exception creating CertStore: " + e.getMessage(), e);
- }
- }
-
- /**
* Return any X.509 certificate objects in this SignedData structure as a Store of X509CertificateHolder objects.
*
* @return a Store of X509CertificateHolder objects.
@@ -719,102 +448,6 @@ public class CMSSignedDataParser
* The output stream is returned unclosed.
* </p>
* @param original the signed data stream to be used as a base.
- * @param certsAndCrls the new certificates and CRLs to be used.
- * @param out the stream to write the new signed data object to.
- * @return out.
- * @exception CMSException if there is an error processing the CertStore
- * @deprecated use method that takes Store objects.
- */
- public static OutputStream replaceCertificatesAndCRLs(
- InputStream original,
- CertStore certsAndCrls,
- OutputStream out)
- throws CMSException, IOException
- {
- ASN1StreamParser in = new ASN1StreamParser(original);
- ContentInfoParser contentInfo = new ContentInfoParser((ASN1SequenceParser)in.readObject());
- SignedDataParser signedData = SignedDataParser.getInstance(contentInfo.getContent(BERTags.SEQUENCE));
-
- BERSequenceGenerator sGen = new BERSequenceGenerator(out);
-
- sGen.addObject(CMSObjectIdentifiers.signedData);
-
- BERSequenceGenerator sigGen = new BERSequenceGenerator(sGen.getRawOutputStream(), 0, true);
-
- // version number
- sigGen.addObject(signedData.getVersion());
-
- // digests
- sigGen.getRawOutputStream().write(signedData.getDigestAlgorithms().toASN1Primitive().getEncoded());
-
- // encap content info
- ContentInfoParser encapContentInfo = signedData.getEncapContentInfo();
-
- BERSequenceGenerator eiGen = new BERSequenceGenerator(sigGen.getRawOutputStream());
-
- eiGen.addObject(encapContentInfo.getContentType());
-
- pipeEncapsulatedOctetString(encapContentInfo, eiGen.getRawOutputStream());
-
- eiGen.close();
-
- //
- // skip existing certs and CRLs
- //
- getASN1Set(signedData.getCertificates());
- getASN1Set(signedData.getCrls());
-
- //
- // replace the certs and crls in the SignedData object
- //
- ASN1Set certs;
-
- try
- {
- certs = CMSUtils.createBerSetFromList(CMSUtils.getCertificatesFromStore(certsAndCrls));
- }
- catch (CertStoreException e)
- {
- throw new CMSException("error getting certs from certStore", e);
- }
-
- if (certs.size() > 0)
- {
- sigGen.getRawOutputStream().write(new DERTaggedObject(false, 0, certs).getEncoded());
- }
-
- ASN1Set crls;
-
- try
- {
- crls = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(certsAndCrls));
- }
- catch (CertStoreException e)
- {
- throw new CMSException("error getting crls from certStore", e);
- }
-
- if (crls.size() > 0)
- {
- sigGen.getRawOutputStream().write(new DERTaggedObject(false, 1, crls).getEncoded());
- }
-
- sigGen.getRawOutputStream().write(signedData.getSignerInfos().toASN1Primitive().getEncoded());
-
- sigGen.close();
-
- sGen.close();
-
- return out;
- }
-
- /**
- * Replace the certificate and CRL information associated with this
- * CMSSignedData object with the new one passed in.
- * <p>
- * The output stream is returned unclosed.
- * </p>
- * @param original the signed data stream to be used as a base.
* @param certs new certificates to be used, if any.
* @param crls new CRLs to be used, if any.
* @param attrCerts new attribute certificates to be used, if any.
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataStreamGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataStreamGenerator.java
index cbd1c50..1e09b48 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataStreamGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedDataStreamGenerator.java
@@ -2,14 +2,6 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.Provider;
-import java.security.SecureRandom;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.List;
@@ -21,14 +13,8 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.BERSequenceGenerator;
import org.bouncycastle.asn1.BERTaggedObject;
import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.SignerInfo;
-import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
-import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
/**
* General class for generating a pkcs7-signature message stream.
@@ -71,17 +57,6 @@ public class CMSSignedDataStreamGenerator
}
/**
- * constructor allowing specific source of randomness
- * @param rand instance of SecureRandom to use
- * @deprecated no longer required if the addSignerInfoGenerator method is used.
- */
- public CMSSignedDataStreamGenerator(
- SecureRandom rand)
- {
- super(rand);
- }
-
- /**
* Set the underlying string size for encapsulated data
*
* @param bufferSize length of octet strings to buffer the data.
@@ -91,514 +66,6 @@ public class CMSSignedDataStreamGenerator
{
_bufferSize = bufferSize;
}
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here.
- * @throws NoSuchProviderException
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, cert, digestOID, CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here.
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- Provider sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, cert, digestOID, new DefaultSignedAttributeTableGenerator(),
- (CMSAttributeTableGenerator)null, sigProvider);
- }
-
- /**
- * add a signer, specifying the digest encryption algorithm - no attributes other than the default ones will be
- * provided here.
- * @throws NoSuchProviderException
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, cert, encryptionOID, digestOID, CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * add a signer, specifying digest encryptionOID - no attributes other than the default ones will be
- * provided here.
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID,
- Provider sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, cert, encryptionOID, digestOID, new DefaultSignedAttributeTableGenerator(),
- (CMSAttributeTableGenerator)null, sigProvider);
- }
-
- /**
- * add a signer with extra signed/unsigned attributes.
- * @throws NoSuchProviderException
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, cert, digestOID, signedAttr, unsignedAttr,
- CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * add a signer with extra signed/unsigned attributes.
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr,
- Provider sigProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- addSigner(key, cert, digestOID, new DefaultSignedAttributeTableGenerator(signedAttr),
- new SimpleAttributeTableGenerator(unsignedAttr), sigProvider);
- }
-
- /**
- * add a signer with extra signed/unsigned attributes - specifying digest
- * encryption algorithm.
- * @throws NoSuchProviderException
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, cert, encryptionOID, digestOID, signedAttr, unsignedAttr,
- CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * add a signer with extra signed/unsigned attributes and the digest encryption algorithm.
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr,
- Provider sigProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- addSigner(key, cert, encryptionOID, digestOID,
- new DefaultSignedAttributeTableGenerator(signedAttr),
- new SimpleAttributeTableGenerator(unsignedAttr), sigProvider);
- }
-
- /**
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, cert, digestOID, signedAttrGenerator, unsignedAttrGenerator,
- CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- Provider sigProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- addSigner(key, cert, getEncOID(key, digestOID), digestOID, signedAttrGenerator,
- unsignedAttrGenerator, sigProvider);
- }
-
- /**
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, cert, encryptionOID, digestOID, signedAttrGenerator, unsignedAttrGenerator,
- CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- Provider sigProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- addSigner(key, cert, encryptionOID, digestOID, signedAttrGenerator, unsignedAttrGenerator, sigProvider, sigProvider);
- }
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here.
- * @throws NoSuchProviderException
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String digestOID,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, digestOID, CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here.
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String digestOID,
- Provider sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, digestOID, new DefaultSignedAttributeTableGenerator(),
- (CMSAttributeTableGenerator)null, sigProvider);
- }
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here.
- * @throws NoSuchProviderException
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignedInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String encryptionOID,
- String digestOID,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, encryptionOID, digestOID, CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * add a signer - no attributes other than the default ones will be
- * provided here, specifying the digest encryption algorithm.
- *
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String encryptionOID,
- String digestOID,
- Provider sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, encryptionOID, digestOID,
- new DefaultSignedAttributeTableGenerator(), (CMSAttributeTableGenerator)null,
- sigProvider);
- }
-
- /**
- * add a signer with extra signed/unsigned attributes.
- * @throws NoSuchProviderException
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, digestOID, signedAttr, unsignedAttr,
- CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * add a signer with extra signed/unsigned attributes.
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String digestOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr,
- Provider sigProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, digestOID,
- new DefaultSignedAttributeTableGenerator(signedAttr),
- new SimpleAttributeTableGenerator(unsignedAttr), sigProvider);
- }
-
- /**
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, digestOID, signedAttrGenerator, unsignedAttrGenerator,
- CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- Provider sigProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID, signedAttrGenerator,
- unsignedAttrGenerator, sigProvider);
- }
-
- /**
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String encryptionOID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, encryptionOID, digestOID, signedAttrGenerator,
- unsignedAttrGenerator, CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String encryptionOID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- Provider sigProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- addSigner(key, subjectKeyID, encryptionOID, digestOID, signedAttrGenerator, unsignedAttrGenerator, sigProvider, sigProvider);
- }
-
- /**
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- X509Certificate cert,
- String encryptionOID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- Provider sigProvider,
- Provider digProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- doAddSigner(key, cert, encryptionOID, digestOID, signedAttrGenerator, unsignedAttrGenerator, sigProvider, digProvider);
- }
-
- private void doAddSigner(PrivateKey key, Object signerId, String encryptionOID, String digestOID, CMSAttributeTableGenerator signedAttrGenerator, CMSAttributeTableGenerator unsignedAttrGenerator, Provider sigProvider, Provider digProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- String digestName = CMSSignedHelper.INSTANCE.getDigestAlgName(digestOID);
- String signatureName = digestName + "with" + CMSSignedHelper.INSTANCE.getEncryptionAlgName(encryptionOID);
-
- JcaContentSignerBuilder signerBuilder;
-
- try
- {
- signerBuilder = new JcaContentSignerBuilder(signatureName).setSecureRandom(rand);
- }
- catch (IllegalArgumentException e)
- {
- throw new NoSuchAlgorithmException(e.getMessage());
- }
-
- if (sigProvider != null)
- {
- signerBuilder.setProvider(sigProvider);
- }
-
- try
- {
- JcaDigestCalculatorProviderBuilder calculatorProviderBuilder = new JcaDigestCalculatorProviderBuilder();
-
- if (digProvider != null && !digProvider.getName().equalsIgnoreCase("SunRsaSign"))
- {
- calculatorProviderBuilder.setProvider(digProvider);
- }
-
- JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(calculatorProviderBuilder.build());
-
- builder.setSignedAttributeGenerator(signedAttrGenerator);
-
- builder.setUnsignedAttributeGenerator(unsignedAttrGenerator);
-
- try
- {
- ContentSigner contentSigner = signerBuilder.build(key);
-
- if (signerId instanceof X509Certificate)
- {
- addSignerInfoGenerator(builder.build(contentSigner, (X509Certificate)signerId));
- }
- else
- {
- addSignerInfoGenerator(builder.build(contentSigner, (byte[])signerId));
- }
- }
- catch (OperatorCreationException e)
- {
- if (e.getCause() instanceof NoSuchAlgorithmException)
- {
- throw (NoSuchAlgorithmException)e.getCause();
- }
- if (e.getCause() instanceof InvalidKeyException)
- {
- throw (InvalidKeyException)e.getCause();
- }
- }
- }
- catch (OperatorCreationException e)
- {
- throw new NoSuchAlgorithmException("unable to create operators: " + e.getMessage());
- }
- catch (CertificateEncodingException e)
- {
- throw new IllegalStateException("unable to encode certificate");
- }
- }
-
- /**
- * @deprecated use addSignerInfoGenerator
- */
- public void addSigner(
- PrivateKey key,
- byte[] subjectKeyID,
- String encryptionOID,
- String digestOID,
- CMSAttributeTableGenerator signedAttrGenerator,
- CMSAttributeTableGenerator unsignedAttrGenerator,
- Provider sigProvider,
- Provider digProvider)
- throws NoSuchAlgorithmException, InvalidKeyException
- {
- doAddSigner(key, subjectKeyID, encryptionOID, digestOID, signedAttrGenerator, unsignedAttrGenerator, sigProvider, digProvider);
- }
/**
* generate a signed object that for a CMS Signed Data
@@ -645,18 +112,6 @@ public class CMSSignedDataStreamGenerator
}
/**
- * @deprecated use open(ASN1ObjectIdentifier, OutputStream, boolean)
- */
- public OutputStream open(
- OutputStream out,
- String eContentType,
- boolean encapsulate)
- throws IOException
- {
- return open(out, eContentType, encapsulate, null);
- }
-
- /**
* generate a signed object that for a CMS Signed Data
* object using the given provider - if encapsulate is true a copy
* of the message will be included in the signature. The content type
@@ -672,19 +127,6 @@ public class CMSSignedDataStreamGenerator
}
/**
- * @deprecated use open(ASN1ObjectIdenfier, OutputStream, boolean, OutputStream)
- */
- public OutputStream open(
- OutputStream out,
- String eContentType,
- boolean encapsulate,
- OutputStream dataOutputStream)
- throws IOException
- {
- return open(new ASN1ObjectIdentifier(eContentType), out, encapsulate, dataOutputStream);
- }
-
- /**
* generate a signed object that for a CMS Signed Data
* object using the given provider - if encapsulate is true a copy
* of the message will be included in the signature. The content type
@@ -786,23 +228,6 @@ public class CMSSignedDataStreamGenerator
return new CmsSignedDataOutputStream(sigStream, eContentType, sGen, sigGen, eiGen);
}
- // TODO Make public?
- void generate(
- OutputStream out,
- String eContentType,
- boolean encapsulate,
- OutputStream dataOutputStream,
- CMSProcessable content)
- throws CMSException, IOException
- {
- OutputStream signedOut = open(out, eContentType, encapsulate, dataOutputStream);
- if (content != null)
- {
- content.write(signedOut);
- }
- signedOut.close();
- }
-
// RFC3852, section 5.1:
// IF ((certificates is present) AND
// (any certificates with a type of other are present)) OR
@@ -915,7 +340,7 @@ public class CMSSignedDataStreamGenerator
{
SignerInfoGenerator s = (SignerInfoGenerator)it.next();
- if (s.getGeneratedVersion().getValue().intValue() == 3)
+ if (s.getGeneratedVersion() == 3)
{
return true;
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedGenerator.java
index 84369e7..9fe6779 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedGenerator.java
@@ -1,12 +1,5 @@
package org.bouncycastle.cms;
-import java.io.IOException;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -17,11 +10,7 @@ import java.util.Set;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
@@ -30,16 +19,12 @@ import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.AttributeCertificate;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.jce.interfaces.GOST3410PrivateKey;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Store;
-import org.bouncycastle.x509.X509AttributeCertificate;
-import org.bouncycastle.x509.X509Store;
public class CMSSignedGenerator
{
@@ -98,62 +83,11 @@ public class CMSSignedGenerator
protected List signerGens = new ArrayList();
protected Map digests = new HashMap();
- protected final SecureRandom rand;
-
/**
* base constructor
*/
protected CMSSignedGenerator()
{
- this(new SecureRandom());
- }
-
- /**
- * constructor allowing specific source of randomness
- * @param rand instance of SecureRandom to use
- */
- protected CMSSignedGenerator(
- SecureRandom rand)
- {
- this.rand = rand;
- }
-
- protected String getEncOID(
- PrivateKey key,
- String digestOID)
- {
- String encOID = null;
-
- if (key instanceof RSAPrivateKey || "RSA".equalsIgnoreCase(key.getAlgorithm()))
- {
- encOID = ENCRYPTION_RSA;
- }
- else if (key instanceof DSAPrivateKey || "DSA".equalsIgnoreCase(key.getAlgorithm()))
- {
- encOID = ENCRYPTION_DSA;
- if (!digestOID.equals(DIGEST_SHA1))
- {
- throw new IllegalArgumentException("can't mix DSA with anything but SHA1");
- }
- }
- else if ("ECDSA".equalsIgnoreCase(key.getAlgorithm()) || "EC".equalsIgnoreCase(key.getAlgorithm()))
- {
- encOID = (String)EC_ALGORITHMS.get(digestOID);
- if (encOID == null)
- {
- throw new IllegalArgumentException("can't mix ECDSA with anything but SHA family digests");
- }
- }
- else if (key instanceof GOST3410PrivateKey || "GOST3410".equalsIgnoreCase(key.getAlgorithm()))
- {
- encOID = ENCRYPTION_GOST3410;
- }
- else if ("ECGOST3410".equalsIgnoreCase(key.getAlgorithm()))
- {
- encOID = ENCRYPTION_ECGOST3410;
- }
-
- return encOID;
}
protected Map getBaseParameters(ASN1ObjectIdentifier contentType, AlgorithmIdentifier digAlgId, byte[] hash)
@@ -165,36 +99,6 @@ public class CMSSignedGenerator
return param;
}
- protected ASN1Set getAttributeSet(
- AttributeTable attr)
- {
- if (attr != null)
- {
- return new DERSet(attr.toASN1EncodableVector());
- }
-
- return null;
- }
-
- /**
- * add the certificates and CRLs contained in the given CertStore
- * to the pool that will be included in the encoded signature block.
- * <p>
- * Note: this assumes the CertStore will support null in the get
- * methods.
- * @param certStore CertStore containing the public key certificates and CRLs
- * @throws java.security.cert.CertStoreException if an issue occurs processing the CertStore
- * @throws CMSException if an issue occurse transforming data from the CertStore into the message
- * @deprecated use addCertificates and addCRLs
- */
- public void addCertificatesAndCRLs(
- CertStore certStore)
- throws CertStoreException, CMSException
- {
- certs.addAll(CMSUtils.getCertificatesFromStore(certStore));
- crls.addAll(CMSUtils.getCRLsFromStore(certStore));
- }
-
/**
* Add a certificate to the certificate set to be included with the generated SignedData message.
*
@@ -297,40 +201,7 @@ public class CMSSignedGenerator
}
/**
- * Add the attribute certificates contained in the passed in store to the
- * generator.
- *
- * @param store a store of Version 2 attribute certificates
- * @throws CMSException if an error occurse processing the store.
- * @deprecated use basic Store method
- */
- public void addAttributeCertificates(
- X509Store store)
- throws CMSException
- {
- try
- {
- for (Iterator it = store.getMatches(null).iterator(); it.hasNext();)
- {
- X509AttributeCertificate attrCert = (X509AttributeCertificate)it.next();
-
- certs.add(new DERTaggedObject(false, 2,
- AttributeCertificate.getInstance(ASN1Primitive.fromByteArray(attrCert.getEncoded()))));
- }
- }
- catch (IllegalArgumentException e)
- {
- throw new CMSException("error processing attribute certs", e);
- }
- catch (IOException e)
- {
- throw new CMSException("error processing attribute certs", e);
- }
- }
-
-
- /**
- * Add a store of precalculated signers to the generator.
+ * Add a store of pre-calculated signers to the generator.
*
* @param signerStore store of signers
*/
@@ -345,6 +216,11 @@ public class CMSSignedGenerator
}
}
+ /**
+ * Add a generator for a particular signer to this CMS SignedData generator.
+ *
+ * @param infoGen the generator representing the particular signer.
+ */
public void addSignerInfoGenerator(SignerInfoGenerator infoGen)
{
signerGens.add(infoGen);
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedHelper.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedHelper.java
index ce20884..2f98e69 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedHelper.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedHelper.java
@@ -1,14 +1,8 @@
package org.bouncycastle.cms;
-import java.io.IOException;
-import java.security.Provider;
-import java.security.cert.CRLException;
-import java.security.cert.CertificateException;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -35,14 +29,8 @@ import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.util.CollectionStore;
import org.bouncycastle.util.Store;
-import org.bouncycastle.x509.NoSuchStoreException;
-import org.bouncycastle.x509.X509CollectionStoreParameters;
-import org.bouncycastle.x509.X509Store;
-import org.bouncycastle.x509.X509V2AttributeCertificate;
class CMSSignedHelper
{
@@ -125,23 +113,7 @@ class CMSSignedHelper
digestAliases.put("SHA384", new String[] { "SHA-384" });
digestAliases.put("SHA512", new String[] { "SHA-512" });
}
-
- /**
- * Return the digest algorithm using one of the standard JCA string
- * representations rather than the algorithm identifier (if possible).
- */
- String getDigestAlgName(
- String digestAlgOID)
- {
- String algName = (String)digestAlgs.get(digestAlgOID);
-
- if (algName != null)
- {
- return algName;
- }
- return digestAlgOID;
- }
/**
* Return the digest encryption algorithm using one of the standard
@@ -161,95 +133,6 @@ class CMSSignedHelper
return encryptionAlgOID;
}
- X509Store createAttributeStore(
- String type,
- Provider provider,
- Store certStore)
- throws NoSuchStoreException, CMSException
- {
- try
- {
- Collection certHldrs = certStore.getMatches(null);
- List certs = new ArrayList(certHldrs.size());
-
- for (Iterator it = certHldrs.iterator(); it.hasNext();)
- {
- certs.add(new X509V2AttributeCertificate(((X509AttributeCertificateHolder)it.next()).getEncoded()));
- }
-
- return X509Store.getInstance(
- "AttributeCertificate/" +type, new X509CollectionStoreParameters(certs), provider);
- }
- catch (IllegalArgumentException e)
- {
- throw new CMSException("can't setup the X509Store", e);
- }
- catch (IOException e)
- {
- throw new CMSException("can't setup the X509Store", e);
- }
- }
-
- X509Store createCertificateStore(
- String type,
- Provider provider,
- Store certStore)
- throws NoSuchStoreException, CMSException
- {
- try
- {
- JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(provider);
- Collection certHldrs = certStore.getMatches(null);
- List certs = new ArrayList(certHldrs.size());
-
- for (Iterator it = certHldrs.iterator(); it.hasNext();)
- {
- certs.add(converter.getCertificate((X509CertificateHolder)it.next()));
- }
-
- return X509Store.getInstance(
- "Certificate/" +type, new X509CollectionStoreParameters(certs), provider);
- }
- catch (IllegalArgumentException e)
- {
- throw new CMSException("can't setup the X509Store", e);
- }
- catch (CertificateException e)
- {
- throw new CMSException("can't setup the X509Store", e);
- }
- }
-
- X509Store createCRLsStore(
- String type,
- Provider provider,
- Store crlStore)
- throws NoSuchStoreException, CMSException
- {
- try
- {
- JcaX509CRLConverter converter = new JcaX509CRLConverter().setProvider(provider);
- Collection crlHldrs = crlStore.getMatches(null);
- List crls = new ArrayList(crlHldrs.size());
-
- for (Iterator it = crlHldrs.iterator(); it.hasNext();)
- {
- crls.add(converter.getCRL((X509CRLHolder)it.next()));
- }
-
- return X509Store.getInstance(
- "CRL/" +type, new X509CollectionStoreParameters(crls), provider);
- }
- catch (IllegalArgumentException e)
- {
- throw new CMSException("can't setup the X509Store", e);
- }
- catch (CRLException e)
- {
- throw new CMSException("can't setup the X509Store", e);
- }
- }
-
AlgorithmIdentifier fixAlgID(AlgorithmIdentifier algId)
{
if (algId.getParameters() == null)
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java
index 743ab8e..dc9c2ee 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java
@@ -3,15 +3,6 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.Security;
-import java.security.cert.CRLException;
-import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
@@ -21,7 +12,6 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.BEROctetStringGenerator;
import org.bouncycastle.asn1.BERSet;
@@ -29,13 +19,9 @@ import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat;
import org.bouncycastle.asn1.ocsp.OCSPResponse;
import org.bouncycastle.asn1.ocsp.OCSPResponseStatus;
-import org.bouncycastle.asn1.x509.Certificate;
-import org.bouncycastle.asn1.x509.CertificateList;
-import org.bouncycastle.asn1.x509.TBSCertificate;
import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509CertificateHolder;
@@ -63,36 +49,6 @@ class CMSUtils
return readContentInfo(new ASN1InputStream(input));
}
- static List getCertificatesFromStore(CertStore certStore)
- throws CertStoreException, CMSException
- {
- List certs = new ArrayList();
-
- try
- {
- for (Iterator it = certStore.getCertificates(null).iterator(); it.hasNext();)
- {
- X509Certificate c = (X509Certificate)it.next();
-
- certs.add(Certificate.getInstance(ASN1Primitive.fromByteArray(c.getEncoded())));
- }
-
- return certs;
- }
- catch (IllegalArgumentException e)
- {
- throw new CMSException("error processing certs", e);
- }
- catch (IOException e)
- {
- throw new CMSException("error processing certs", e);
- }
- catch (CertificateEncodingException e)
- {
- throw new CMSException("error encoding certs", e);
- }
- }
-
static List getCertificatesFromStore(Store certStore)
throws CMSException
{
@@ -137,35 +93,6 @@ class CMSUtils
}
}
- static List getCRLsFromStore(CertStore certStore)
- throws CertStoreException, CMSException
- {
- List crls = new ArrayList();
-
- try
- {
- for (Iterator it = certStore.getCRLs(null).iterator(); it.hasNext();)
- {
- X509CRL c = (X509CRL)it.next();
-
- crls.add(CertificateList.getInstance(ASN1Primitive.fromByteArray(c.getEncoded())));
- }
-
- return crls;
- }
- catch (IllegalArgumentException e)
- {
- throw new CMSException("error processing crls", e);
- }
- catch (IOException e)
- {
- throw new CMSException("error processing crls", e);
- }
- catch (CRLException e)
- {
- throw new CMSException("error encoding crls", e);
- }
- }
static List getCRLsFromStore(Store crlStore)
throws CMSException
@@ -250,27 +177,6 @@ class CMSUtils
return octGen.getOctetOutputStream();
}
- static TBSCertificate getTBSCertificateStructure(
- X509Certificate cert)
- {
- try
- {
- return TBSCertificate.getInstance(
- ASN1Primitive.fromByteArray(cert.getTBSCertificate()));
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException(
- "can't extract TBS structure from this cert");
- }
- }
-
- static IssuerAndSerialNumber getIssuerAndSerialNumber(X509Certificate cert)
- {
- TBSCertificate tbsCert = getTBSCertificateStructure(cert);
- return new IssuerAndSerialNumber(tbsCert.getIssuer(), tbsCert.getSerialNumber().getValue());
- }
-
private static ContentInfo readContentInfo(
ASN1InputStream in)
throws CMSException
@@ -308,24 +214,6 @@ class CMSUtils
return Streams.readAllLimited(in, limit);
}
- public static Provider getProvider(String providerName)
- throws NoSuchProviderException
- {
- if (providerName != null)
- {
- Provider prov = Security.getProvider(providerName);
-
- if (prov != null)
- {
- return prov;
- }
-
- throw new NoSuchProviderException("provider " + providerName + " not found.");
- }
-
- return null;
- }
-
static InputStream attachDigestsToInputStream(Collection digests, InputStream s)
{
InputStream result = s;
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java
index 8ba3686..837edd8 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java
@@ -1,6 +1,7 @@
package org.bouncycastle.cms;
import java.util.Date;
+import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
@@ -59,7 +60,7 @@ public class DefaultSignedAttributeTableGenerator
protected Hashtable createStandardAttributeTable(
Map parameters)
{
- Hashtable std = (Hashtable)table.clone();
+ Hashtable std = copyHashTable(table);
if (!std.containsKey(CMSAttributes.contentType))
{
@@ -103,4 +104,18 @@ public class DefaultSignedAttributeTableGenerator
{
return new AttributeTable(createStandardAttributeTable(parameters));
}
+
+ private static Hashtable copyHashTable(Hashtable paramsMap)
+ {
+ Hashtable newTable = new Hashtable();
+
+ Enumeration keys = paramsMap.keys();
+ while (keys.hasMoreElements())
+ {
+ Object key = keys.nextElement();
+ newTable.put(key, paramsMap.get(key));
+ }
+
+ return newTable;
+ }
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/KEKRecipientInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/KEKRecipientInformation.java
index 4e1b8cd..62c6529 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/KEKRecipientInformation.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/KEKRecipientInformation.java
@@ -1,18 +1,10 @@
package org.bouncycastle.cms;
import java.io.IOException;
-import java.security.Key;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-
-import javax.crypto.SecretKey;
import org.bouncycastle.asn1.cms.KEKIdentifier;
import org.bouncycastle.asn1.cms.KEKRecipientInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceKEKAuthenticatedRecipient;
-import org.bouncycastle.cms.jcajce.JceKEKEnvelopedRecipient;
-import org.bouncycastle.cms.jcajce.JceKEKRecipient;
/**
* the RecipientInfo class for a recipient who has been sent a message
@@ -38,52 +30,6 @@ public class KEKRecipientInformation
this.rid = new KEKRecipientId(kekId.getKeyIdentifier().getOctets());
}
- /**
- * decrypt the content and return an input stream.
- */
- public CMSTypedStream getContentStream(
- Key key,
- String prov)
- throws CMSException, NoSuchProviderException
- {
- return getContentStream(key, CMSUtils.getProvider(prov));
- }
-
- /**
- * decrypt the content and return an input stream.
- * @deprecated use getContentStream(Recipient)
- */
- public CMSTypedStream getContentStream(
- Key key,
- Provider prov)
- throws CMSException
- {
- try
- {
- JceKEKRecipient recipient;
-
- if (secureReadable instanceof CMSEnvelopedHelper.CMSEnvelopedSecureReadable)
- {
- recipient = new JceKEKEnvelopedRecipient((SecretKey)key);
- }
- else
- {
- recipient = new JceKEKAuthenticatedRecipient((SecretKey)key);
- }
-
- if (prov != null)
- {
- recipient.setProvider(prov);
- }
-
- return getContentStream(recipient);
- }
- catch (IOException e)
- {
- throw new CMSException("encoding error: " + e.getMessage(), e);
- }
- }
-
protected RecipientOperator getRecipientOperator(Recipient recipient)
throws CMSException, IOException
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInformation.java
index 51917da..16c26bd 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInformation.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/KeyAgreeRecipientInformation.java
@@ -1,10 +1,6 @@
package org.bouncycastle.cms;
import java.io.IOException;
-import java.security.Key;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.Provider;
import java.util.List;
import org.bouncycastle.asn1.ASN1OctetString;
@@ -19,9 +15,6 @@ import org.bouncycastle.asn1.cms.RecipientKeyIdentifier;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.cms.jcajce.JceKeyAgreeAuthenticatedRecipient;
-import org.bouncycastle.cms.jcajce.JceKeyAgreeEnvelopedRecipient;
-import org.bouncycastle.cms.jcajce.JceKeyAgreeRecipient;
/**
* the RecipientInfo class for a recipient who has been sent a message
@@ -126,57 +119,6 @@ public class KeyAgreeRecipientInformation
throw new CMSException("No support for 'originator' as IssuerAndSerialNumber or SubjectKeyIdentifier");
}
- /**
- * decrypt the content and return it
- * @deprecated use getContentStream(Recipient) method
- */
- public CMSTypedStream getContentStream(
- Key key,
- String prov)
- throws CMSException, NoSuchProviderException
- {
- return getContentStream(key, CMSUtils.getProvider(prov));
- }
-
- /**
- * decrypt the content and return it
- * @deprecated use getContentStream(Recipient) method
- */
- public CMSTypedStream getContentStream(
- Key key,
- Provider prov)
- throws CMSException
- {
- try
- {
- JceKeyAgreeRecipient recipient;
-
- if (secureReadable instanceof CMSEnvelopedHelper.CMSEnvelopedSecureReadable)
- {
- recipient = new JceKeyAgreeEnvelopedRecipient((PrivateKey)key);
- }
- else
- {
- recipient = new JceKeyAgreeAuthenticatedRecipient((PrivateKey)key);
- }
-
- if (prov != null)
- {
- recipient.setProvider(prov);
- if (prov.getName().equalsIgnoreCase("SunJCE"))
- {
- recipient.setContentProvider((String)null); // need to fall back to generic search
- }
- }
-
- return getContentStream(recipient);
- }
- catch (IOException e)
- {
- throw new CMSException("encoding error: " + e.getMessage(), e);
- }
- }
-
protected RecipientOperator getRecipientOperator(Recipient recipient)
throws CMSException, IOException
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/KeyTransRecipientInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/KeyTransRecipientInformation.java
index a1180b4..d59f4b3 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/KeyTransRecipientInformation.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/KeyTransRecipientInformation.java
@@ -1,20 +1,10 @@
package org.bouncycastle.cms;
-import java.io.IOException;
-import java.security.Key;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.Provider;
-
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
import org.bouncycastle.asn1.cms.KeyTransRecipientInfo;
import org.bouncycastle.asn1.cms.RecipientIdentifier;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceKeyTransAuthenticatedRecipient;
-import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
-import org.bouncycastle.cms.jcajce.JceKeyTransRecipient;
-
/**
* the KeyTransRecipientInformation class for a recipient who has been sent a secret
@@ -52,57 +42,6 @@ public class KeyTransRecipientInformation
}
}
- /**
- * decrypt the content and return it
- * @deprecated use getContentStream(Recipient) method
- */
- public CMSTypedStream getContentStream(
- Key key,
- String prov)
- throws CMSException, NoSuchProviderException
- {
- return getContentStream(key, CMSUtils.getProvider(prov));
- }
-
- /**
- * decrypt the content and return it
- * @deprecated use getContentStream(Recipient) method
- */
- public CMSTypedStream getContentStream(
- Key key,
- Provider prov)
- throws CMSException
- {
- try
- {
- JceKeyTransRecipient recipient;
-
- if (secureReadable instanceof CMSEnvelopedHelper.CMSEnvelopedSecureReadable)
- {
- recipient = new JceKeyTransEnvelopedRecipient((PrivateKey)key);
- }
- else
- {
- recipient = new JceKeyTransAuthenticatedRecipient((PrivateKey)key);
- }
-
- if (prov != null)
- {
- recipient.setProvider(prov);
- if (prov.getName().equalsIgnoreCase("SunJCE"))
- {
- recipient.setContentProvider((String)null); // need to fall back to generic search
- }
- }
-
- return getContentStream(recipient);
- }
- catch (IOException e)
- {
- throw new CMSException("encoding error: " + e.getMessage(), e);
- }
- }
-
protected RecipientOperator getRecipientOperator(Recipient recipient)
throws CMSException
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PKCS5Scheme2PBEKey.java b/bcpkix/src/main/java/org/bouncycastle/cms/PKCS5Scheme2PBEKey.java
deleted file mode 100644
index b5be483..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/PKCS5Scheme2PBEKey.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.cms;
-
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-/**
- * PKCS5 scheme-2 - password converted to bytes assuming ASCII.
- */
-public class PKCS5Scheme2PBEKey
- extends CMSPBEKey
-{
- public PKCS5Scheme2PBEKey(char[] password, byte[] salt, int iterationCount)
- {
- super(password, salt, iterationCount);
- }
-
- public PKCS5Scheme2PBEKey(char[] password, AlgorithmParameters pbeParams)
- throws InvalidAlgorithmParameterException
- {
- super(password, getParamSpec(pbeParams));
- }
-
- byte[] getEncoded(String algorithmOid)
- {
- PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator();
-
- gen.init(PBEParametersGenerator.PKCS5PasswordToBytes(this.getPassword()), this.getSalt(), this.getIterationCount());
-
- return ((KeyParameter)gen.generateDerivedParameters(CMSEnvelopedHelper.INSTANCE.getKeySize(algorithmOid))).getKey();
- }
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PKCS5Scheme2UTF8PBEKey.java b/bcpkix/src/main/java/org/bouncycastle/cms/PKCS5Scheme2UTF8PBEKey.java
deleted file mode 100644
index 436ba66..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/PKCS5Scheme2UTF8PBEKey.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.cms;
-
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-/**
- * PKCS5 scheme-2 - password converted to bytes using UTF-8.
- */
-public class PKCS5Scheme2UTF8PBEKey
- extends CMSPBEKey
-{
- public PKCS5Scheme2UTF8PBEKey(char[] password, byte[] salt, int iterationCount)
- {
- super(password, salt, iterationCount);
- }
-
- public PKCS5Scheme2UTF8PBEKey(char[] password, AlgorithmParameters pbeParams)
- throws InvalidAlgorithmParameterException
- {
- super(password, getParamSpec(pbeParams));
- }
-
- byte[] getEncoded(String algorithmOid)
- {
- PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator();
-
- gen.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(this.getPassword()), this.getSalt(), this.getIterationCount());
-
- return ((KeyParameter)gen.generateDerivedParameters(CMSEnvelopedHelper.INSTANCE.getKeySize(algorithmOid))).getKey();
- }
-} \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java
index 4517ad6..d7639e9 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipientInformation.java
@@ -1,10 +1,6 @@
package org.bouncycastle.cms;
import java.io.IOException;
-import java.security.AlgorithmParameters;
-import java.security.Key;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
import java.util.HashMap;
import java.util.Map;
@@ -12,10 +8,6 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.cms.PasswordRecipientInfo;
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceAlgorithmIdentifierConverter;
-import org.bouncycastle.cms.jcajce.JcePasswordAuthenticatedRecipient;
-import org.bouncycastle.cms.jcajce.JcePasswordEnvelopedRecipient;
-import org.bouncycastle.cms.jcajce.JcePasswordRecipient;
import org.bouncycastle.crypto.PBEParametersGenerator;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
@@ -110,88 +102,6 @@ public class PasswordRecipientInformation
return info.getKeyDerivationAlgorithm();
}
- /**
- * return an AlgorithmParameters object representing the parameters to the
- * key derivation algorithm to the recipient.
- *
- * @return AlgorithmParameters object, null if there aren't any.
- * @deprecated use getKeyDerivationAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getKeyDerivationAlgParameters(String provider)
- throws NoSuchProviderException
- {
- return getKeyDerivationAlgParameters(CMSUtils.getProvider(provider));
- }
-
- /**
- * return an AlgorithmParameters object representing the parameters to the
- * key derivation algorithm to the recipient.
- *
- * @return AlgorithmParameters object, null if there aren't any.
- * @deprecated use getKeyDerivationAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getKeyDerivationAlgParameters(Provider provider)
- {
- try
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(info.getKeyDerivationAlgorithm());
- }
- catch (Exception e)
- {
- throw new RuntimeException("exception getting encryption parameters " + e);
- }
- }
-
- /**
- * decrypt the content and return an input stream.
- * @deprecated use getContentStream(Recipient)
- */
- public CMSTypedStream getContentStream(
- Key key,
- String prov)
- throws CMSException, NoSuchProviderException
- {
- return getContentStream(key, CMSUtils.getProvider(prov));
- }
-
- /**
- * decrypt the content and return an input stream.
- * @deprecated use getContentStream(Recipient)
- */
- public CMSTypedStream getContentStream(
- Key key,
- Provider prov)
- throws CMSException
- {
- try
- {
- CMSPBEKey pbeKey = (CMSPBEKey)key;
- JcePasswordRecipient recipient;
-
- if (secureReadable instanceof CMSEnvelopedHelper.CMSEnvelopedSecureReadable)
- {
- recipient = new JcePasswordEnvelopedRecipient(pbeKey.getPassword());
- }
- else
- {
- recipient = new JcePasswordAuthenticatedRecipient(pbeKey.getPassword());
- }
-
- recipient.setPasswordConversionScheme((pbeKey instanceof PKCS5Scheme2UTF8PBEKey) ? PasswordRecipient.PKCS5_SCHEME2_UTF8 : PasswordRecipient.PKCS5_SCHEME2);
-
- if (prov != null)
- {
- recipient.setProvider(prov);
- }
-
- return getContentStream(recipient);
- }
- catch (IOException e)
- {
- throw new CMSException("encoding error: " + e.getMessage(), e);
- }
- }
-
protected RecipientOperator getRecipientOperator(Recipient recipient)
throws CMSException, IOException
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/RecipientInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/RecipientInformation.java
index 5129881..86f9fa3 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/RecipientInformation.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/RecipientInformation.java
@@ -2,15 +2,10 @@ package org.bouncycastle.cms;
import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.security.AlgorithmParameters;
-import java.security.Key;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.jcajce.JceAlgorithmIdentifierConverter;
import org.bouncycastle.util.io.Streams;
public abstract class RecipientInformation
@@ -71,7 +66,7 @@ public abstract class RecipientInformation
*/
public String getKeyEncryptionAlgOID()
{
- return keyEncAlg.getObjectId().getId();
+ return keyEncAlg.getAlgorithm().getId();
}
/**
@@ -93,68 +88,6 @@ public abstract class RecipientInformation
}
/**
- * Return an AlgorithmParameters object giving the encryption parameters
- * used to encrypt the key this recipient holds.
- *
- * @param provider the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @throws NoSuchProviderException if the provider cannot be found.
- * @deprecated use getKeyEncryptionAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getKeyEncryptionAlgorithmParameters(
- String provider)
- throws CMSException, NoSuchProviderException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(keyEncAlg);
- }
-
- /**
- * Return an AlgorithmParameters object giving the encryption parameters
- * used to encrypt the key this recipient holds.
- *
- * @param provider the provider to generate the parameters for.
- * @return the parameters object, null if there is not one.
- * @throws CMSException if the algorithm cannot be found, or the parameters can't be parsed.
- * @deprecated use getKeyEncryptionAlgorithm and JceAlgorithmIdentifierConverter().
- */
- public AlgorithmParameters getKeyEncryptionAlgorithmParameters(
- Provider provider)
- throws CMSException
- {
- return new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(keyEncAlg);
- }
-
- /**
- * @deprecated use getContent(Recipient)
- */
- public byte[] getContent(
- Key key,
- String provider)
- throws CMSException, NoSuchProviderException
- {
- return getContent(key, CMSUtils.getProvider(provider));
- }
-
- /**
- * @deprecated use getContent(Recipient)
- */
- public byte[] getContent(
- Key key,
- Provider provider)
- throws CMSException
- {
- try
- {
- return CMSUtils.streamToByteArray(getContentStream(key, provider).getContentStream());
- }
- catch (IOException e)
- {
- throw new RuntimeException("unable to parse internal stream: " + e);
- }
- }
-
- /**
* Return the content digest calculated during the read of the content if one has been generated. This will
* only happen if we are dealing with authenticated data and authenticated attributes are present.
*
@@ -223,24 +156,6 @@ public abstract class RecipientInformation
}
/**
- * decrypt the content and return it
- * @deprecated use getContentStream(Recipient) method
- */
- public CMSTypedStream getContentStream(Key key, String provider)
- throws CMSException, NoSuchProviderException
- {
- return getContentStream(key, CMSUtils.getProvider(provider));
- }
-
- /**
- * decrypt the content and return it
- * @deprecated use getContentStream(Recipient) method
- */
- public abstract CMSTypedStream getContentStream(Key key, Provider provider)
- throws CMSException;
-
-
- /**
* Return a CMSTypedStream representing the content in the EnvelopedData after recovering the content
* encryption/MAC key using the passed in Recipient.
*
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java
index e378629..f264729 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGenerator.java
@@ -7,7 +7,6 @@ import java.util.HashMap;
import java.util.Map;
import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DEROctetString;
@@ -23,6 +22,7 @@ import org.bouncycastle.operator.DigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.io.TeeOutputStream;
public class SignerInfoGenerator
@@ -126,9 +126,9 @@ public class SignerInfoGenerator
return signerIdentifier;
}
- public ASN1Integer getGeneratedVersion()
+ public int getGeneratedVersion()
{
- return new ASN1Integer(signerIdentifier.isTagged() ? 3 : 1);
+ return signerIdentifier.isTagged() ? 3 : 1;
}
public boolean hasAssociatedCertificate()
@@ -221,7 +221,7 @@ public class SignerInfoGenerator
if (unsAttrGen != null)
{
Map parameters = getBaseParameters(contentType, digestAlg, calculatedDigest);
- parameters.put(CMSAttributeTableGenerator.SIGNATURE, sigBytes.clone());
+ parameters.put(CMSAttributeTableGenerator.SIGNATURE, Arrays.clone(sigBytes));
AttributeTable unsigned = unsAttrGen.getAttributes(Collections.unmodifiableMap(parameters));
@@ -265,7 +265,7 @@ public class SignerInfoGenerator
}
param.put(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER, digAlgId);
- param.put(CMSAttributeTableGenerator.DIGEST, hash.clone());
+ param.put(CMSAttributeTableGenerator.DIGEST, Arrays.clone(hash));
return param;
}
@@ -273,7 +273,7 @@ public class SignerInfoGenerator
{
if (calculatedDigest != null)
{
- return (byte[])calculatedDigest.clone();
+ return Arrays.clone(calculatedDigest);
}
return null;
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java
index bd9703a..7e178d6 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java
@@ -2,13 +2,6 @@ package org.bouncycastle.cms;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.PublicKey;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
@@ -33,13 +26,10 @@ import org.bouncycastle.asn1.cms.Time;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DigestInfo;
import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.cms.jcajce.JcaSignerInfoVerifierBuilder;
-import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.operator.ContentVerifier;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.RawContentVerifier;
-import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.io.TeeOutputStream;
@@ -172,7 +162,7 @@ public class SignerInformation
throw new IllegalStateException("method can only be called after verify.");
}
- return (byte[])resultDigest.clone();
+ return Arrays.clone(resultDigest);
}
/**
@@ -232,7 +222,7 @@ public class SignerInformation
*/
public byte[] getSignature()
{
- return (byte[])signature.clone();
+ return Arrays.clone(signature);
}
/**
@@ -318,42 +308,6 @@ public class SignerInformation
return null;
}
- /**
- * @deprecated
- */
- private boolean doVerify(
- PublicKey key,
- Provider sigProvider)
- throws CMSException, NoSuchAlgorithmException
- {
- try
- {
- SignerInformationVerifier verifier;
-
- if (sigProvider != null)
- {
- if (!sigProvider.getName().equalsIgnoreCase("BC"))
- {
- verifier = new JcaSignerInfoVerifierBuilder(new JcaDigestCalculatorProviderBuilder().build()).setProvider(sigProvider).build(key);
- }
- else
- {
- verifier = new JcaSimpleSignerInfoVerifierBuilder().setProvider(sigProvider).build(key);
- }
- }
- else
- {
- verifier = new JcaSimpleSignerInfoVerifierBuilder().build(key);
- }
-
- return doVerify(verifier);
- }
- catch (OperatorCreationException e)
- {
- throw new CMSException("unable to create verifier: " + e.getMessage(), e);
- }
- }
-
private boolean doVerify(
SignerInformationVerifier verifier)
throws CMSException
@@ -555,75 +509,6 @@ public class SignerInformation
}
/**
- * verify that the given public key successfully handles and confirms the
- * signature associated with this signer.
- * @deprecated use verify(ContentVerifierProvider)
- */
- public boolean verify(
- PublicKey key,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return verify(key, CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * verify that the given public key successfully handles and confirms the
- * signature associated with this signer
- * @deprecated use verify(ContentVerifierProvider)
- */
- public boolean verify(
- PublicKey key,
- Provider sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- // Optional, but still need to validate if present
- getSigningTime();
-
- return doVerify(key, sigProvider);
- }
-
- /**
- * verify that the given certificate successfully handles and confirms
- * the signature associated with this signer and, if a signingTime
- * attribute is available, that the certificate was valid at the time the
- * signature was generated.
- * @deprecated use verify(ContentVerifierProvider)
- */
- public boolean verify(
- X509Certificate cert,
- String sigProvider)
- throws NoSuchAlgorithmException, NoSuchProviderException,
- CertificateExpiredException, CertificateNotYetValidException,
- CMSException
- {
- return verify(cert, CMSUtils.getProvider(sigProvider));
- }
-
- /**
- * verify that the given certificate successfully handles and confirms
- * the signature associated with this signer and, if a signingTime
- * attribute is available, that the certificate was valid at the time the
- * signature was generated.
- * @deprecated use verify(ContentVerifierProvider)
- */
- public boolean verify(
- X509Certificate cert,
- Provider sigProvider)
- throws NoSuchAlgorithmException,
- CertificateExpiredException, CertificateNotYetValidException,
- CMSException
- {
- Time signingTime = getSigningTime();
- if (signingTime != null)
- {
- cert.checkValidity(signingTime.getDate());
- }
-
- return doVerify(cert.getPublicKey(), sigProvider);
- }
-
- /**
* Verify that the given verifier can successfully verify the signature on
* this SignerInformation object.
*
@@ -654,17 +539,6 @@ public class SignerInformation
}
/**
- * Return the base ASN.1 CMS structure that this object contains.
- *
- * @return an object containing a CMS SignerInfo structure.
- * @deprecated use toASN1Structure()
- */
- public SignerInfo toSignerInfo()
- {
- return info;
- }
-
- /**
* Return the underlying ASN.1 object defining this SignerInformation object.
*
* @return a SignerInfo.
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/CMSUtils.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/CMSUtils.java
index bd36b73..104b16f 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/CMSUtils.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/CMSUtils.java
@@ -1,14 +1,19 @@
package org.bouncycastle.cms.jcajce;
+import java.io.IOException;
+import java.security.AlgorithmParameters;
import java.security.Provider;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
+import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
import org.bouncycastle.asn1.x509.Certificate;
+import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.TBSCertificateStructure;
-import org.bouncycastle.asn1.x509.X509Extension;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.jcajce.JcaJceUtils;
class CMSUtils
{
@@ -30,7 +35,7 @@ class CMSUtils
static byte[] getSubjectKeyId(X509Certificate cert)
{
- byte[] ext = cert.getExtensionValue(X509Extension.subjectKeyIdentifier.getId());
+ byte[] ext = cert.getExtensionValue(Extension.subjectKeyIdentifier.getId());
if (ext != null)
{
@@ -66,4 +71,29 @@ class CMSUtils
}
}
+ static ASN1Encodable extractParameters(AlgorithmParameters params)
+ throws CMSException
+ {
+ try
+ {
+ return JcaJceUtils.extractParameters(params);
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("cannot extract parameters: " + e.getMessage(), e);
+ }
+ }
+
+ static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams)
+ throws CMSException
+ {
+ try
+ {
+ JcaJceUtils.loadParameters(params, sParams);
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("error encoding algorithm parameters.", e);
+ }
+ }
} \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java
index 5f3958f..b081051 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java
@@ -1,6 +1,5 @@
package org.bouncycastle.cms.jcajce;
-import java.io.IOException;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
@@ -32,7 +31,6 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Null;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
@@ -41,12 +39,16 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.cms.CMSAlgorithm;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.operator.DefaultSecretKeySizeProvider;
import org.bouncycastle.operator.GenericKey;
+import org.bouncycastle.operator.SecretKeySizeProvider;
import org.bouncycastle.operator.SymmetricKeyUnwrapper;
import org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper;
-class EnvelopedDataHelper
+public class EnvelopedDataHelper
{
+ protected static final SecretKeySizeProvider KEY_SIZE_PROVIDER = DefaultSecretKeySizeProvider.INSTANCE;
+
protected static final Map BASE_CIPHER_NAMES = new HashMap();
protected static final Map CIPHER_ALG_NAMES = new HashMap();
protected static final Map MAC_ALG_NAMES = new HashMap();
@@ -64,8 +66,10 @@ class EnvelopedDataHelper
BASE_CIPHER_NAMES.put(CMSAlgorithm.CAMELLIA192_CBC, "Camellia");
BASE_CIPHER_NAMES.put(CMSAlgorithm.CAMELLIA256_CBC, "Camellia");
BASE_CIPHER_NAMES.put(CMSAlgorithm.SEED_CBC, "SEED");
+ BASE_CIPHER_NAMES.put(PKCSObjectIdentifiers.rc4, "RC4");
CIPHER_ALG_NAMES.put(CMSAlgorithm.DES_CBC, "DES/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.RC2_CBC, "RC2/CBC/PKCS5Padding");
CIPHER_ALG_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDE/CBC/PKCS5Padding");
CIPHER_ALG_NAMES.put(CMSAlgorithm.AES128_CBC, "AES/CBC/PKCS5Padding");
CIPHER_ALG_NAMES.put(CMSAlgorithm.AES192_CBC, "AES/CBC/PKCS5Padding");
@@ -76,6 +80,7 @@ class EnvelopedDataHelper
CIPHER_ALG_NAMES.put(CMSAlgorithm.CAMELLIA192_CBC, "Camellia/CBC/PKCS5Padding");
CIPHER_ALG_NAMES.put(CMSAlgorithm.CAMELLIA256_CBC, "Camellia/CBC/PKCS5Padding");
CIPHER_ALG_NAMES.put(CMSAlgorithm.SEED_CBC, "SEED/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(PKCSObjectIdentifiers.rc4, "RC4");
MAC_ALG_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDEMac");
MAC_ALG_NAMES.put(CMSAlgorithm.AES128_CBC, "AESMac");
@@ -156,7 +161,7 @@ class EnvelopedDataHelper
throw new IllegalArgumentException("unknown generic key type");
}
- Key getJceKey(ASN1ObjectIdentifier algorithm, GenericKey key)
+ public Key getJceKey(ASN1ObjectIdentifier algorithm, GenericKey key)
{
if (key.getRepresentation() instanceof Key)
{
@@ -171,6 +176,33 @@ class EnvelopedDataHelper
throw new IllegalArgumentException("unknown generic key type");
}
+ public void keySizeCheck(AlgorithmIdentifier keyAlgorithm, Key key)
+ throws CMSException
+ {
+ int expectedKeySize = EnvelopedDataHelper.KEY_SIZE_PROVIDER.getKeySize(keyAlgorithm);
+ if (expectedKeySize > 0)
+ {
+ byte[] keyEnc = null;
+
+ try
+ {
+ keyEnc = key.getEncoded();
+ }
+ catch (Exception e)
+ {
+ // ignore - we're using a HSM...
+ }
+
+ if (keyEnc != null)
+ {
+ if (keyEnc.length * 8 != expectedKeySize)
+ {
+ throw new CMSException("Expected key size for algorithm OID not found in recipient.");
+ }
+ }
+ }
+ }
+
Cipher createCipher(ASN1ObjectIdentifier algorithm)
throws CMSException
{
@@ -294,7 +326,7 @@ class EnvelopedDataHelper
return helper.createAlgorithmParameterGenerator(algorithm.getId());
}
- Cipher createContentCipher(final Key sKey, final AlgorithmIdentifier encryptionAlgID)
+ public Cipher createContentCipher(final Key sKey, final AlgorithmIdentifier encryptionAlgID)
throws CMSException
{
return (Cipher)execute(new JCECallback()
@@ -314,14 +346,7 @@ class EnvelopedDataHelper
{
AlgorithmParameters params = createAlgorithmParameters(encryptionAlgID.getAlgorithm());
- try
- {
- params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1");
- }
- catch (IOException e)
- {
- throw new CMSException("error decoding algorithm parameters.", e);
- }
+ CMSUtils.loadParameters(params, sParams);
cipher.init(Cipher.DECRYPT_MODE, sKey, params);
}
@@ -383,14 +408,7 @@ class EnvelopedDataHelper
{
AlgorithmParameters params = createAlgorithmParameters(macAlgId.getAlgorithm());
- try
- {
- params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1");
- }
- catch (IOException e)
- {
- throw new CMSException("error decoding algorithm parameters.", e);
- }
+ CMSUtils.loadParameters(params, sParams);
mac.init(sKey, params.getParameterSpec(IvParameterSpec.class));
}
@@ -491,7 +509,7 @@ class EnvelopedDataHelper
{
AlgorithmParameterGenerator pGen = createAlgorithmParameterGenerator(encryptionOID);
- if (encryptionOID.equals(CMSEnvelopedDataGenerator.RC2_CBC))
+ if (encryptionOID.equals(CMSAlgorithm.RC2_CBC))
{
byte[] iv = new byte[8];
@@ -525,14 +543,7 @@ class EnvelopedDataHelper
ASN1Encodable asn1Params;
if (params != null)
{
- try
- {
- asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
- }
- catch (IOException e)
- {
- throw new CMSException("cannot encode parameters: " + e.getMessage(), e);
- }
+ asn1Params = CMSUtils.extractParameters(params);
}
else
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceAlgorithmIdentifierConverter.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceAlgorithmIdentifierConverter.java
index bb9e064..59928f4 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceAlgorithmIdentifierConverter.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceAlgorithmIdentifierConverter.java
@@ -1,7 +1,6 @@
package org.bouncycastle.cms.jcajce;
-import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@@ -49,7 +48,7 @@ public class JceAlgorithmIdentifierConverter
{
AlgorithmParameters params = helper.createAlgorithmParameters(algorithmIdentifier.getAlgorithm());
- params.init(parameters.toASN1Primitive().getEncoded(), "ASN.1");
+ CMSUtils.loadParameters(params, algorithmIdentifier.getParameters());
return params;
}
@@ -57,10 +56,6 @@ public class JceAlgorithmIdentifierConverter
{
throw new CMSException("can't find parameters for algorithm", e);
}
- catch (IOException e)
- {
- throw new CMSException("can't parse parameters", e);
- }
catch (NoSuchProviderException e)
{
throw new CMSException("can't find provider for algorithm", e);
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java
index 89d2c65..93d8b72 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java
@@ -5,8 +5,6 @@ import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.SecureRandom;
-import java.util.HashMap;
-import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
@@ -14,40 +12,19 @@ import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cms.CMSAlgorithm;
import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.operator.DefaultSecretKeySizeProvider;
import org.bouncycastle.operator.GenericKey;
import org.bouncycastle.operator.OutputEncryptor;
+import org.bouncycastle.operator.SecretKeySizeProvider;
import org.bouncycastle.operator.jcajce.JceGenericKey;
-import org.bouncycastle.util.Integers;
public class JceCMSContentEncryptorBuilder
{
- private static Map keySizes = new HashMap();
+ private static final SecretKeySizeProvider KEY_SIZE_PROVIDER = DefaultSecretKeySizeProvider.INSTANCE;
- static
- {
- keySizes.put(CMSAlgorithm.AES128_CBC, Integers.valueOf(128));
- keySizes.put(CMSAlgorithm.AES192_CBC, Integers.valueOf(192));
- keySizes.put(CMSAlgorithm.AES256_CBC, Integers.valueOf(256));
-
- keySizes.put(CMSAlgorithm.CAMELLIA128_CBC, Integers.valueOf(128));
- keySizes.put(CMSAlgorithm.CAMELLIA192_CBC, Integers.valueOf(192));
- keySizes.put(CMSAlgorithm.CAMELLIA256_CBC, Integers.valueOf(256));
- }
-
- private static int getKeySize(ASN1ObjectIdentifier oid)
- {
- Integer size = (Integer)keySizes.get(oid);
-
- if (size != null)
- {
- return size.intValue();
- }
-
- return -1;
- }
private final ASN1ObjectIdentifier encryptionOID;
private final int keySize;
@@ -57,13 +34,30 @@ public class JceCMSContentEncryptorBuilder
public JceCMSContentEncryptorBuilder(ASN1ObjectIdentifier encryptionOID)
{
- this(encryptionOID, getKeySize(encryptionOID));
+ this(encryptionOID, KEY_SIZE_PROVIDER.getKeySize(encryptionOID));
}
public JceCMSContentEncryptorBuilder(ASN1ObjectIdentifier encryptionOID, int keySize)
{
this.encryptionOID = encryptionOID;
this.keySize = keySize;
+
+ int fixedSize = KEY_SIZE_PROVIDER.getKeySize(encryptionOID);
+
+ if (encryptionOID.equals(PKCSObjectIdentifiers.des_EDE3_CBC))
+ {
+ if (keySize != 168 && keySize != fixedSize)
+ {
+ throw new IllegalArgumentException("incorrect keySize for encryptionOID passed to builder.");
+ }
+ }
+ else
+ {
+ if (fixedSize > 0 && fixedSize != keySize)
+ {
+ throw new IllegalArgumentException("incorrect keySize for encryptionOID passed to builder.");
+ }
+ }
}
public JceCMSContentEncryptorBuilder setProvider(Provider provider)
@@ -116,6 +110,10 @@ public class JceCMSContentEncryptorBuilder
}
else
{
+ if (encryptionOID.equals(PKCSObjectIdentifiers.des_EDE3_CBC) && keySize == 192)
+ {
+ keySize = 168;
+ }
keyGen.init(keySize, random);
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java
index a01e279..d0e4164 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKEKRecipient.java
@@ -18,6 +18,7 @@ public abstract class JceKEKRecipient
protected EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper());
protected EnvelopedDataHelper contentHelper = helper;
+ protected boolean validateKeySize = false;
public JceKEKRecipient(SecretKey recipientKey)
{
@@ -78,14 +79,37 @@ public abstract class JceKEKRecipient
return this;
}
- protected Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey)
+ /**
+ * Set validation of retrieved key sizes against the algorithm parameters for the encrypted key where possible - default is off.
+ * <p>
+ * This setting will not have any affect if the encryption algorithm in the recipient does not specify a particular key size, or
+ * if the unwrapper is a HSM and the byte encoding of the unwrapped secret key is not available.
+ * </p>
+ * @param doValidate true if unwrapped key's should be validated against the content encryption algorithm, false otherwise.
+ * @return this recipient.
+ */
+ public JceKEKRecipient setKeySizeValidation(boolean doValidate)
+ {
+ this.validateKeySize = doValidate;
+
+ return this;
+ }
+
+ protected Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier encryptedKeyAlgorithm, byte[] encryptedContentEncryptionKey)
throws CMSException
{
SymmetricKeyUnwrapper unwrapper = helper.createSymmetricUnwrapper(keyEncryptionAlgorithm, recipientKey);
try
{
- return helper.getJceKey(contentEncryptionAlgorithm.getAlgorithm(), unwrapper.generateUnwrappedKey(contentEncryptionAlgorithm, encryptedContentEncryptionKey));
+ Key key = helper.getJceKey(encryptedKeyAlgorithm.getAlgorithm(), unwrapper.generateUnwrappedKey(encryptedKeyAlgorithm, encryptedContentEncryptionKey));
+
+ if (validateKeySize)
+ {
+ helper.keySizeCheck(encryptedKeyAlgorithm, key);
+ }
+
+ return key;
}
catch (OperatorException e)
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java
index 788af8d..a457ede 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipient.java
@@ -22,6 +22,7 @@ public abstract class JceKeyTransRecipient
protected EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper());
protected EnvelopedDataHelper contentHelper = helper;
protected Map extraMappings = new HashMap();
+ protected boolean validateKeySize = false;
public JceKeyTransRecipient(PrivateKey recipientKey)
{
@@ -105,6 +106,22 @@ public abstract class JceKeyTransRecipient
return this;
}
+ /**
+ * Set validation of retrieved key sizes against the algorithm parameters for the encrypted key where possible - default is off.
+ * <p>
+ * This setting will not have any affect if the encryption algorithm in the recipient does not specify a particular key size, or
+ * if the unwrapper is a HSM and the byte encoding of the unwrapped secret key is not available.
+ * </p>
+ * @param doValidate true if unwrapped key's should be validated against the content encryption algorithm, false otherwise.
+ * @return this recipient.
+ */
+ public JceKeyTransRecipient setKeySizeValidation(boolean doValidate)
+ {
+ this.validateKeySize = doValidate;
+
+ return this;
+ }
+
protected Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier encryptedKeyAlgorithm, byte[] encryptedEncryptionKey)
throws CMSException
{
@@ -122,7 +139,14 @@ public abstract class JceKeyTransRecipient
try
{
- return helper.getJceKey(encryptedKeyAlgorithm.getAlgorithm(), unwrapper.generateUnwrappedKey(encryptedKeyAlgorithm, encryptedEncryptionKey));
+ Key key = helper.getJceKey(encryptedKeyAlgorithm.getAlgorithm(), unwrapper.generateUnwrappedKey(encryptedKeyAlgorithm, encryptedEncryptionKey));
+
+ if (validateKeySize)
+ {
+ helper.keySizeCheck(encryptedKeyAlgorithm, key);
+ }
+
+ return key;
}
catch (OperatorException e)
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipientInfoGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipientInfoGenerator.java
index 73733c7..60a2ff2 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipientInfoGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JceKeyTransRecipientInfoGenerator.java
@@ -7,6 +7,7 @@ import java.security.cert.X509Certificate;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cms.KeyTransRecipientInfoGenerator;
import org.bouncycastle.operator.jcajce.JceAsymmetricKeyWrapper;
@@ -17,7 +18,7 @@ public class JceKeyTransRecipientInfoGenerator
public JceKeyTransRecipientInfoGenerator(X509Certificate recipientCert)
throws CertificateEncodingException
{
- super(new IssuerAndSerialNumber(new JcaX509CertificateHolder(recipientCert).toASN1Structure()), new JceAsymmetricKeyWrapper(recipientCert.getPublicKey()));
+ super(new IssuerAndSerialNumber(new JcaX509CertificateHolder(recipientCert).toASN1Structure()), new JceAsymmetricKeyWrapper(recipientCert));
}
public JceKeyTransRecipientInfoGenerator(byte[] subjectKeyIdentifier, PublicKey publicKey)
@@ -25,6 +26,30 @@ public class JceKeyTransRecipientInfoGenerator
super(subjectKeyIdentifier, new JceAsymmetricKeyWrapper(publicKey));
}
+ /**
+ * Create a generator overriding the algorithm type implied by the public key in the certificate passed in.
+ *
+ * @param recipientCert certificate carrying the public key.
+ * @param algorithmIdentifier the identifier and parameters for the encryption algorithm to be used.
+ */
+ public JceKeyTransRecipientInfoGenerator(X509Certificate recipientCert, AlgorithmIdentifier algorithmIdentifier)
+ throws CertificateEncodingException
+ {
+ super(new IssuerAndSerialNumber(new JcaX509CertificateHolder(recipientCert).toASN1Structure()), new JceAsymmetricKeyWrapper(algorithmIdentifier, recipientCert.getPublicKey()));
+ }
+
+ /**
+ * Create a generator overriding the algorithm type implied by the public key passed in.
+ *
+ * @param subjectKeyIdentifier the subject key identifier value to associate with the public key.
+ * @param algorithmIdentifier the identifier and parameters for the encryption algorithm to be used.
+ * @param publicKey the public key to use.
+ */
+ public JceKeyTransRecipientInfoGenerator(byte[] subjectKeyIdentifier, AlgorithmIdentifier algorithmIdentifier, PublicKey publicKey)
+ {
+ super(subjectKeyIdentifier, new JceAsymmetricKeyWrapper(algorithmIdentifier, publicKey));
+ }
+
public JceKeyTransRecipientInfoGenerator setProvider(String providerName)
{
((JceAsymmetricKeyWrapper)this.wrapper).setProvider(providerName);
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java
index 107a0ef..15729a7 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java
@@ -15,6 +15,9 @@ public class ZlibExpanderProvider
{
private final long limit;
+ /**
+ * Base constructor. Create an expander which will not limit the size of any objects expanded in the stream.
+ */
public ZlibExpanderProvider()
{
this.limit = -1;
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/package.html b/bcpkix/src/main/java/org/bouncycastle/cms/package.html
deleted file mode 100644
index 644e862..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-A package for processing RFC 3852 Cryptographic Message Syntax (CMS) objects - also referred to as PKCS#7 (formerly RFC 2630, 3369).
-</body>
-</html>
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/AllTests.java
index dc81f5a..9cc2b0e 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/AllTests.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/AllTests.java
@@ -18,21 +18,13 @@ public class AllTests
{
TestSuite suite = new TestSuite("CMS tests");
- suite.addTest(AuthenticatedDataTest.suite());
- suite.addTest(AuthenticatedDataStreamTest.suite());
- suite.addTest(CompressedDataTest.suite());
suite.addTest(NewCompressedDataTest.suite());
- suite.addTest(SignedDataTest.suite());
suite.addTest(NewSignedDataTest.suite());
- suite.addTest(EnvelopedDataTest.suite());
suite.addTest(NewEnvelopedDataTest.suite());
suite.addTest(NewAuthenticatedDataTest.suite());
suite.addTest(NewAuthenticatedDataStreamTest.suite());
- suite.addTest(CompressedDataStreamTest.suite());
suite.addTest(NewCompressedDataStreamTest.suite());
- suite.addTest(SignedDataStreamTest.suite());
suite.addTest(NewSignedDataStreamTest.suite());
- suite.addTest(EnvelopedDataStreamTest.suite());
suite.addTest(NewEnvelopedDataStreamTest.suite());
suite.addTest(MiscDataStreamTest.suite());
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/AuthenticatedDataStreamTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/AuthenticatedDataStreamTest.java
deleted file mode 100644
index fe056e6..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/AuthenticatedDataStreamTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.bouncycastle.cms.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.security.KeyPair;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.cms.CMSAuthenticatedDataGenerator;
-import org.bouncycastle.cms.CMSAuthenticatedDataParser;
-import org.bouncycastle.cms.CMSAuthenticatedDataStreamGenerator;
-import org.bouncycastle.cms.RecipientInformation;
-import org.bouncycastle.cms.RecipientInformationStore;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
-public class AuthenticatedDataStreamTest
- extends TestCase
-{
- private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
-
- private static String _signDN;
- private static KeyPair _signKP;
- private static X509Certificate _signCert;
-
- private static String _origDN;
- private static KeyPair _origKP;
- private static X509Certificate _origCert;
-
- private static String _reciDN;
- private static KeyPair _reciKP;
- private static X509Certificate _reciCert;
-
- private static KeyPair _origEcKP;
- private static KeyPair _reciEcKP;
- private static X509Certificate _reciEcCert;
-
- private static boolean _initialised = false;
-
- public boolean DEBUG = true;
-
- private static void init()
- throws Exception
- {
- if (!_initialised)
- {
- _initialised = true;
-
- _signDN = "O=Bouncy Castle, C=AU";
- _signKP = CMSTestUtil.makeKeyPair();
- _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN);
-
- _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
- _origKP = CMSTestUtil.makeKeyPair();
- _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN);
-
- _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
- _reciKP = CMSTestUtil.makeKeyPair();
- _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN);
-
- _origEcKP = CMSTestUtil.makeEcDsaKeyPair();
- _reciEcKP = CMSTestUtil.makeEcDsaKeyPair();
- _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN);
- }
- }
-
- public void setUp()
- throws Exception
- {
- init();
- }
-
- public AuthenticatedDataStreamTest(String name)
- {
- super(name);
- }
-
- public static void main(String args[])
- {
- junit.textui.TestRunner.run(AuthenticatedDataStreamTest.class);
- }
-
- public static Test suite()
- throws Exception
- {
- init();
-
- return new CMSTestSetup(new TestSuite(AuthenticatedDataStreamTest.class));
- }
-
- public void testKeyTransDESede()
- throws Exception
- {
- tryKeyTrans(CMSAuthenticatedDataGenerator.DES_EDE3_CBC);
- }
-
- private void tryKeyTrans(String macAlg)
- throws Exception
- {
- byte[] data = "Eric H. Echidna".getBytes();
-
- CMSAuthenticatedDataStreamGenerator adGen = new CMSAuthenticatedDataStreamGenerator();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- adGen.addKeyTransRecipient(_reciCert);
-
- OutputStream aOut = adGen.open(bOut, macAlg, BC);
-
- aOut.write(data);
-
- aOut.close();
-
- CMSAuthenticatedDataParser ad = new CMSAuthenticatedDataParser(bOut.toByteArray());
-
- RecipientInformationStore recipients = ad.getRecipientInfos();
-
- assertEquals(ad.getMacAlgOID(), macAlg);
-
- Collection c = recipients.getRecipients();
-
- assertEquals(1, c.size());
-
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), BC);
-
- assertTrue(Arrays.equals(data, recData));
- assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
- }
- }
-} \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/AuthenticatedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/AuthenticatedDataTest.java
deleted file mode 100644
index 454b369..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/AuthenticatedDataTest.java
+++ /dev/null
@@ -1,308 +0,0 @@
-package org.bouncycastle.cms.test;
-
-import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-
-import javax.crypto.SecretKey;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.cms.CMSAuthenticatedData;
-import org.bouncycastle.cms.CMSAuthenticatedDataGenerator;
-import org.bouncycastle.cms.CMSException;
-import org.bouncycastle.cms.CMSPBEKey;
-import org.bouncycastle.cms.CMSProcessableByteArray;
-import org.bouncycastle.cms.PKCS5Scheme2PBEKey;
-import org.bouncycastle.cms.PasswordRecipientInformation;
-import org.bouncycastle.cms.RecipientInformation;
-import org.bouncycastle.cms.RecipientInformationStore;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Hex;
-
-public class AuthenticatedDataTest
- extends TestCase
-{
- private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
-
- private static String _signDN;
- private static KeyPair _signKP;
- private static X509Certificate _signCert;
-
- private static String _origDN;
- private static KeyPair _origKP;
- private static X509Certificate _origCert;
-
- private static String _reciDN;
- private static KeyPair _reciKP;
- private static X509Certificate _reciCert;
-
- private static KeyPair _origEcKP;
- private static KeyPair _reciEcKP;
- private static X509Certificate _reciEcCert;
-
- private static boolean _initialised = false;
-
- public boolean DEBUG = true;
-
- private static void init()
- throws Exception
- {
- if (!_initialised)
- {
- _initialised = true;
-
- _signDN = "O=Bouncy Castle, C=AU";
- _signKP = CMSTestUtil.makeKeyPair();
- _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN);
-
- _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
- _origKP = CMSTestUtil.makeKeyPair();
- _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN);
-
- _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
- _reciKP = CMSTestUtil.makeKeyPair();
- _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN);
-
- _origEcKP = CMSTestUtil.makeEcDsaKeyPair();
- _reciEcKP = CMSTestUtil.makeEcDsaKeyPair();
- _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN);
- }
- }
-
- public void setUp()
- throws Exception
- {
- init();
- }
-
- public AuthenticatedDataTest(String name)
- {
- super(name);
- }
-
- public static void main(String args[])
- {
- junit.textui.TestRunner.run(AuthenticatedDataTest.class);
- }
-
- public static Test suite()
- throws Exception
- {
- init();
-
- return new CMSTestSetup(new TestSuite(AuthenticatedDataTest.class));
- }
-
- public void testKeyTransDESede()
- throws Exception
- {
- tryKeyTrans(CMSAuthenticatedDataGenerator.DES_EDE3_CBC);
- }
-
- public void testKEKDESede()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeDesede192Key(), new DERObjectIdentifier("1.2.840.113549.1.9.16.3.6"));
- }
-
- public void testPasswordAES256()
- throws Exception
- {
- passwordTest(CMSAuthenticatedDataGenerator.AES256_CBC);
- }
-
- public void testECKeyAgree()
- throws Exception
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();
-
- adGen.addKeyAgreementRecipient(CMSAuthenticatedDataGenerator.ECDH_SHA1KDF, _origEcKP.getPrivate(), _origEcKP.getPublic(), _reciEcCert, CMSAuthenticatedDataGenerator.AES128_WRAP, BC);
-
- CMSAuthenticatedData ad = adGen.generate(
- new CMSProcessableByteArray(data),
- CMSAuthenticatedDataGenerator.DES_EDE3_CBC, BC);
-
- RecipientInformationStore recipients = ad.getRecipientInfos();
-
- assertEquals(ad.getMacAlgOID(),
- CMSAuthenticatedDataGenerator.DES_EDE3_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- byte[] recData = recipient.getContent(_reciEcKP.getPrivate(), BC);
- assertTrue(Arrays.equals(data, recData));
- assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- public void testEncoding()
- throws Exception
- {
- byte[] data = "Eric H. Echidna".getBytes();
-
- CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();
-
- adGen.addKeyTransRecipient(_reciCert);
-
- CMSAuthenticatedData ad = adGen.generate(
- new CMSProcessableByteArray(data),
- CMSAuthenticatedDataGenerator.DES_EDE3_CBC, BC);
-
- ad = new CMSAuthenticatedData(ad.getEncoded());
-
- RecipientInformationStore recipients = ad.getRecipientInfos();
-
- assertEquals(CMSAuthenticatedDataGenerator.DES_EDE3_CBC, ad.getMacAlgOID());
-
- Collection c = recipients.getRecipients();
-
- assertEquals(1, c.size());
-
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), BC);
-
- assertTrue(Arrays.equals(data, recData));
- assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
- }
- }
-
- private void tryKeyTrans(String macAlg)
- throws Exception
- {
- byte[] data = "Eric H. Echidna".getBytes();
-
- CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();
-
- adGen.addKeyTransRecipient(_reciCert);
-
- CMSAuthenticatedData ad = adGen.generate(
- new CMSProcessableByteArray(data),
- macAlg, BC);
-
- RecipientInformationStore recipients = ad.getRecipientInfos();
-
- assertEquals(ad.getMacAlgOID(), macAlg);
-
- Collection c = recipients.getRecipients();
-
- assertEquals(1, c.size());
-
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), BC);
-
- assertTrue(Arrays.equals(data, recData));
- assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
- }
- }
-
- private void tryKekAlgorithm(SecretKey kek, DERObjectIdentifier algOid)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- byte[] data = "Eric H. Echidna".getBytes();
-
- CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();
-
- byte[] kekId = new byte[] { 1, 2, 3, 4, 5 };
-
- adGen.addKEKRecipient(kek, kekId);
-
- CMSAuthenticatedData ad = adGen.generate(
- new CMSProcessableByteArray(data),
- CMSAuthenticatedDataGenerator.DES_EDE3_CBC, BC);
-
- RecipientInformationStore recipients = ad.getRecipientInfos();
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC);
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId());
-
- byte[] recData = recipient.getContent(kek, BC);
-
- assertTrue(Arrays.equals(data, recData));
- assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- private void passwordTest(String algorithm)
- throws Exception
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();
-
- adGen.addPasswordRecipient(new PKCS5Scheme2PBEKey("password".toCharArray(), new byte[20], 5), algorithm);
-
- CMSAuthenticatedData ad = adGen.generate(
- new CMSProcessableByteArray(data),
- CMSAuthenticatedDataGenerator.DES_EDE3_CBC, BC);
-
- RecipientInformationStore recipients = ad.getRecipientInfos();
-
- assertEquals(ad.getMacAlgOID(),
- CMSAuthenticatedDataGenerator.DES_EDE3_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- PasswordRecipientInformation recipient = (PasswordRecipientInformation)it.next();
-
- CMSPBEKey key = new PKCS5Scheme2PBEKey("password".toCharArray(),
- recipient.getKeyDerivationAlgParameters(BC));
-
- byte[] recData = recipient.getContent(key, BC);
-
- assertTrue(Arrays.equals(data, recData));
- assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
- }
- else
- {
- fail("no recipient found");
- }
- }
-} \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/BcSignedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/BcSignedDataTest.java
index 299f68d..1c4ccc0 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/BcSignedDataTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/BcSignedDataTest.java
@@ -61,6 +61,7 @@ import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.BufferingContentSigner;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
@@ -572,6 +573,46 @@ public class BcSignedDataTest
verifySignatures(s, null);
}
+ public void testDetachedVerificationWithBufferingContentSigner()
+ throws Exception
+ {
+ byte[] data = "Hello World!".getBytes();
+ List certList = new ArrayList();
+ CMSTypedData msg = new CMSProcessableByteArray(data);
+
+ certList.add(_origCert);
+ certList.add(_signCert);
+
+ Store certs = new JcaCertStore(certList);
+
+ CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
+
+ DigestCalculatorProvider digProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build();
+ JcaSignerInfoGeneratorBuilder signerInfoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(digProvider);
+ ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate());
+ ContentSigner md5Signer = new JcaContentSignerBuilder("MD5withRSA").setProvider(BC).build(_origKP.getPrivate());
+
+ gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(new BufferingContentSigner(sha1Signer), _origCert));
+ gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(new BufferingContentSigner(md5Signer), _origCert));
+
+ gen.addCertificates(certs);
+
+ CMSSignedData s = gen.generate(msg);
+
+ MessageDigest sha1 = MessageDigest.getInstance("SHA1", BC);
+ MessageDigest md5 = MessageDigest.getInstance("MD5", BC);
+ Map hashes = new HashMap();
+ byte[] sha1Hash = sha1.digest(data);
+ byte[] md5Hash = md5.digest(data);
+
+ hashes.put(CMSAlgorithm.SHA1, sha1Hash);
+ hashes.put(CMSAlgorithm.MD5, md5Hash);
+
+ s = new CMSSignedData(hashes, s.getEncoded());
+
+ verifySignatures(s, null);
+ }
+
public void testSHA1AndMD5WithRSAEncapsulatedRepeated()
throws Exception
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/CMSTestUtil.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/CMSTestUtil.java
index 4eb9841..3a1517a 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/CMSTestUtil.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/CMSTestUtil.java
@@ -20,32 +20,38 @@ import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.RSAESOAEPparams;
import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.CRLReason;
+import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.X509Name;
+import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.bouncycastle.cert.X509ExtensionUtils;
+import org.bouncycastle.cert.X509v1CertificateBuilder;
import org.bouncycastle.cert.X509v2CRLBuilder;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaX509v1CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.ECGOST3410NamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.GOST3410ParameterSpec;
+import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.x509.X509AttributeCertificate;
-import org.bouncycastle.x509.X509StreamParser;
-import org.bouncycastle.x509.X509V1CertificateGenerator;
-import org.bouncycastle.x509.X509V3CertificateGenerator;
-import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
public class CMSTestUtil
{
public static SecureRandom rand;
public static KeyPairGenerator kpg;
+
public static KeyPairGenerator gostKpg;
public static KeyPairGenerator dsaKpg;
public static KeyPairGenerator ecGostKpg;
@@ -114,7 +120,10 @@ public class CMSTestUtil
kpg = KeyPairGenerator.getInstance("RSA", "BC");
kpg.initialize(1024, rand);
-
+
+ kpg = KeyPairGenerator.getInstance("RSA", "BC");
+ kpg.initialize(1024, rand);
+
gostKpg = KeyPairGenerator.getInstance("GOST3410", "BC");
GOST3410ParameterSpec gost3410P = new GOST3410ParameterSpec(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A.getId());
@@ -189,14 +198,10 @@ public class CMSTestUtil
return buf.toString();
}
- public static X509AttributeCertificate getAttributeCertificate()
+ public static X509AttributeCertificateHolder getAttributeCertificate()
throws Exception
{
- X509StreamParser parser = X509StreamParser.getInstance("AttributeCertificate", "BC");
-
- parser.init(CMSTestUtil.attrCert);
-
- return (X509AttributeCertificate)parser.read();
+ return new X509AttributeCertificateHolder(CMSTestUtil.attrCert);
}
public static KeyPair makeKeyPair()
@@ -273,60 +278,44 @@ public class CMSTestUtil
public static X509Certificate makeCertificate(KeyPair _subKP,
String _subDN, KeyPair _issKP, String _issDN)
- throws GeneralSecurityException, IOException
+ throws GeneralSecurityException, IOException, OperatorCreationException
{
-
return makeCertificate(_subKP, _subDN, _issKP, _issDN, false);
}
- public static X509Certificate makeCACertificate(KeyPair _subKP,
+ public static X509Certificate makeOaepCertificate(KeyPair _subKP,
String _subDN, KeyPair _issKP, String _issDN)
- throws GeneralSecurityException, IOException
+ throws GeneralSecurityException, IOException, OperatorCreationException
{
+ return makeOaepCertificate(_subKP, _subDN, _issKP, _issDN, false);
+ }
+ public static X509Certificate makeCACertificate(KeyPair _subKP,
+ String _subDN, KeyPair _issKP, String _issDN)
+ throws GeneralSecurityException, IOException, OperatorCreationException
+ {
return makeCertificate(_subKP, _subDN, _issKP, _issDN, true);
}
public static X509Certificate makeV1Certificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN)
- throws GeneralSecurityException, IOException
+ throws GeneralSecurityException, IOException, OperatorCreationException
{
PublicKey subPub = subKP.getPublic();
PrivateKey issPriv = issKP.getPrivate();
PublicKey issPub = issKP.getPublic();
- X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator();
+ X509v1CertificateBuilder v1CertGen = new JcaX509v1CertificateBuilder(
+ new X500Name(_issDN),
+ allocateSerialNumber(),
+ new Date(System.currentTimeMillis()),
+ new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)),
+ new X500Name(_subDN),
+ subPub);
- v1CertGen.reset();
- v1CertGen.setSerialNumber(allocateSerialNumber());
- v1CertGen.setIssuerDN(new X509Name(_issDN));
- v1CertGen.setNotBefore(new Date(System.currentTimeMillis()));
- v1CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)));
- v1CertGen.setSubjectDN(new X509Name(_subDN));
- v1CertGen.setPublicKey(subPub);
+ JcaContentSignerBuilder contentSignerBuilder = makeContentSignerBuilder(issPub);
- if (issPub instanceof RSAPublicKey)
- {
- v1CertGen.setSignatureAlgorithm("SHA1WithRSA");
- }
- else if (issPub.getAlgorithm().equals("DSA"))
- {
- v1CertGen.setSignatureAlgorithm("SHA1withDSA");
- }
- else if (issPub.getAlgorithm().equals("ECDSA"))
- {
- v1CertGen.setSignatureAlgorithm("SHA1withECDSA");
- }
- else if (issPub.getAlgorithm().equals("ECGOST3410"))
- {
- v1CertGen.setSignatureAlgorithm("GOST3411withECGOST3410");
- }
- else
- {
- v1CertGen.setSignatureAlgorithm("GOST3411WithGOST3410");
- }
-
- X509Certificate _cert = v1CertGen.generate(issPriv);
+ X509Certificate _cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(v1CertGen.build(contentSignerBuilder.build(issPriv)));
_cert.checkValidity(new Date());
_cert.verify(issPub);
@@ -335,78 +324,128 @@ public class CMSTestUtil
}
public static X509Certificate makeCertificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN, boolean _ca)
- throws GeneralSecurityException, IOException
+ throws GeneralSecurityException, IOException, OperatorCreationException
{
PublicKey subPub = subKP.getPublic();
PrivateKey issPriv = issKP.getPrivate();
PublicKey issPub = issKP.getPublic();
- X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
-
- v3CertGen.reset();
- v3CertGen.setSerialNumber(allocateSerialNumber());
- v3CertGen.setIssuerDN(new X509Name(_issDN));
- v3CertGen.setNotBefore(new Date(System.currentTimeMillis()));
- v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)));
- v3CertGen.setSubjectDN(new X509Name(_subDN));
- v3CertGen.setPublicKey(subPub);
-
- if (issPub instanceof RSAPublicKey)
- {
- v3CertGen.setSignatureAlgorithm("SHA1WithRSA");
- }
- else if (issPub.getAlgorithm().equals("DSA"))
- {
- v3CertGen.setSignatureAlgorithm("SHA1withDSA");
- }
- else if (issPub.getAlgorithm().equals("ECDSA"))
- {
- v3CertGen.setSignatureAlgorithm("SHA1withECDSA");
- }
- else if (issPub.getAlgorithm().equals("ECGOST3410"))
- {
- v3CertGen.setSignatureAlgorithm("GOST3411withECGOST3410");
- }
- else
- {
- v3CertGen.setSignatureAlgorithm("GOST3411WithGOST3410");
- }
+ X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder(
+ new X500Name(_issDN),
+ allocateSerialNumber(),
+ new Date(System.currentTimeMillis()),
+ new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)),
+ new X500Name(_subDN),
+ subPub);
+
+ JcaContentSignerBuilder contentSignerBuilder = makeContentSignerBuilder(issPub);
v3CertGen.addExtension(
- X509Extension.subjectKeyIdentifier,
+ Extension.subjectKeyIdentifier,
false,
createSubjectKeyId(subPub));
v3CertGen.addExtension(
- X509Extension.authorityKeyIdentifier,
+ Extension.authorityKeyIdentifier,
false,
createAuthorityKeyId(issPub));
v3CertGen.addExtension(
- X509Extension.basicConstraints,
+ Extension.basicConstraints,
false,
new BasicConstraints(_ca));
- X509Certificate _cert = v3CertGen.generate(issPriv);
+ X509Certificate _cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(v3CertGen.build(contentSignerBuilder.build(issPriv)));
_cert.checkValidity(new Date());
_cert.verify(issPub);
return _cert;
}
-
+
+ public static X509Certificate makeOaepCertificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN, boolean _ca)
+ throws GeneralSecurityException, IOException, OperatorCreationException
+ {
+
+ SubjectPublicKeyInfo subPub = SubjectPublicKeyInfo.getInstance(subKP.getPublic().getEncoded());
+ PrivateKey issPriv = issKP.getPrivate();
+ PublicKey issPub = issKP.getPublic();
+
+ X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(
+ new X500Name(_issDN),
+ allocateSerialNumber(),
+ new Date(System.currentTimeMillis()),
+ new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)),
+ new X500Name(_subDN),
+ new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, new RSAESOAEPparams()), subPub.parsePublicKey()));
+
+ JcaContentSignerBuilder contentSignerBuilder = makeContentSignerBuilder(issPub);
+
+ v3CertGen.addExtension(
+ Extension.subjectKeyIdentifier,
+ false,
+ createSubjectKeyId(subPub));
+
+ v3CertGen.addExtension(
+ Extension.authorityKeyIdentifier,
+ false,
+ createAuthorityKeyId(issPub));
+
+ v3CertGen.addExtension(
+ Extension.basicConstraints,
+ false,
+ new BasicConstraints(_ca));
+
+ X509Certificate _cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(v3CertGen.build(contentSignerBuilder.build(issPriv)));
+
+ _cert.checkValidity(new Date());
+ _cert.verify(issPub);
+
+ return _cert;
+ }
+
+ private static JcaContentSignerBuilder makeContentSignerBuilder(PublicKey issPub)
+ {
+ JcaContentSignerBuilder contentSignerBuilder;
+ if (issPub instanceof RSAPublicKey)
+ {
+ contentSignerBuilder = new JcaContentSignerBuilder("SHA1WithRSA");
+ }
+ else if (issPub.getAlgorithm().equals("DSA"))
+ {
+ contentSignerBuilder = new JcaContentSignerBuilder("SHA1withDSA");
+ }
+ else if (issPub.getAlgorithm().equals("ECDSA"))
+ {
+ contentSignerBuilder = new JcaContentSignerBuilder("SHA1withECDSA");
+ }
+ else if (issPub.getAlgorithm().equals("ECGOST3410"))
+ {
+ contentSignerBuilder = new JcaContentSignerBuilder("GOST3411withECGOST3410");
+ }
+ else
+ {
+ contentSignerBuilder = new JcaContentSignerBuilder("GOST3411WithGOST3410");
+ }
+
+ contentSignerBuilder.setProvider(BouncyCastleProvider.PROVIDER_NAME);
+
+ return contentSignerBuilder;
+ }
+
public static X509CRL makeCrl(KeyPair pair)
throws Exception
{
Date now = new Date();
X509v2CRLBuilder crlGen = new X509v2CRLBuilder(new X500Name("CN=Test CA"), now);
+ JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils();
crlGen.setNextUpdate(new Date(now.getTime() + 100000));
crlGen.addCRLEntry(BigInteger.ONE, now, CRLReason.privilegeWithdrawn);
- crlGen.addExtension(X509Extension.authorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.getPublic()));
+ crlGen.addExtension(Extension.authorityKeyIdentifier, false, extensionUtils.createAuthorityKeyIdentifier(pair.getPublic()));
return new JcaX509CRLConverter().setProvider("BC").getCRL(crlGen.build(new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider("BC").build(pair.getPrivate())));
}
@@ -427,6 +466,13 @@ public class CMSTestUtil
}
static SubjectKeyIdentifier createSubjectKeyId(
+ SubjectPublicKeyInfo _pubKey)
+ throws IOException
+ {
+ return extUtils.createSubjectKeyIdentifier(_pubKey);
+ }
+
+ static SubjectKeyIdentifier createSubjectKeyId(
PublicKey _pubKey)
throws IOException
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/CompressedDataStreamTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/CompressedDataStreamTest.java
deleted file mode 100644
index f9e5d62..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/CompressedDataStreamTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.bouncycastle.cms.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.Random;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import org.bouncycastle.cms.CMSCompressedDataParser;
-import org.bouncycastle.cms.CMSCompressedDataStreamGenerator;
-import org.bouncycastle.util.encoders.Base64;
-
-public class CompressedDataStreamTest
- extends TestCase
-{
- public CompressedDataStreamTest(String name)
- {
- super(name);
- }
-
- public void testWorkingData()
- throws Exception
- {
- byte[] compData = Base64.decode(
- "MIAGCyqGSIb3DQEJEAEJoIAwgAIBADANBgsqhkiG9w0BCRADCDCABgkqhkiG9w0BBwGggCSABIIC"
- + "Hnic7ZRdb9owFIbvK/k/5PqVYPFXGK12YYyboVFASSp1vQtZGiLRACZE49/XHoUW7S/0tXP8Efux"
- + "fU5ivWnasml72XFb3gb5druui7ytN803M570nii7C5r8tfwR281hy/p/KSM3+jzH5s3+pbQ90xSb"
- + "P3VT3QbLusnt8WPIuN5vN/vaA2+DulnXTXkXvNTr8j8ouZmkCmGI/UW+ZS/C8zP0bz2dz0zwLt+1"
- + "UEk2M8mlaxjRMByAhZTj0RGYg4TvogiRASROsZgjpVcJCb1KV6QzQeDJ1XkoQ5Jm+C5PbOHZZGRi"
- + "v+ORAcshOGeCcdFJyfgFxdtCdEcmOrbinc/+BBMzRThEYpwl+jEBpciSGWQkI0TSlREmD/eOHb2D"
- + "SGLuESm/iKUFt1y4XHBO2a5oq0IKJKWLS9kUZTA7vC5LSxYmgVL46SIWxIfWBQd6AdrnjLmH94UT"
- + "vGxVibLqRCtIpp4g2qpdtqK1LiOeolpVK5wVQ5P7+QjZAlrh0cePYTx/gNZuB9Vhndtgujl9T/tg"
- + "W9ogK+3rnmg3YWygnTuF5GDS+Q/jIVLnCcYZFc6Kk/+c80wKwZjwdZIqDYWRH68MuBQSXLgXYXj2"
- + "3CAaYOBNJMliTl0X7eV5DnoKIFSKYdj3cRpD/cK/JWTHJRe76MUXnfBW8m7Hd5zhQ4ri2NrVF/WL"
- + "+kV1/3AGSlJ32bFPd2BsQD8uSzIx6lObkjdz95c0AAAAAAAAAAAAAAAA");
-
- byte[] uncompData = Base64.decode(
- "Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9FREktWDEyOyBuYW1lPUdyb3VwMi54MTINCkNvbnRl"
- + "bnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJpbmFyeQ0KQ29udGVudC1EaXNwb3NpdGlvbjogaW5saW5l"
- + "OyBmaWxlbmFtZT1Hcm91cDIueDEyDQoNCklTQSowMCpzc3Nzc3Nzc3NzKjAwKnJycnJycnJycnIqW"
- + "loqQ1lDTE9ORSAgICAgICAgKlpaKlBBUlRORVIgICAgICAgICo5NjEwMDcqMjAxMypVKjAwMjAwKj"
- + "AwMDAwMDAwMSowKlQqKg1HUypQTypTMVMxUzFTMVMxUzFTMVMqUjFSMVIxUjFSMVIxUjFSKjk2MTA"
- + "wNyoyMDEzKjAwMDAwMDAwNCpYKjAwMzA1MA1TVCo4NTAqMDAwMDQwMDAxDUJFRyowMCpCRSoyYSo0"
- + "MzMyNDIzNHY1NTIzKjk2MTAwNyoyM3RjNHZ5MjR2MmgzdmgzdmgqWloqSUVMKjA5KlJFKjA5DUNVU"
- + "ioxMSpUUk4qNTY1Nio2NSo1NjYqSU1GKjAwNio5NjEwMDcNUkVGKjZBKjQzM3IxYzNyMzRyMzRjMz"
- + "MxMnFjdGdjNTQqUmVmZXJlbmNlIE51bWJlcg1QRVIqQUEqSGFucyBHdXR0ZW4qQ1AqMS4zMjIuMzI"
- + "zLjQ0NDQqKioqKnJnZzRlZ3Y0dDQNVEFYKjR0Z3RidDR0cjR0cipHTCpnaGdoKioqKioqKioqRypD"
- + "DUZPQipUUCpDQSpVU0EqMDIqRE9NKkNDKlJlZ3VsYXIgTG9jYXRpb25zIHBlciBUZXJtcw1DVFAqR"
- + "EUqQzA0KjQ1MyoyNTAwMCpEOSpTRUwqMjMyMTQqMjM0MzI0MjM0MjMqRVMqNDIyNDM0MjMNU0FDKk"
- + "EqQjAwMCpBRSozNTQ1KjM0NDIzMDANQ1VSKjExKjc2Nyo3NzY3KjY1DVBPMSoxMTEtYWFhKjEwMDA"
- + "wMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioq"
- + "KioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzN"
- + "HE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMD"
- + "AwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKio"
- + "qKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRx"
- + "NmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwM"
- + "CpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKi"
- + "oqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZ"
- + "mMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAq"
- + "QVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqK"
- + "kExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2Zj"
- + "M1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkF"
- + "TKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipB"
- + "MSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzN"
- + "TM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNQ1RUKjENU0UqMjIqMDAwMDQwMDAxDU"
- + "dFKjEqMDAwMDAwMDA0DUlFQSoxKjAwMDAwMDAwMQ0=");
-
- CMSCompressedDataParser ed = new CMSCompressedDataParser(compData);
-
- assertEquals(true, Arrays.equals(uncompData, CMSTestUtil.streamToByteArray(ed.getContent().getContentStream())));
- }
-
- public void testEach()
- throws Exception
- {
- byte[] testData = "Hello world!".getBytes();
-
- CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream cOut = gen.open(bOut, CMSCompressedDataStreamGenerator.ZLIB);
-
- cOut.write(testData);
-
- cOut.close();
-
- CMSCompressedDataParser ed = new CMSCompressedDataParser(bOut.toByteArray());
-
- assertEquals(true, Arrays.equals(testData, CMSTestUtil.streamToByteArray(ed.getContent().getContentStream())));
- }
-
- public void test1000()
- throws Exception
- {
- byte[] testData = new byte[10000];
- Random rand = new Random();
-
- rand.setSeed(0);
-
- for (int i = 0; i != 10; i++)
- {
- CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream cOut = gen.open(bOut, CMSCompressedDataStreamGenerator.ZLIB);
-
- rand.nextBytes(testData);
-
- cOut.write(testData);
-
- cOut.close();
-
- CMSCompressedDataParser ed = new CMSCompressedDataParser(bOut.toByteArray());
-
- assertEquals(true, Arrays.equals(testData, CMSTestUtil.streamToByteArray(ed.getContent().getContentStream())));
- }
- }
-
- public static Test suite()
- {
- return new TestSuite(CompressedDataStreamTest.class);
- }
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/CompressedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/CompressedDataTest.java
deleted file mode 100644
index 6fd06b3..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/CompressedDataTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.bouncycastle.cms.test;
-
-import java.util.Arrays;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.cms.CMSCompressedData;
-import org.bouncycastle.cms.CMSCompressedDataGenerator;
-import org.bouncycastle.cms.CMSException;
-import org.bouncycastle.cms.CMSProcessableByteArray;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.io.StreamOverflowException;
-
-public class CompressedDataTest
- extends TestCase
-{
- private static final byte[] TEST_DATA = "Hello world!".getBytes();
-
- /*
- *
- * INFRASTRUCTURE
- *
- */
-
- public CompressedDataTest(String name)
- {
- super(name);
- }
-
- public static void main(String args[])
- {
- junit.textui.TestRunner.run(CompressedDataTest.class);
- }
-
- public static Test suite()
- {
- return new CMSTestSetup(new TestSuite(CompressedDataTest.class));
- }
-
- public void setUp()
- {
-
- }
-
- public void tearDown()
- {
-
- }
-
- public void testWorkingData()
- throws Exception
- {
- byte[] compData = Base64
- .decode("MIAGCyqGSIb3DQEJEAEJoIAwgAIBADANBgsqhkiG9w0BCRADCDCABgkqhkiG9w0BBwGggCSABIIC"
- + "Hnic7ZRdb9owFIbvK/k/5PqVYPFXGK12YYyboVFASSp1vQtZGiLRACZE49/XHoUW7S/0tXP8Efux"
- + "fU5ivWnasml72XFb3gb5druui7ytN803M570nii7C5r8tfwR281hy/p/KSM3+jzH5s3+pbQ90xSb"
- + "P3VT3QbLusnt8WPIuN5vN/vaA2+DulnXTXkXvNTr8j8ouZmkCmGI/UW+ZS/C8zP0bz2dz0zwLt+1"
- + "UEk2M8mlaxjRMByAhZTj0RGYg4TvogiRASROsZgjpVcJCb1KV6QzQeDJ1XkoQ5Jm+C5PbOHZZGRi"
- + "v+ORAcshOGeCcdFJyfgFxdtCdEcmOrbinc/+BBMzRThEYpwl+jEBpciSGWQkI0TSlREmD/eOHb2D"
- + "SGLuESm/iKUFt1y4XHBO2a5oq0IKJKWLS9kUZTA7vC5LSxYmgVL46SIWxIfWBQd6AdrnjLmH94UT"
- + "vGxVibLqRCtIpp4g2qpdtqK1LiOeolpVK5wVQ5P7+QjZAlrh0cePYTx/gNZuB9Vhndtgujl9T/tg"
- + "W9ogK+3rnmg3YWygnTuF5GDS+Q/jIVLnCcYZFc6Kk/+c80wKwZjwdZIqDYWRH68MuBQSXLgXYXj2"
- + "3CAaYOBNJMliTl0X7eV5DnoKIFSKYdj3cRpD/cK/JWTHJRe76MUXnfBW8m7Hd5zhQ4ri2NrVF/WL"
- + "+kV1/3AGSlJ32bFPd2BsQD8uSzIx6lObkjdz95c0AAAAAAAAAAAAAAAA");
-
- byte[] uncompData = Base64
- .decode("Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9FREktWDEyOyBuYW1lPUdyb3VwMi54MTINCkNvbnRl"
- + "bnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJpbmFyeQ0KQ29udGVudC1EaXNwb3NpdGlvbjogaW5saW5l"
- + "OyBmaWxlbmFtZT1Hcm91cDIueDEyDQoNCklTQSowMCpzc3Nzc3Nzc3NzKjAwKnJycnJycnJycnIqW"
- + "loqQ1lDTE9ORSAgICAgICAgKlpaKlBBUlRORVIgICAgICAgICo5NjEwMDcqMjAxMypVKjAwMjAwKj"
- + "AwMDAwMDAwMSowKlQqKg1HUypQTypTMVMxUzFTMVMxUzFTMVMqUjFSMVIxUjFSMVIxUjFSKjk2MTA"
- + "wNyoyMDEzKjAwMDAwMDAwNCpYKjAwMzA1MA1TVCo4NTAqMDAwMDQwMDAxDUJFRyowMCpCRSoyYSo0"
- + "MzMyNDIzNHY1NTIzKjk2MTAwNyoyM3RjNHZ5MjR2MmgzdmgzdmgqWloqSUVMKjA5KlJFKjA5DUNVU"
- + "ioxMSpUUk4qNTY1Nio2NSo1NjYqSU1GKjAwNio5NjEwMDcNUkVGKjZBKjQzM3IxYzNyMzRyMzRjMz"
- + "MxMnFjdGdjNTQqUmVmZXJlbmNlIE51bWJlcg1QRVIqQUEqSGFucyBHdXR0ZW4qQ1AqMS4zMjIuMzI"
- + "zLjQ0NDQqKioqKnJnZzRlZ3Y0dDQNVEFYKjR0Z3RidDR0cjR0cipHTCpnaGdoKioqKioqKioqRypD"
- + "DUZPQipUUCpDQSpVU0EqMDIqRE9NKkNDKlJlZ3VsYXIgTG9jYXRpb25zIHBlciBUZXJtcw1DVFAqR"
- + "EUqQzA0KjQ1MyoyNTAwMCpEOSpTRUwqMjMyMTQqMjM0MzI0MjM0MjMqRVMqNDIyNDM0MjMNU0FDKk"
- + "EqQjAwMCpBRSozNTQ1KjM0NDIzMDANQ1VSKjExKjc2Nyo3NzY3KjY1DVBPMSoxMTEtYWFhKjEwMDA"
- + "wMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioq"
- + "KioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzN"
- + "HE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMD"
- + "AwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKio"
- + "qKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRx"
- + "NmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwM"
- + "CpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKi"
- + "oqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZ"
- + "mMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAq"
- + "QVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqK"
- + "kExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2Zj"
- + "M1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkF"
- + "TKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipB"
- + "MSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzN"
- + "TM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNQ1RUKjENU0UqMjIqMDAwMDQwMDAxDUdFKjEqMDAwMDAwMDA0DUlFQSoxKjAwMDAwMDAwMQ0=");
-
- CMSCompressedData ed = new CMSCompressedData(compData);
-
- assertEquals(true, Arrays.equals(uncompData, ed.getContent()));
- }
-
- public void testEach()
- throws Exception
- {
- CMSCompressedData cd = getStdData();
-
- assertEquals(true, Arrays.equals(TEST_DATA, cd.getContent()));
- }
-
- public void testLimitUnder()
- throws Exception
- {
- CMSCompressedData cd = getStdData();
-
- try
- {
- cd.getContent(TEST_DATA.length / 2);
- }
- catch (CMSException e)
- {
- assertEquals(true, e.getCause() instanceof StreamOverflowException);
- }
- }
-
- public void testLimitOver()
- throws Exception
- {
- CMSCompressedData cd = getStdData();
-
- assertEquals(true, Arrays.equals(TEST_DATA, cd.getContent(TEST_DATA.length * 2)));
- }
-
- public void testLimitEqual()
- throws Exception
- {
- CMSCompressedData cd = getStdData();
-
- assertEquals(true, Arrays.equals(TEST_DATA, cd.getContent(TEST_DATA.length)));
- }
-
- private CMSCompressedData getStdData()
- throws CMSException
- {
- CMSProcessableByteArray testData = new CMSProcessableByteArray(TEST_DATA);
- CMSCompressedDataGenerator gen = new CMSCompressedDataGenerator();
-
- return gen.generate(testData,
- CMSCompressedDataGenerator.ZLIB);
- }
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/EnvelopedDataStreamTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/EnvelopedDataStreamTest.java
deleted file mode 100644
index 046db10..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/EnvelopedDataStreamTest.java
+++ /dev/null
@@ -1,631 +0,0 @@
-package org.bouncycastle.cms.test;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.Key;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.Security;
-import java.security.cert.X509Certificate;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-
-import javax.crypto.SecretKey;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
-import org.bouncycastle.cms.CMSEnvelopedDataParser;
-import org.bouncycastle.cms.CMSEnvelopedDataStreamGenerator;
-import org.bouncycastle.cms.CMSTypedStream;
-import org.bouncycastle.cms.KEKRecipientId;
-import org.bouncycastle.cms.RecipientId;
-import org.bouncycastle.cms.RecipientInformation;
-import org.bouncycastle.cms.RecipientInformationStore;
-import org.bouncycastle.cms.jcajce.JceKeyAgreeRecipientId;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-
-public class EnvelopedDataStreamTest
- extends TestCase
-{
- private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
-
- private static final int BUFFER_SIZE = 4000;
- private static String _signDN;
- private static KeyPair _signKP;
- private static X509Certificate _signCert;
-
- private static String _origDN;
- private static KeyPair _origKP;
- private static X509Certificate _origCert;
-
- private static String _reciDN;
- private static KeyPair _reciKP;
- private static X509Certificate _reciCert;
-
- private static KeyPair _origEcKP;
- private static KeyPair _reciEcKP;
- private static X509Certificate _reciEcCert;
-
- private static boolean _initialised = false;
-
- public EnvelopedDataStreamTest()
- {
- }
-
- private static void init()
- throws Exception
- {
- if (!_initialised)
- {
- _initialised = true;
-
- _signDN = "O=Bouncy Castle, C=AU";
- _signKP = CMSTestUtil.makeKeyPair();
- _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN);
-
- _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
- _origKP = CMSTestUtil.makeKeyPair();
- _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN);
-
- _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
- _reciKP = CMSTestUtil.makeKeyPair();
- _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN);
-
- _origEcKP = CMSTestUtil.makeEcDsaKeyPair();
- _reciEcKP = CMSTestUtil.makeEcDsaKeyPair();
- _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN);
- }
- }
-
- public void setUp()
- throws Exception
- {
- init();
- }
-
- public void testWorkingData()
- throws Exception
- {
- byte[] keyData = Base64.decode(
- "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKrAz/SQKrcQ" +
- "nj9IxHIfKDbuXsMqUpI06s2gps6fp7RDNvtUDDMOciWGFhD45YSy8GO0mPx3" +
- "Nkc7vKBqX4TLcqLUz7kXGOHGOwiPZoNF+9jBMPNROe/B0My0PkWg9tuq+nxN" +
- "64oD47+JvDwrpNOS5wsYavXeAW8Anv9ZzHLU7KwZAgMBAAECgYA/fqdVt+5K" +
- "WKGfwr1Z+oAHvSf7xtchiw/tGtosZ24DOCNP3fcTXUHQ9kVqVkNyzt9ZFCT3" +
- "bJUAdBQ2SpfuV4DusVeQZVzcROKeA09nPkxBpTefWbSDQGhb+eZq9L8JDRSW" +
- "HyYqs+MBoUpLw7GKtZiJkZyY6CsYkAnQ+uYVWq/TIQJBAP5zafO4HUV/w4KD" +
- "VJi+ua+GYF1Sg1t/dYL1kXO9GP1p75YAmtm6LdnOCas7wj70/G1YlPGkOP0V" +
- "GFzeG5KAmAUCQQCryvKU9nwWA+kypcQT9Yr1P4vGS0APYoBThnZq7jEPc5Cm" +
- "ZI82yseSxSeea0+8KQbZ5mvh1p3qImDLEH/iNSQFAkAghS+tboKPN10NeSt+" +
- "uiGRRWNbiggv0YJ7Uldcq3ZeLQPp7/naiekCRUsHD4Qr97OrZf7jQ1HlRqTu" +
- "eZScjMLhAkBNUMZCQnhwFAyEzdPkQ7LpU1MdyEopYmRssuxijZao5JLqQAGw" +
- "YCzXokGFa7hz72b09F4DQurJL/WuDlvvu4jdAkEAxwT9lylvfSfEQw4/qQgZ" +
- "MFB26gqB6Gqs1pHIZCzdliKx5BO3VDeUGfXMI8yOkbXoWbYx5xPid/+N8R//" +
- "+sxLBw==");
-
- byte[] envData = Base64.decode(
- "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1C" +
- "b3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBHjANBgkqhkiG9w0BAQEFAASB" +
- "gDmnaDZ0vDJNlaUSYyEXsgbaUH+itNTjCOgv77QTX2ImXj+kTctM19PQF2I1" +
- "0/NL0fjakvCgBTHKmk13a7jqB6cX3bysenHNrglHsgNGgeXQ7ggAq5fV/JQQ" +
- "T7rSxEtuwpbuHQnoVUZahOHVKy/a0uLr9iIh1A3y+yZTZaG505ZJMIAGCSqG" +
- "SIb3DQEHATAdBglghkgBZQMEAQIEENmkYNbDXiZxJWtq82qIRZKggAQgkOGr" +
- "1JcTsADStez1eY4+rO4DtyBIyUYQ3pilnbirfPkAAAAAAAAAAAAA");
-
-
- CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(envData);
-
- RecipientInformationStore recipients = ep.getRecipientInfos();
-
- assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyData);
- KeyFactory keyFact = KeyFactory.getInstance("RSA", BC);
- Key priKey = keyFact.generatePrivate(keySpec);
- byte[] data = Hex.decode("57616c6c6157616c6c6157617368696e67746f6e");
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- CMSTypedStream recData = recipient.getContentStream(priKey, BC);
-
- assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream())));
- }
- }
-
- private void verifyData(
- ByteArrayOutputStream encodedStream,
- String expectedOid,
- byte[] expectedData)
- throws Exception
- {
- CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(encodedStream.toByteArray());
- RecipientInformationStore recipients = ep.getRecipientInfos();
-
- assertEquals(ep.getEncryptionAlgOID(), expectedOid);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- CMSTypedStream recData = recipient.getContentStream(_reciKP.getPrivate(), BC);
-
- assertEquals(true, Arrays.equals(expectedData, CMSTestUtil.streamToByteArray(recData.getContentStream())));
- }
- }
-
- public void testKeyTransAES128BufferedStream()
- throws Exception
- {
- byte[] data = new byte[2000];
-
- for (int i = 0; i != 2000; i++)
- {
- data[i] = (byte)(i & 0xff);
- }
-
- //
- // unbuffered
- //
- CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream out = edGen.open(
- bOut, CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- for (int i = 0; i != 2000; i++)
- {
- out.write(data[i]);
- }
-
- out.close();
-
- verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data);
-
- int unbufferedLength = bOut.toByteArray().length;
-
- //
- // Using buffered output - should be == to unbuffered
- //
- edGen = new CMSEnvelopedDataStreamGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- bOut = new ByteArrayOutputStream();
-
- out = edGen.open(bOut, CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- BufferedOutputStream bfOut = new BufferedOutputStream(out, 300);
-
- for (int i = 0; i != 2000; i++)
- {
- bfOut.write(data[i]);
- }
-
- bfOut.close();
-
- verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data);
-
- assertTrue(bOut.toByteArray().length == unbufferedLength);
- }
-
- public void testKeyTransAES128Buffered()
- throws Exception
- {
- byte[] data = new byte[2000];
-
- for (int i = 0; i != 2000; i++)
- {
- data[i] = (byte)(i & 0xff);
- }
-
- //
- // unbuffered
- //
- CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream out = edGen.open(
- bOut, CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- for (int i = 0; i != 2000; i++)
- {
- out.write(data[i]);
- }
-
- out.close();
-
- verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data);
-
- int unbufferedLength = bOut.toByteArray().length;
-
- //
- // buffered - less than default of 1000
- //
- edGen = new CMSEnvelopedDataStreamGenerator();
-
- edGen.setBufferSize(300);
-
- edGen.addKeyTransRecipient(_reciCert);
-
- bOut = new ByteArrayOutputStream();
-
- out = edGen.open(bOut, CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- for (int i = 0; i != 2000; i++)
- {
- out.write(data[i]);
- }
-
- out.close();
-
- verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data);
-
- assertTrue(bOut.toByteArray().length > unbufferedLength);
- }
-
- public void testKeyTransAES128Der()
- throws Exception
- {
- byte[] data = new byte[2000];
-
- for (int i = 0; i != 2000; i++)
- {
- data[i] = (byte)(i & 0xff);
- }
-
- CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream out = edGen.open(
- bOut, CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- for (int i = 0; i != 2000; i++)
- {
- out.write(data[i]);
- }
-
- out.close();
-
- // convert to DER
- ASN1InputStream aIn = new ASN1InputStream(bOut.toByteArray());
-
- bOut.reset();
-
- DEROutputStream dOut = new DEROutputStream(bOut);
-
- dOut.writeObject(aIn.readObject());
-
- verifyData(bOut, CMSEnvelopedDataGenerator.AES128_CBC, data);
- }
-
- public void testKeyTransAES128Throughput()
- throws Exception
- {
- byte[] data = new byte[40001];
-
- for (int i = 0; i != data.length; i++)
- {
- data[i] = (byte)(i & 0xff);
- }
-
- //
- // buffered
- //
- CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator();
-
- edGen.setBufferSize(BUFFER_SIZE);
-
- edGen.addKeyTransRecipient(_reciCert);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream out = edGen.open(bOut, CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- for (int i = 0; i != data.length; i++)
- {
- out.write(data[i]);
- }
-
- out.close();
-
- CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray());
- RecipientInformationStore recipients = ep.getRecipientInfos();
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- CMSTypedStream recData = recipient.getContentStream(_reciKP.getPrivate(), BC);
-
- InputStream dataStream = recData.getContentStream();
- ByteArrayOutputStream dataOut = new ByteArrayOutputStream();
- int len;
- byte[] buf = new byte[BUFFER_SIZE];
- int count = 0;
-
- while (count != 10 && (len = dataStream.read(buf)) > 0)
- {
- assertEquals(buf.length, len);
-
- dataOut.write(buf);
- count++;
- }
-
- len = dataStream.read(buf);
- dataOut.write(buf, 0, len);
-
- assertEquals(true, Arrays.equals(data, dataOut.toByteArray()));
- }
- else
- {
- fail("recipient not found.");
- }
- }
-
- public void testKeyTransAES128()
- throws Exception
- {
- byte[] data = "WallaWallaWashington".getBytes();
-
- CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream out = edGen.open(
- bOut, CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- out.write(data);
-
- out.close();
-
- CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray());
-
- RecipientInformationStore recipients = ep.getRecipientInfos();
-
- assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- CMSTypedStream recData = recipient.getContentStream(_reciKP.getPrivate(), BC);
-
- assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream())));
- }
-
- ep.close();
- }
-
- public void testKeyTransCAST5SunJCE()
- throws Exception
- {
- if (Security.getProvider("SunJCE") == null)
- {
- return;
- }
-
- String version = System.getProperty("java.version");
- if (version.startsWith("1.4") || version.startsWith("1.3"))
- {
- return;
- }
-
- byte[] data = "WallaWallaWashington".getBytes();
-
- CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream out = edGen.open(
- bOut, CMSEnvelopedDataGenerator.CAST5_CBC, "SunJCE");
-
- out.write(data);
-
- out.close();
-
- CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray());
-
- RecipientInformationStore recipients = ep.getRecipientInfos();
-
- assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.CAST5_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- CMSTypedStream recData = recipient.getContentStream(_reciKP.getPrivate(), "SunJCE");
-
- assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream())));
- }
-
- ep.close();
- }
-
- public void testAESKEK()
- throws Exception
- {
- byte[] data = "WallaWallaWashington".getBytes();
- SecretKey kek = CMSTestUtil.makeAES192Key();
-
- CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator();
-
- byte[] kekId = new byte[] { 1, 2, 3, 4, 5 };
-
- edGen.addKEKRecipient(kek, kekId);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream out = edGen.open(
- bOut,
- CMSEnvelopedDataGenerator.DES_EDE3_CBC, BC);
- out.write(data);
-
- out.close();
-
- CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray());
-
- RecipientInformationStore recipients = ep.getRecipientInfos();
-
- assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), "2.16.840.1.101.3.4.1.25");
-
- CMSTypedStream recData = recipient.getContentStream(kek, BC);
-
- assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream())));
- }
-
- ep.close();
- }
-
- public void testTwoAESKEK()
- throws Exception
- {
- byte[] data = "WallaWallaWashington".getBytes();
- SecretKey kek1 = CMSTestUtil.makeAES192Key();
- SecretKey kek2 = CMSTestUtil.makeAES192Key();
-
- CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator();
-
- byte[] kekId1 = new byte[] { 1, 2, 3, 4, 5 };
- byte[] kekId2 = new byte[] { 5, 4, 3, 2, 1 };
-
- edGen.addKEKRecipient(kek1, kekId1);
- edGen.addKEKRecipient(kek2, kekId2);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream out = edGen.open(
- bOut,
- CMSEnvelopedDataGenerator.DES_EDE3_CBC, BC);
- out.write(data);
-
- out.close();
-
- CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray());
-
- RecipientInformationStore recipients = ep.getRecipientInfos();
-
- assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
-
- RecipientId recSel = new KEKRecipientId(kekId2);
-
- RecipientInformation recipient = recipients.get(recSel);
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), "2.16.840.1.101.3.4.1.25");
-
- CMSTypedStream recData = recipient.getContentStream(kek2, BC);
-
- assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream())));
-
- ep.close();
- }
-
- public void testECKeyAgree()
- throws Exception
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSEnvelopedDataStreamGenerator edGen = new CMSEnvelopedDataStreamGenerator();
-
- edGen.addKeyAgreementRecipient(CMSEnvelopedDataGenerator.ECDH_SHA1KDF, _origEcKP.getPrivate(), _origEcKP.getPublic(), _reciEcCert, CMSEnvelopedDataGenerator.AES128_WRAP, BC);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream out = edGen.open(
- bOut,
- CMSEnvelopedDataGenerator.AES128_CBC, BC);
- out.write(data);
-
- out.close();
-
- CMSEnvelopedDataParser ep = new CMSEnvelopedDataParser(bOut.toByteArray());
-
- RecipientInformationStore recipients = ep.getRecipientInfos();
-
- assertEquals(ep.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC);
-
- RecipientId recSel = new JceKeyAgreeRecipientId(_reciEcCert);
-
- RecipientInformation recipient = recipients.get(recSel);
-
- CMSTypedStream recData = recipient.getContentStream(_reciEcKP.getPrivate(), BC);
-
- assertEquals(true, Arrays.equals(data, CMSTestUtil.streamToByteArray(recData.getContentStream())));
-
- ep.close();
- }
-
- public void testOriginatorInfo()
- throws Exception
- {
- CMSEnvelopedDataParser env = new CMSEnvelopedDataParser(CMSSampleMessages.originatorMessage);
-
- env.getRecipientInfos();
-
- assertEquals(CMSEnvelopedDataGenerator.DES_EDE3_CBC, env.getEncryptionAlgOID());
- }
-
- public static Test suite()
- throws Exception
- {
- return new CMSTestSetup(new TestSuite(EnvelopedDataStreamTest.class));
- }
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/EnvelopedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/EnvelopedDataTest.java
deleted file mode 100644
index dea5d92..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/EnvelopedDataTest.java
+++ /dev/null
@@ -1,1002 +0,0 @@
-package org.bouncycastle.cms.test;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.Key;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.Security;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers;
-import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
-import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.cms.CMSEnvelopedData;
-import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
-import org.bouncycastle.cms.CMSException;
-import org.bouncycastle.cms.CMSPBEKey;
-import org.bouncycastle.cms.CMSProcessableByteArray;
-import org.bouncycastle.cms.KeyTransRecipientInformation;
-import org.bouncycastle.cms.PKCS5Scheme2PBEKey;
-import org.bouncycastle.cms.PKCS5Scheme2UTF8PBEKey;
-import org.bouncycastle.cms.PasswordRecipientInformation;
-import org.bouncycastle.cms.RecipientId;
-import org.bouncycastle.cms.RecipientInformation;
-import org.bouncycastle.cms.RecipientInformationStore;
-import org.bouncycastle.cms.jcajce.JceKeyAgreeRecipientId;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-
-public class EnvelopedDataTest
- extends TestCase
-{
- private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
-
- private static String _signDN;
- private static KeyPair _signKP;
- private static X509Certificate _signCert;
-
- private static String _origDN;
- private static KeyPair _origKP;
- private static X509Certificate _origCert;
-
- private static String _reciDN;
- private static String _reciDN2;
- private static KeyPair _reciKP;
- private static X509Certificate _reciCert;
-
- private static KeyPair _origEcKP;
- private static KeyPair _reciEcKP;
- private static X509Certificate _reciEcCert;
- private static KeyPair _reciEcKP2;
- private static X509Certificate _reciEcCert2;
-
- private static boolean _initialised = false;
-
- private byte[] oldKEK = Base64.decode(
- "MIAGCSqGSIb3DQEHA6CAMIACAQIxQaI/MD0CAQQwBwQFAQIDBAUwDQYJYIZIAWUDBAEFBQAEI"
- + "Fi2eHTPM4bQSjP4DUeDzJZLpfemW2gF1SPq7ZPHJi1mMIAGCSqGSIb3DQEHATAUBggqhkiG9w"
- + "0DBwQImtdGyUdGGt6ggAQYk9X9z01YFBkU7IlS3wmsKpm/zpZClTceAAAAAAAAAAAAAA==");
-
- private byte[] ecKeyAgreeMsgAES256 = Base64.decode(
- "MIAGCSqGSIb3DQEHA6CAMIACAQIxgcShgcECAQOgQ6FBMAsGByqGSM49AgEF"
- + "AAMyAAPdXlSTpub+qqno9hUGkUDl+S3/ABhPziIB5yGU4678tgOgU5CiKG9Z"
- + "kfnabIJ3nZYwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBLQUAMFswWTAtMCgx"
- + "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBCi/"
- + "rJRLbFwEVW6PcLLmojjW9lI/xGD7CfZzXrqXFw8iHaf3hTRau1gYMIAGCSqG"
- + "SIb3DQEHATAdBglghkgBZQMEASoEEMtCnKKPwccmyrbgeSIlA3qggAQQDLw8"
- + "pNJR97bPpj6baG99bQQQwhEDsoj5Xg1oOxojHVcYzAAAAAAAAAAAAAA=");
-
- private byte[] ecKeyAgreeMsgAES128 = Base64.decode(
- "MIAGCSqGSIb3DQEHA6CAMIACAQIxgbShgbECAQOgQ6FBMAsGByqGSM49AgEF"
- + "AAMyAAL01JLEgKvKh5rbxI/hOxs/9WEezMIsAbUaZM4l5tn3CzXAN505nr5d"
- + "LhrcurMK+tAwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBBQUAMEswSTAtMCgx"
- + "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBBhi"
- + "FLjc5g6aqDT3f8LomljOwl1WTrplUT8wgAYJKoZIhvcNAQcBMB0GCWCGSAFl"
- + "AwQBAgQQzXjms16Y69S/rB0EbHqRMaCABBAFmc/QdVW6LTKdEy97kaZzBBBa"
- + "fQuviUS03NycpojELx0bAAAAAAAAAAAAAA==");
-
- private byte[] ecKeyAgreeMsgDESEDE = Base64.decode(
- "MIAGCSqGSIb3DQEHA6CAMIACAQIxgcahgcMCAQOgQ6FBMAsGByqGSM49AgEF"
- + "AAMyAALIici6Nx1WN5f0ThH2A8ht9ovm0thpC5JK54t73E1RDzCifePaoQo0"
- + "xd6sUqoyGaYwHAYJK4EFEIZIPwACMA8GCyqGSIb3DQEJEAMGBQAwWzBZMC0w"
- + "KDETMBEGA1UEAxMKQWRtaW4tTURTRTERMA8GA1UEChMINEJDVC0ySUQCAQEE"
- + "KJuqZQ1NB1vXrKPOnb4TCpYOsdm6GscWdwAAZlm2EHMp444j0s55J9wwgAYJ"
- + "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAjwnsDMsafCrKCABBjyPvqFOVMKxxut"
- + "VfTx4fQlNGJN8S2ATRgECMcTQ/dsmeViAAAAAAAAAAAAAA==");
-
- private byte[] ecMQVKeyAgreeMsgAES128 = Base64.decode(
- "MIAGCSqGSIb3DQEHA6CAMIACAQIxgf2hgfoCAQOgQ6FBMAsGByqGSM49AgEF"
- + "AAMyAAPDKU+0H58tsjpoYmYCInMr/FayvCCkupebgsnpaGEB7qS9vzcNVUj6"
- + "mrnmiC2grpmhRwRFMEMwQTALBgcqhkjOPQIBBQADMgACZpD13z9c7DzRWx6S"
- + "0xdbq3S+EJ7vWO+YcHVjTD8NcQDcZcWASW899l1PkL936zsuMBoGCSuBBRCG"
- + "SD8AEDANBglghkgBZQMEAQUFADBLMEkwLTAoMRMwEQYDVQQDEwpBZG1pbi1N"
- + "RFNFMREwDwYDVQQKEwg0QkNULTJJRAIBAQQYFq58L71nyMK/70w3nc6zkkRy"
- + "RL7DHmpZMIAGCSqGSIb3DQEHATAdBglghkgBZQMEAQIEEDzRUpreBsZXWHBe"
- + "onxOtSmggAQQ7csAZXwT1lHUqoazoy8bhAQQq+9Zjj8iGdOWgyebbfj67QAA"
- + "AAAAAAAAAAA=");
-
-
- private byte[] ecKeyAgreeKey = Base64.decode(
- "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDC8vp7xVTbKSgYVU5Wc"
- + "hGkWbzaj+yUFETIWP1Dt7+WSpq3ikSPdl7PpHPqnPVZfoIWhZANiAgSYHTgxf+Dd"
- + "Tt84dUvuSKkFy3RhjxJmjwIscK6zbEUzKhcPQG2GHzXhWK5x1kov0I74XpGhVkya"
- + "ElH5K6SaOXiXAzcyNGggTOk4+ZFnz5Xl0pBje3zKxPhYu0SnCw7Pcqw=");
-
- private byte[] bobPrivRsaEncrypt = Base64.decode(
- "MIIChQIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKnhZ5g/OdVf"
- + "8qCTQV6meYmFyDVdmpFb+x0B2hlwJhcPvaUi0DWFbXqYZhRBXM+3twg7CcmR"
- + "uBlpN235ZR572akzJKN/O7uvRgGGNjQyywcDWVL8hYsxBLjMGAgUSOZPHPtd"
- + "YMTgXB9T039T2GkB8QX4enDRvoPGXzjPHCyqaqfrAgMBAAECgYBnzUhMmg2P"
- + "mMIbZf8ig5xt8KYGHbztpwOIlPIcaw+LNd4Ogngwy+e6alatd8brUXlweQqg"
- + "9P5F4Kmy9Bnah5jWMIR05PxZbMHGd9ypkdB8MKCixQheIXFD/A0HPfD6bRSe"
- + "TmPwF1h5HEuYHD09sBvf+iU7o8AsmAX2EAnYh9sDGQJBANDDIsbeopkYdo+N"
- + "vKZ11mY/1I1FUox29XLE6/BGmvE+XKpVC5va3Wtt+Pw7PAhDk7Vb/s7q/WiE"
- + "I2Kv8zHCueUCQQDQUfweIrdb7bWOAcjXq/JY1PeClPNTqBlFy2bKKBlf4hAr"
- + "84/sajB0+E0R9KfEILVHIdxJAfkKICnwJAiEYH2PAkA0umTJSChXdNdVUN5q"
- + "SO8bKlocSHseIVnDYDubl6nA7xhmqU5iUjiEzuUJiEiUacUgFJlaV/4jbOSn"
- + "I3vQgLeFAkEAni+zN5r7CwZdV+EJBqRd2ZCWBgVfJAZAcpw6iIWchw+dYhKI"
- + "FmioNRobQ+g4wJhprwMKSDIETukPj3d9NDAlBwJAVxhn1grStavCunrnVNqc"
- + "BU+B1O8BiR4yPWnLMcRSyFRVJQA7HCp8JlDV6abXd8vPFfXuC9WN7rOvTKF8"
- + "Y0ZB9qANMAsGA1UdDzEEAwIAEA==");
-
- private byte[] rfc4134ex5_1 = Base64.decode(
- "MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYD"
- + "VQQDEwdDYXJsUlNBAhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUA"
- + "BIGAC3EN5nGIiJi2lsGPcP2iJ97a4e8kbKQz36zg6Z2i0yx6zYC4mZ7mX7FB"
- + "s3IWg+f6KgCLx3M1eCbWx8+MDFbbpXadCDgO8/nUkUNYeNxJtuzubGgzoyEd"
- + "8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652jKKHRLFf02hosdR8wQwYJ"
- + "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8Z9P43LrY4O"
- + "xUk660cu1lXeCSFOSOpOJ7FuVyU=");
-
- private byte[] rfc4134ex5_2 = Base64.decode(
- "MIIBZQYJKoZIhvcNAQcDoIIBVjCCAVICAQIxggEAMIG9AgEAMCYwEjEQMA4G"
- + "A1UEAxMHQ2FybFJTQQIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQEF"
- + "AASBgJQmQojGi7Z4IP+CVypBmNFoCDoEp87khtgyff2N4SmqD3RxPx+8hbLQ"
- + "t9i3YcMwcap+aiOkyqjMalT03VUC0XBOGv+HYI3HBZm/aFzxoq+YOXAWs5xl"
- + "GerZwTOc9j6AYlK4qXvnztR5SQ8TBjlzytm4V7zg+TGrnGVNQBNw47Ewoj4C"
- + "AQQwDQQLTWFpbExpc3RSQzIwEAYLKoZIhvcNAQkQAwcCAToEGHcUr5MSJ/g9"
- + "HnJVHsQ6X56VcwYb+OfojTBJBgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgIC"
- + "AKAECJwE0hkuKlWhgCBeKNXhojuej3org9Lt7n+wWxOhnky5V50vSpoYRfRR"
- + "yw==");
-
- public EnvelopedDataTest()
- {
- }
-
- private static void init()
- throws Exception
- {
- if (!_initialised)
- {
- _initialised = true;
-
- _signDN = "O=Bouncy Castle, C=AU";
- _signKP = CMSTestUtil.makeKeyPair();
- _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN);
-
- _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
- _origKP = CMSTestUtil.makeKeyPair();
- _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN);
-
- _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
- _reciDN2 = "CN=Fred, OU=Sales, O=Bouncy Castle, C=AU";
- _reciKP = CMSTestUtil.makeKeyPair();
- _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN);
-
- _origEcKP = CMSTestUtil.makeEcDsaKeyPair();
- _reciEcKP = CMSTestUtil.makeEcDsaKeyPair();
- _reciEcCert = CMSTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN);
- _reciEcKP2 = CMSTestUtil.makeEcDsaKeyPair();
- _reciEcCert2 = CMSTestUtil.makeCertificate(_reciEcKP2, _reciDN2, _signKP, _signDN);
- }
- }
-
- public static void main(
- String args[])
- throws Exception
- {
- junit.textui.TestRunner.run(EnvelopedDataTest.suite());
- }
-
- public static Test suite()
- throws Exception
- {
- init();
-
- return new CMSTestSetup(new TestSuite(EnvelopedDataTest.class));
- }
-
- public void testKeyTrans()
- throws Exception
- {
- byte[] data = "WallaWallaWashington".getBytes();
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- CMSEnvelopedDataGenerator.DES_EDE3_CBC, BC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
-
- assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
-
- Collection c = recipients.getRecipients();
-
- assertEquals(1, c.size());
-
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), BC);
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- }
-
- public void testKeyTransCAST5SunJCE()
- throws Exception
- {
- if (Security.getProvider("SunJCE") == null)
- {
- return;
- }
-
- String version = System.getProperty("java.version");
- if (version.startsWith("1.4") || version.startsWith("1.3"))
- {
- return;
- }
-
- byte[] data = "WallaWallaWashington".getBytes();
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- CMSEnvelopedDataGenerator.CAST5_CBC, "SunJCE");
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.CAST5_CBC);
-
- Collection c = recipients.getRecipients();
-
- assertEquals(1, c.size());
-
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), "SunJCE");
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- }
-
- public void testKeyTransRC4()
- throws Exception
- {
- byte[] data = "WallaWallaBouncyCastle".getBytes();
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- "1.2.840.113549.3.4", BC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals(ed.getEncryptionAlgOID(), "1.2.840.113549.3.4");
-
- Collection c = recipients.getRecipients();
-
- assertEquals(1, c.size());
-
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), BC);
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- }
-
- public void testKeyTrans128RC4()
- throws Exception
- {
- byte[] data = "WallaWallaBouncyCastle".getBytes();
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- "1.2.840.113549.3.4", 128, BC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals(ed.getEncryptionAlgOID(), "1.2.840.113549.3.4");
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), BC);
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- public void testKeyTransODES()
- throws Exception
- {
- byte[] data = "WallaWallaBouncyCastle".getBytes();
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- "1.3.14.3.2.7", BC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals(ed.getEncryptionAlgOID(), "1.3.14.3.2.7");
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), BC);
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- public void testKeyTransSmallAES()
- throws Exception
- {
- byte[] data = new byte[] { 0, 1, 2, 3 };
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals(ed.getEncryptionAlgOID(),
- CMSEnvelopedDataGenerator.AES128_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), BC);
- assertEquals(true, Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- public void testKeyTransCAST5()
- throws Exception
- {
- tryKeyTrans(CMSEnvelopedDataGenerator.CAST5_CBC, new DERObjectIdentifier(CMSEnvelopedDataGenerator.CAST5_CBC), ASN1Sequence.class);
- }
-
- public void testKeyTransAES128()
- throws Exception
- {
- tryKeyTrans(CMSEnvelopedDataGenerator.AES128_CBC, NISTObjectIdentifiers.id_aes128_CBC, DEROctetString.class);
- }
-
- public void testKeyTransAES192()
- throws Exception
- {
- tryKeyTrans(CMSEnvelopedDataGenerator.AES192_CBC, NISTObjectIdentifiers.id_aes192_CBC, DEROctetString.class);
- }
-
- public void testKeyTransAES256()
- throws Exception
- {
- tryKeyTrans(CMSEnvelopedDataGenerator.AES256_CBC, NISTObjectIdentifiers.id_aes256_CBC, DEROctetString.class);
- }
-
- public void testKeyTransSEED()
- throws Exception
- {
- tryKeyTrans(CMSEnvelopedDataGenerator.SEED_CBC, KISAObjectIdentifiers.id_seedCBC, DEROctetString.class);
- }
-
- public void testKeyTransCamellia128()
- throws Exception
- {
- tryKeyTrans(CMSEnvelopedDataGenerator.CAMELLIA128_CBC, NTTObjectIdentifiers.id_camellia128_cbc, DEROctetString.class);
- }
-
- public void testKeyTransCamellia192()
- throws Exception
- {
- tryKeyTrans(CMSEnvelopedDataGenerator.CAMELLIA192_CBC, NTTObjectIdentifiers.id_camellia192_cbc, DEROctetString.class);
- }
-
- public void testKeyTransCamellia256()
- throws Exception
- {
- tryKeyTrans(CMSEnvelopedDataGenerator.CAMELLIA256_CBC, NTTObjectIdentifiers.id_camellia256_cbc, DEROctetString.class);
- }
-
- private void tryKeyTrans(String generatorOID, DERObjectIdentifier checkOID, Class asn1Params)
- throws Exception
- {
- byte[] data = "WallaWallaWashington".getBytes();
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addKeyTransRecipient(_reciCert);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- generatorOID, BC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals(checkOID.getId(), ed.getEncryptionAlgOID());
-
- if (asn1Params != null)
- {
- ASN1InputStream aIn = new ASN1InputStream(ed.getEncryptionAlgParams());
-
- assertTrue(asn1Params.isAssignableFrom(aIn.readObject().getClass()));
- }
-
- Collection c = recipients.getRecipients();
-
- assertEquals(1, c.size());
-
- Iterator it = c.iterator();
-
- if (!it.hasNext())
- {
- fail("no recipients found");
- }
-
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
-
- byte[] recData = recipient.getContent(_reciKP.getPrivate(), BC);
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- }
-
- public void testErrorneousKEK()
- throws Exception
- {
- byte[] data = "WallaWallaWashington".getBytes();
- SecretKey kek = new SecretKeySpec(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, "AES");
-
- CMSEnvelopedData ed = new CMSEnvelopedData(oldKEK);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(recipient.getKeyEncryptionAlgOID(), NISTObjectIdentifiers.id_aes128_wrap.getId());
-
- byte[] recData = recipient.getContent(kek, BC);
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- public void testDESKEK()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeDesede192Key(), new DERObjectIdentifier("1.2.840.113549.1.9.16.3.6"));
- }
- public void testRC2128KEK()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeRC2128Key(), new DERObjectIdentifier("1.2.840.113549.1.9.16.3.7"));
- }
-
- public void testAES128KEK()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeAESKey(128), NISTObjectIdentifiers.id_aes128_wrap);
- }
-
- public void testAES192KEK()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeAESKey(192), NISTObjectIdentifiers.id_aes192_wrap);
- }
-
- public void testAES256KEK()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeAESKey(256), NISTObjectIdentifiers.id_aes256_wrap);
- }
-
- public void testSEED128KEK()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeSEEDKey(), KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap);
- }
-
- public void testCamellia128KEK()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeCamelliaKey(128), NTTObjectIdentifiers.id_camellia128_wrap);
- }
-
- public void testCamellia192KEK()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeCamelliaKey(192), NTTObjectIdentifiers.id_camellia192_wrap);
- }
-
- public void testCamellia256KEK()
- throws Exception
- {
- tryKekAlgorithm(CMSTestUtil.makeCamelliaKey(256), NTTObjectIdentifiers.id_camellia256_wrap);
- }
-
- private void tryKekAlgorithm(SecretKey kek, DERObjectIdentifier algOid)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- byte[] data = "WallaWallaWashington".getBytes();
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- byte[] kekId = new byte[] { 1, 2, 3, 4, 5 };
-
- edGen.addKEKRecipient(kek, kekId);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- CMSEnvelopedDataGenerator.DES_EDE3_CBC, BC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals(algOid.getId(), recipient.getKeyEncryptionAlgOID());
-
- byte[] recData = recipient.getContent(kek, BC);
-
- assertTrue(Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- public void testECKeyAgree()
- throws Exception
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addKeyAgreementRecipient(CMSEnvelopedDataGenerator.ECDH_SHA1KDF,
- _origEcKP.getPrivate(), _origEcKP.getPublic(),
- _reciEcCert, CMSEnvelopedDataGenerator.AES128_WRAP, BC);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC);
- confirmNumberRecipients(recipients, 1);
- }
-
- public void testECMQVKeyAgree()
- throws Exception
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addKeyAgreementRecipient(CMSEnvelopedDataGenerator.ECMQV_SHA1KDF,
- _origEcKP.getPrivate(), _origEcKP.getPublic(),
- _reciEcCert, CMSEnvelopedDataGenerator.AES128_WRAP, BC);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC);
- confirmNumberRecipients(recipients, 1);
- }
-
- public void testECMQVKeyAgreeMultiple()
- throws Exception
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- ArrayList recipientCerts = new ArrayList();
- recipientCerts.add(_reciEcCert);
- recipientCerts.add(_reciEcCert2);
-
- edGen.addKeyAgreementRecipients(CMSEnvelopedDataGenerator.ECMQV_SHA1KDF,
- _origEcKP.getPrivate(), _origEcKP.getPublic(),
- recipientCerts, CMSEnvelopedDataGenerator.AES128_WRAP, BC);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.AES128_CBC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- confirmDataReceived(recipients, data, _reciEcCert, _reciEcKP.getPrivate(), BC);
- confirmDataReceived(recipients, data, _reciEcCert2, _reciEcKP2.getPrivate(), BC);
- confirmNumberRecipients(recipients, 2);
- }
-
- private static void confirmDataReceived(RecipientInformationStore recipients,
- byte[] expectedData, X509Certificate reciCert, PrivateKey reciPrivKey, String provider)
- throws CMSException, NoSuchProviderException, CertificateEncodingException, IOException
- {
- RecipientId rid = new JceKeyAgreeRecipientId(reciCert);
-
- RecipientInformation recipient = recipients.get(rid);
- assertNotNull(recipient);
-
- byte[] actualData = recipient.getContent(reciPrivKey, provider);
- assertEquals(true, Arrays.equals(expectedData, actualData));
- }
-
- private static void confirmNumberRecipients(RecipientInformationStore recipients, int count)
- {
- assertEquals(count, recipients.getRecipients().size());
- }
-
- public void testECKeyAgreeVectors()
- throws Exception
- {
- PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(ecKeyAgreeKey);
- KeyFactory fact = KeyFactory.getInstance("ECDH", BC);
- PrivateKey privKey = fact.generatePrivate(privSpec);
-
- verifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.42", ecKeyAgreeMsgAES256);
- verifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecKeyAgreeMsgAES128);
- verifyECKeyAgreeVectors(privKey, "1.2.840.113549.3.7", ecKeyAgreeMsgDESEDE);
- }
-
- public void testECMQVKeyAgreeVectors()
- throws Exception
- {
- PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(ecKeyAgreeKey);
- KeyFactory fact = KeyFactory.getInstance("ECDH", BC);
- PrivateKey privKey = fact.generatePrivate(privSpec);
-
- verifyECMQVKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecMQVKeyAgreeMsgAES128);
- }
-
- public void testPasswordAES256()
- throws Exception
- {
- passwordTest(CMSEnvelopedDataGenerator.AES256_CBC);
- passwordUTF8Test(CMSEnvelopedDataGenerator.AES256_CBC);
- }
-
- public void testPasswordDESEDE()
- throws Exception
- {
- passwordTest(CMSEnvelopedDataGenerator.DES_EDE3_CBC);
- passwordUTF8Test(CMSEnvelopedDataGenerator.DES_EDE3_CBC);
- }
-
- public void testRFC4134ex5_1()
- throws Exception
- {
- byte[] data = Hex.decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e");
-
- KeyFactory kFact = KeyFactory.getInstance("RSA", BC);
- Key key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt));
-
- CMSEnvelopedData ed = new CMSEnvelopedData(rfc4134ex5_1);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals("1.2.840.113549.3.7", ed.getEncryptionAlgOID());
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- byte[] recData = recipient.getContent(key, BC);
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- public void testRFC4134ex5_2()
- throws Exception
- {
- byte[] data = Hex.decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e");
-
- KeyFactory kFact = KeyFactory.getInstance("RSA", BC);
- Key key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt));
-
- CMSEnvelopedData ed = new CMSEnvelopedData(rfc4134ex5_2);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals("1.2.840.113549.3.2", ed.getEncryptionAlgOID());
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- while (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
- byte[] recData;
-
- if (recipient instanceof KeyTransRecipientInformation)
- {
- recData = recipient.getContent(key, BC);
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- }
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- public void testOriginatorInfo()
- throws Exception
- {
- CMSEnvelopedData env = new CMSEnvelopedData(CMSSampleMessages.originatorMessage);
-
- RecipientInformationStore recipients = env.getRecipientInfos();
-
- assertEquals(CMSEnvelopedDataGenerator.DES_EDE3_CBC, env.getEncryptionAlgOID());
-
- }
-
- private void passwordTest(String algorithm)
- throws Exception
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addPasswordRecipient(new PKCS5Scheme2PBEKey("password".toCharArray(), new byte[20], 5), algorithm);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals(ed.getEncryptionAlgOID(),
- CMSEnvelopedDataGenerator.AES128_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- PasswordRecipientInformation recipient = (PasswordRecipientInformation)it.next();
-
- CMSPBEKey key = new PKCS5Scheme2PBEKey("password".toCharArray(),
- recipient.getKeyDerivationAlgParameters(BC));
-
- byte[] recData = recipient.getContent(key, BC);
-
- assertEquals(true, Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
-
- //
- // try algorithm parameters constructor
- //
- it = c.iterator();
-
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- byte[] recData = recipient.getContent(new PKCS5Scheme2PBEKey("password".toCharArray(), ((PasswordRecipientInformation)recipient).getKeyDerivationAlgParameters(BC)), BC);
- assertEquals(true, Arrays.equals(data, recData));
- }
-
- private void passwordUTF8Test(String algorithm)
- throws Exception
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
-
- edGen.addPasswordRecipient(new PKCS5Scheme2UTF8PBEKey("abc\u5639\u563b".toCharArray(), new byte[20], 5), algorithm);
-
- CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- CMSEnvelopedDataGenerator.AES128_CBC, BC);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- assertEquals(ed.getEncryptionAlgOID(),
- CMSEnvelopedDataGenerator.AES128_CBC);
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- byte[] recData = recipient.getContent(new PKCS5Scheme2UTF8PBEKey("abc\u5639\u563b".toCharArray(), new byte[20], 5), BC);
- assertEquals(true, Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
-
- //
- // try algorithm parameters constructor
- //
- it = c.iterator();
-
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- byte[] recData = recipient.getContent(new PKCS5Scheme2UTF8PBEKey("abc\u5639\u563b".toCharArray(), ((PasswordRecipientInformation)recipient).getKeyDerivationAlgParameters(BC)), BC);
- assertEquals(true, Arrays.equals(data, recData));
- }
-
- private void verifyECKeyAgreeVectors(PrivateKey privKey, String wrapAlg, byte[] message)
- throws CMSException, GeneralSecurityException
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSEnvelopedData ed = new CMSEnvelopedData(message);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- assertEquals(wrapAlg, ed.getEncryptionAlgOID());
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals("1.3.133.16.840.63.0.2", recipient.getKeyEncryptionAlgOID());
-
- byte[] recData = recipient.getContent(privKey, BC);
-
- assertTrue(Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
- }
-
- private void verifyECMQVKeyAgreeVectors(PrivateKey privKey, String wrapAlg, byte[] message)
- throws CMSException, GeneralSecurityException
- {
- byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
-
- CMSEnvelopedData ed = new CMSEnvelopedData(message);
-
- RecipientInformationStore recipients = ed.getRecipientInfos();
-
- Collection c = recipients.getRecipients();
- Iterator it = c.iterator();
-
- assertEquals(wrapAlg, ed.getEncryptionAlgOID());
-
- if (it.hasNext())
- {
- RecipientInformation recipient = (RecipientInformation)it.next();
-
- assertEquals("1.3.133.16.840.63.0.16", recipient.getKeyEncryptionAlgOID());
-
- byte[] recData = recipient.getContent(privKey, BC);
-
- assertTrue(Arrays.equals(data, recData));
- }
- else
- {
- fail("no recipient found");
- }
- }
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/MiscDataStreamTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/MiscDataStreamTest.java
index 7efaec7..4a86cac 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/MiscDataStreamTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/MiscDataStreamTest.java
@@ -5,8 +5,6 @@ import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.security.KeyPair;
import java.security.MessageDigest;
-import java.security.cert.CertStore;
-import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
@@ -17,6 +15,9 @@ import java.util.List;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.jcajce.JcaCRLStore;
+import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.CMSCompressedDataStreamGenerator;
import org.bouncycastle.cms.CMSDigestedData;
import org.bouncycastle.cms.CMSSignedDataParser;
@@ -24,10 +25,16 @@ import org.bouncycastle.cms.CMSSignedDataStreamGenerator;
import org.bouncycastle.cms.CMSTypedStream;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
+import org.bouncycastle.cms.jcajce.JcaSignerInfoVerifierBuilder;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
import org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter;
+import org.bouncycastle.cms.jcajce.ZlibCompressor;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.DigestCalculatorProvider;
+import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Store;
import org.bouncycastle.util.encoders.Base64;
public class MiscDataStreamTest
@@ -74,6 +81,20 @@ public class MiscDataStreamTest
private static final JcaX509CertSelectorConverter selectorConverter = new JcaX509CertSelectorConverter();
+ private static final DigestCalculatorProvider digCalcProv;
+
+ static
+ {
+ try
+ {
+ digCalcProv = new JcaDigestCalculatorProviderBuilder().build();
+ }
+ catch (OperatorCreationException e)
+ {
+ throw new IllegalStateException("can't create default provider!!!");
+ }
+ }
+
public MiscDataStreamTest(String name)
{
super(name);
@@ -109,7 +130,7 @@ public class MiscDataStreamTest
private void verifySignatures(CMSSignedDataParser sp, byte[] contentDigest)
throws Exception
{
- CertStore certStore = sp.getCertificatesAndCRLs("Collection", BC);
+ Store certStore = sp.getCertificates();
SignerInformationStore signers = sp.getSignerInfos();
Collection c = signers.getSigners();
@@ -118,24 +139,18 @@ public class MiscDataStreamTest
while (it.hasNext())
{
SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certStore.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
+ Collection certCollection = certStore.getMatches(signer.getSID());
Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
+ X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
- assertEquals(true, signer.verify(cert, BC));
+ assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(cert)));
if (contentDigest != null)
{
assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest()));
}
}
-
- Collection certColl = certStore.getCertificates(null);
- Collection crlColl = certStore.getCRLs(null);
-
- assertEquals(certColl.size(), sp.getCertificates("Collection", BC).getMatches(null).size());
- assertEquals(crlColl.size(), sp.getCRLs("Collection", BC).getMatches(null).size());
}
private void verifySignatures(CMSSignedDataParser sp)
@@ -148,7 +163,7 @@ public class MiscDataStreamTest
throws Exception
{
CMSSignedDataParser sp;
- sp = new CMSSignedDataParser(bOut.toByteArray());
+ sp = new CMSSignedDataParser(digCalcProv, bOut.toByteArray());
sp.getSignedContent().drain();
@@ -160,14 +175,14 @@ public class MiscDataStreamTest
private void checkSigParseable(byte[] sig)
throws Exception
{
- CMSSignedDataParser sp = new CMSSignedDataParser(sig);
+ CMSSignedDataParser sp = new CMSSignedDataParser(digCalcProv, sig);
sp.getVersion();
CMSTypedStream sc = sp.getSignedContent();
if (sc != null)
{
sc.drain();
}
- sp.getCertificatesAndCRLs("Collection", BC);
+ sp.getCertificates();
sp.getSignerInfos();
sp.close();
}
@@ -176,28 +191,27 @@ public class MiscDataStreamTest
throws Exception
{
List certList = new ArrayList();
+ List crlList = new ArrayList();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
certList.add(_origCert);
certList.add(_signCert);
- certList.add(_signCrl);
- certList.add(_origCrl);
-
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
+ crlList.add(_signCrl);
+ crlList.add(_origCrl);
CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
+ gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", _origKP.getPrivate(), _origCert));
- gen.addCertificatesAndCRLs(certsAndCrls);
+ gen.addCertificates(new JcaCertStore(certList));
+ gen.addCRLs(new JcaCRLStore(crlList));
OutputStream sigOut = gen.open(bOut);
CMSCompressedDataStreamGenerator cGen = new CMSCompressedDataStreamGenerator();
- OutputStream cOut = cGen.open(sigOut, CMSCompressedDataStreamGenerator.ZLIB);
+ OutputStream cOut = cGen.open(sigOut, new ZlibCompressor());
cOut.write(TEST_MESSAGE.getBytes());
@@ -210,13 +224,13 @@ public class MiscDataStreamTest
// generate compressed stream
ByteArrayOutputStream cDataOut = new ByteArrayOutputStream();
- cOut = cGen.open(cDataOut, CMSCompressedDataStreamGenerator.ZLIB);
+ cOut = cGen.open(cDataOut, new ZlibCompressor());
cOut.write(TEST_MESSAGE.getBytes());
cOut.close();
- CMSSignedDataParser sp = new CMSSignedDataParser(
+ CMSSignedDataParser sp = new CMSSignedDataParser(digCalcProv,
new CMSTypedStream(new ByteArrayInputStream(cDataOut.toByteArray())), bOut.toByteArray());
sp.getSignedContent().drain();
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewEnvelopedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewEnvelopedDataTest.java
index c29293a..d95499d 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewEnvelopedDataTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewEnvelopedDataTest.java
@@ -10,6 +10,7 @@ import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
+import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import java.util.Collection;
@@ -17,6 +18,8 @@ import java.util.Hashtable;
import java.util.Iterator;
import javax.crypto.SecretKey;
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.PSource;
import javax.crypto.spec.SecretKeySpec;
import junit.framework.Test;
@@ -26,7 +29,6 @@ import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.DERUTF8String;
@@ -36,8 +38,10 @@ import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.RC2CBCParameter;
import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.X509Extension;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cms.CMSAlgorithm;
@@ -69,6 +73,7 @@ import org.bouncycastle.cms.jcajce.JcePasswordEnvelopedRecipient;
import org.bouncycastle.cms.jcajce.JcePasswordRecipientInfoGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.OutputEncryptor;
+import org.bouncycastle.operator.jcajce.JcaAlgorithmParametersConverter;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
@@ -88,7 +93,9 @@ public class NewEnvelopedDataTest
private static String _reciDN;
private static String _reciDN2;
private static KeyPair _reciKP;
+ private static KeyPair _reciOaepKP;
private static X509Certificate _reciCert;
+ private static X509Certificate _reciCertOaep;
private static KeyPair _origEcKP;
private static KeyPair _reciEcKP;
@@ -185,6 +192,32 @@ public class NewEnvelopedDataTest
+ "AKAECJwE0hkuKlWhgCBeKNXhojuej3org9Lt7n+wWxOhnky5V50vSpoYRfRR"
+ "yw==");
+ private byte[] tooShort3DES = Base64.decode(
+ "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKDA1C" +
+ "b3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBCjANBgkqhkiG9w0BAQEFAASB" +
+ "gJIM2QN0o6iv8Ux018pVCJ8js+ROV4t6+KoMwLJ4DzRKLU8XCAb9BS+crP+F" +
+ "ghNTxTpTX8TaxPrO4wV0USgVHu2SvFnxNaWZjBDVIyZI2HR4QkSTqFMhsUB2" +
+ "6CuZIWBZkhqQ6ruDfvn9UuBWVnfsBD4iryZ1idr713sDeVo5TyvTMIAGCSqG" +
+ "SIb3DQEHATAUBggqhkiG9w0DBwQIQq9e4+WB3CqggAQIwU4cOlmkWUcAAAAA" +
+ "AAAAAAAA");
+
+ private byte[] tooShort3DESKey = Base64.decode(
+ "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAODZDCj0nQdV" +
+ "f0GGeFsPjjvPx1Vem0V6IkJ4SzazGKfddk0pX58ZDCnG+S+OPiXmPDqValiu" +
+ "9FtNy2/r9rrf/6qtcVQJkfSJv9E5Y7HgI98L/Y9lKxZWsfRqu/SlYO5zx0Dc" +
+ "2rzDvvZRtrtaq0uuHXWJlbWda2L9S65sv/Le/zvjAgMBAAECgYEAnn+iGMTG" +
+ "ZMMaH6Cg+t/uTa9cPougPMuplt2hd3+sY7izihUeONK5RkHiqmlE2gaAcnOd" +
+ "McKysiIWxGC73mPEnsOObPkaFlneVb5CtjTaTMdptuLNEQkwvtKhuW2HnMra" +
+ "4afEgFZdll3FyRpvW/CDooe4Bppjd4aGn/Sr/o9nOzECQQD4QKLwZssuclji" +
+ "nD/8gU1CqGMMnGNogTMpHm1269HUOE7r1y3MuapUqSWsVhpuEQ8P/Tko0haJ" +
+ "jeZn2eWTbZu/AkEA591snui8FMeGvkRgvyMFNvXZWDEjsh+N74XEL1lykTgZ" +
+ "FQJ+cmThnrdM/8yj1dKkdASYrk5kFJ4PVE6CzDI43QJAFS22eNncJZc9u/9m" +
+ "eg0x4SjqYk4JMQYsripZXlbZ7Mfs+7O8xYVlYZmYjC5ATPmJlmyc7r2VjKCd" +
+ "cmilbEFikwJBAMh7yf8BaBdjitubzjeW9VxXaa37F01eQWD5PfBfHFP6uJ1V" +
+ "AbayCfAtuHN6I7OwJih3DPmyqJC3NrQECs67IjUCQAb4TfVE/2G1s66SGnb4" +
+ "no34BspoV/i4f0uLhJap84bTHcF/ZRSXCmQOCRGdSvQkXHeNPI5Lus6lOHuU" +
+ "vUDbQC8=");
+
public NewEnvelopedDataTest()
{
}
@@ -208,6 +241,7 @@ public class NewEnvelopedDataTest
_reciDN2 = "CN=Fred, OU=Sales, O=Bouncy Castle, C=AU";
_reciKP = CMSTestUtil.makeKeyPair();
_reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN);
+ _reciCertOaep = CMSTestUtil.makeOaepCertificate(_reciKP, _reciDN, _signKP, _signDN);
_origEcKP = CMSTestUtil.makeEcDsaKeyPair();
_reciEcKP = CMSTestUtil.makeEcDsaKeyPair();
@@ -291,7 +325,7 @@ public class NewEnvelopedDataTest
CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC));
- edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(X509Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), _reciCert.getPublicKey()).setProvider(BC));
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), _reciCert.getPublicKey()).setProvider(BC));
CMSEnvelopedData ed = edGen.generate(
new CMSProcessableByteArray(data),
@@ -329,6 +363,179 @@ public class NewEnvelopedDataTest
assertTrue(collection.iterator().next() instanceof RecipientInformation);
}
+ public void testKeyTransOAEPDefault()
+ throws Exception
+ {
+ byte[] data = "WallaWallaWashington".getBytes();
+
+ CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
+ JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
+
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert, paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, OAEPParameterSpec.DEFAULT)).setProvider(BC));
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, OAEPParameterSpec.DEFAULT), _reciCert.getPublicKey()).setProvider(BC));
+
+ CMSEnvelopedData ed = edGen.generate(
+ new CMSProcessableByteArray(data),
+ new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build());
+
+ RecipientInformationStore recipients = ed.getRecipientInfos();
+
+
+ assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
+
+ Collection c = recipients.getRecipients();
+
+ assertEquals(2, c.size());
+
+ Iterator it = c.iterator();
+
+ while (it.hasNext())
+ {
+ RecipientInformation recipient = (RecipientInformation)it.next();
+
+ assertEquals(PKCSObjectIdentifiers.id_RSAES_OAEP, recipient.getKeyEncryptionAlgorithm().getAlgorithm());
+
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC));
+
+ assertEquals(true, Arrays.equals(data, recData));
+ }
+
+ RecipientId id = new JceKeyTransRecipientId(_reciCert);
+
+ Collection collection = recipients.getRecipients(id);
+ if (collection.size() != 2)
+ {
+ fail("recipients not matched using general recipient ID.");
+ }
+ assertTrue(collection.iterator().next() instanceof RecipientInformation);
+ }
+
+ public void testKeyTransOAEPSHA1()
+ throws Exception
+ {
+ doTestKeyTransOAEPDefaultNamed("SHA-1");
+ }
+
+ public void testKeyTransOAEPSHA224()
+ throws Exception
+ {
+ doTestKeyTransOAEPDefaultNamed("SHA-224");
+ }
+
+ public void testKeyTransOAEPSHA256()
+ throws Exception
+ {
+ doTestKeyTransOAEPDefaultNamed("SHA-256");
+ }
+
+ public void testKeyTransOAEPSHA1AndSHA256()
+ throws Exception
+ {
+ doTestKeyTransOAEPDefaultNamed("SHA-1", "SHA-256");
+ }
+
+ private void doTestKeyTransOAEPDefaultNamed(String digest)
+ throws Exception
+ {
+ doTestKeyTransOAEPDefaultNamed(digest, digest);
+ }
+
+ private void doTestKeyTransOAEPDefaultNamed(String digest, String mgfDigest)
+ throws Exception
+ {
+ byte[] data = "WallaWallaWashington".getBytes();
+
+ CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
+ JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
+
+ OAEPParameterSpec oaepSpec = new OAEPParameterSpec(digest, "MGF1", new MGF1ParameterSpec(mgfDigest), new PSource.PSpecified(new byte[]{1, 2, 3, 4, 5}));
+ AlgorithmIdentifier oaepAlgId = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepSpec);
+
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert, oaepAlgId).setProvider(BC));
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), oaepAlgId, _reciCert.getPublicKey()).setProvider(BC));
+
+ CMSEnvelopedData ed = edGen.generate(
+ new CMSProcessableByteArray(data),
+ new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build());
+
+ RecipientInformationStore recipients = ed.getRecipientInfos();
+
+
+ assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
+
+ Collection c = recipients.getRecipients();
+
+ assertEquals(2, c.size());
+
+ Iterator it = c.iterator();
+
+ while (it.hasNext())
+ {
+ RecipientInformation recipient = (RecipientInformation)it.next();
+
+ assertEquals(PKCSObjectIdentifiers.id_RSAES_OAEP, recipient.getKeyEncryptionAlgorithm().getAlgorithm());
+
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC));
+
+ assertEquals(true, Arrays.equals(data, recData));
+ }
+
+ RecipientId id = new JceKeyTransRecipientId(_reciCert);
+
+ Collection collection = recipients.getRecipients(id);
+ if (collection.size() != 2)
+ {
+ fail("recipients not matched using general recipient ID.");
+ }
+ assertTrue(collection.iterator().next() instanceof RecipientInformation);
+ }
+
+ public void testKeyTransOAEPInCert()
+ throws Exception
+ {
+ byte[] data = "WallaWallaWashington".getBytes();
+
+ CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
+
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCertOaep).setProvider(BC));
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCertOaep.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), _reciCertOaep.getPublicKey()).setProvider(BC));
+
+ CMSEnvelopedData ed = edGen.generate(
+ new CMSProcessableByteArray(data),
+ new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build());
+
+ RecipientInformationStore recipients = ed.getRecipientInfos();
+
+
+ assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
+
+ Collection c = recipients.getRecipients();
+
+ assertEquals(2, c.size());
+
+ Iterator it = c.iterator();
+
+ while (it.hasNext())
+ {
+ RecipientInformation recipient = (RecipientInformation)it.next();
+
+ assertEquals(PKCSObjectIdentifiers.id_RSAES_OAEP, recipient.getKeyEncryptionAlgorithm().getAlgorithm());
+
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC));
+
+ assertEquals(true, Arrays.equals(data, recData));
+ }
+
+ RecipientId id = new JceKeyTransRecipientId(_reciCertOaep);
+
+ Collection collection = recipients.getRecipients(id);
+ if (collection.size() != 2)
+ {
+ fail("recipients not matched using general recipient ID.");
+ }
+ assertTrue(collection.iterator().next() instanceof RecipientInformation);
+ }
+
public void testKeyTransWithAlgMapping()
throws Exception
{
@@ -385,7 +592,7 @@ public class NewEnvelopedDataTest
edGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate());
edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC));
- edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(X509Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), _reciCert.getPublicKey()).setProvider(BC));
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), _reciCert.getPublicKey()).setProvider(BC));
CMSEnvelopedData ed = edGen.generate(
new CMSProcessableByteArray(data),
@@ -425,6 +632,42 @@ public class NewEnvelopedDataTest
assertTrue(collection.iterator().next() instanceof RecipientInformation);
}
+ public void testKeyTransRC2bit40()
+ throws Exception
+ {
+ byte[] data = "WallaWallaBouncyCastle".getBytes();
+
+ CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
+
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC));
+
+ CMSEnvelopedData ed = edGen.generate(
+ new CMSProcessableByteArray(data),
+ new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC, 40).setProvider(BC).build());
+
+ RecipientInformationStore recipients = ed.getRecipientInfos();
+
+ assertEquals(ed.getContentEncryptionAlgorithm().getAlgorithm(), CMSAlgorithm.RC2_CBC);
+
+ RC2CBCParameter rc2P = RC2CBCParameter.getInstance(ed.getContentEncryptionAlgorithm().getParameters());
+ assertEquals(160, rc2P.getRC2ParameterVersion().intValue());
+
+ Collection c = recipients.getRecipients();
+
+ assertEquals(1, c.size());
+
+ Iterator it = c.iterator();
+
+ while (it.hasNext())
+ {
+ RecipientInformation recipient = (RecipientInformation)it.next();
+
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC));
+
+ assertEquals(true, Arrays.equals(data, recData));
+ }
+ }
+
public void testKeyTransRC4()
throws Exception
{
@@ -594,6 +837,44 @@ public class NewEnvelopedDataTest
}
}
+ public void testKeyTransDESEDE3Short()
+ throws Exception
+ {
+ byte[] data = new byte[] { 0, 1, 2, 3 };
+ KeyFactory kf = KeyFactory.getInstance("RSA", BC);
+ PrivateKey kPriv = kf.generatePrivate(new PKCS8EncodedKeySpec(tooShort3DESKey));
+
+ CMSEnvelopedData ed = new CMSEnvelopedData(tooShort3DES);
+
+ RecipientInformationStore recipients = ed.getRecipientInfos();
+
+ assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
+
+ Collection c = recipients.getRecipients();
+ Iterator it = c.iterator();
+
+ if (it.hasNext())
+ {
+ RecipientInformation recipient = (RecipientInformation)it.next();
+ try
+ {
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(kPriv).setKeySizeValidation(true).setProvider(BC));
+ fail("invalid 3DES-EDE key not picked up");
+ }
+ catch (CMSException e)
+ {
+ assertEquals("Expected key size for algorithm OID not found in recipient.", e.getMessage());
+ }
+
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(kPriv).setKeySizeValidation(false).setProvider(BC));
+ assertEquals(true, Arrays.equals(data, recData));
+ }
+ else
+ {
+ fail("no recipient found");
+ }
+ }
+
public void testKeyTransDESEDE3Light()
throws Exception
{
@@ -609,8 +890,7 @@ public class NewEnvelopedDataTest
RecipientInformationStore recipients = ed.getRecipientInfos();
- assertEquals(ed.getEncryptionAlgOID(),
- CMSEnvelopedDataGenerator.DES_EDE3_CBC);
+ assertEquals(ed.getEncryptionAlgOID(), CMSEnvelopedDataGenerator.DES_EDE3_CBC);
Collection c = recipients.getRecipients();
Iterator it = c.iterator();
@@ -619,7 +899,7 @@ public class NewEnvelopedDataTest
{
RecipientInformation recipient = (RecipientInformation)it.next();
- byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC));
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setKeySizeValidation(true).setProvider(BC));
assertEquals(true, Arrays.equals(data, recData));
}
else
@@ -725,7 +1005,7 @@ public class NewEnvelopedDataTest
assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
- byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC));
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setKeySizeValidation(true).setProvider(BC));
assertEquals(true, Arrays.equals(data, recData));
}
@@ -765,12 +1045,12 @@ public class NewEnvelopedDataTest
public void testDESKEK()
throws Exception
{
- tryKekAlgorithm(CMSTestUtil.makeDesede192Key(), new DERObjectIdentifier("1.2.840.113549.1.9.16.3.6"));
+ tryKekAlgorithm(CMSTestUtil.makeDesede192Key(), new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.6"));
}
public void testRC2128KEK()
throws Exception
{
- tryKekAlgorithm(CMSTestUtil.makeRC2128Key(), new DERObjectIdentifier("1.2.840.113549.1.9.16.3.7"));
+ tryKekAlgorithm(CMSTestUtil.makeRC2128Key(), new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7"));
}
public void testAES128KEK()
@@ -815,7 +1095,7 @@ public class NewEnvelopedDataTest
tryKekAlgorithm(CMSTestUtil.makeCamelliaKey(256), NTTObjectIdentifiers.id_camellia256_wrap);
}
- private void tryKekAlgorithm(SecretKey kek, DERObjectIdentifier algOid)
+ private void tryKekAlgorithm(SecretKey kek, ASN1ObjectIdentifier algOid)
throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
{
byte[] data = "WallaWallaWashington".getBytes();
@@ -842,7 +1122,7 @@ public class NewEnvelopedDataTest
assertEquals(algOid.getId(), recipient.getKeyEncryptionAlgOID());
- byte[] recData = recipient.getContent(new JceKEKEnvelopedRecipient(kek).setProvider(BC));
+ byte[] recData = recipient.getContent(new JceKEKEnvelopedRecipient(kek).setKeySizeValidation(true).setProvider(BC));
assertTrue(Arrays.equals(data, recData));
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java
index 9d9e645..8a92cae 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java
@@ -33,7 +33,6 @@ import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCRLStore;
import org.bouncycastle.cert.jcajce.JcaCertStore;
-import org.bouncycastle.cert.jcajce.JcaX509AttributeCertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CRLHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cert.ocsp.OCSPResp;
@@ -957,7 +956,7 @@ public class NewSignedDataStreamTest
gen.addCertificates(certs);
- X509AttributeCertificateHolder attrCert = new JcaX509AttributeCertificateHolder(CMSTestUtil.getAttributeCertificate());
+ X509AttributeCertificateHolder attrCert = CMSTestUtil.getAttributeCertificate();
Store store = new CollectionStore(Collections.singleton(attrCert));
@@ -1283,6 +1282,25 @@ public class NewSignedDataStreamTest
assertEquals(new JcaX509CertificateHolder(_origCert), it.next());
}
+ public void testCertsOnly()
+ throws Exception
+ {
+ List certList = new ArrayList();
+ certList.add(_origCert);
+ certList.add(_signCert);
+
+ Store certs = new JcaCertStore(certList);
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
+ gen.addCertificates(certs);
+
+ gen.open(bOut).close();
+
+ checkSigParseable(bOut.toByteArray());
+ }
+
public static Test suite()
throws Exception
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataTest.java
index 9317b18..7df2c13 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/NewSignedDataTest.java
@@ -6,7 +6,6 @@ import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.Security;
-import java.security.cert.CertificateException;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
@@ -39,7 +38,6 @@ import org.bouncycastle.cert.X509AttributeCertificateHolder;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCRLStore;
import org.bouncycastle.cert.jcajce.JcaCertStore;
-import org.bouncycastle.cert.jcajce.JcaX509AttributeCertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CRLHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cert.ocsp.OCSPResp;
@@ -57,6 +55,7 @@ import org.bouncycastle.cms.SignerInfoGeneratorBuilder;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.cms.SignerInformationVerifier;
+import org.bouncycastle.cms.SignerInformationVerifierProvider;
import org.bouncycastle.cms.bc.BcRSASignerInfoVerifierBuilder;
import org.bouncycastle.cms.jcajce.JcaSignerId;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
@@ -64,7 +63,6 @@ import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
-import org.bouncycastle.cms.SignerInformationVerifierProvider;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
@@ -1663,7 +1661,7 @@ public class NewSignedDataTest
gen.addCertificates(certs);
- X509AttributeCertificateHolder attrCert = new JcaX509AttributeCertificateHolder(CMSTestUtil.getAttributeCertificate());
+ X509AttributeCertificateHolder attrCert = CMSTestUtil.getAttributeCertificate();
List attrList = new ArrayList();
attrList.add(new X509AttributeCertificateHolder(attrCert.getEncoded()));
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/NullProviderTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/NullProviderTest.java
index 4cfc498..a97b21c 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/NullProviderTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/NullProviderTest.java
@@ -12,11 +12,8 @@ import java.security.MessageDigest;
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.cert.CertStore;
-import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
@@ -29,23 +26,35 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.X509Name;
+import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
-import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSSignedDataParser;
import org.bouncycastle.cms.CMSSignedDataStreamGenerator;
+import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.CMSTypedStream;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.RecipientInformationStore;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
+import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter;
+import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
+import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
+import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
+import org.bouncycastle.operator.DigestCalculatorProvider;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.bouncycastle.util.CollectionStore;
+import org.bouncycastle.util.Store;
import org.bouncycastle.x509.X509V3CertificateGenerator;
public class NullProviderTest
@@ -75,27 +84,26 @@ public class NullProviderTest
throws Exception
{
List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes());
+ CMSTypedData msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes());
- certList.add(keyCert);
+ certList.add(new X509CertificateHolder(keyCert.getEncoded()));
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList));
+ DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().build();
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
- gen.addSigner(keyPair.getPrivate(), keyCert, CMSSignedDataGenerator.DIGEST_SHA1);
+ gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").build(keyPair.getPrivate()), keyCert));
- gen.addCertificatesAndCRLs(certsAndCrls);
+ gen.addCertificates(new CollectionStore(certList));
- CMSSignedData s = gen.generate(msg, true, (Provider)null);
+ CMSSignedData s = gen.generate(msg, true);
ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded());
ASN1InputStream aIn = new ASN1InputStream(bIn);
s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
- certsAndCrls = s.getCertificatesAndCRLs("Collection", (String)null); // make sure String works as well
+ Store certsAndCrls = s.getCertificates();
SignerInformationStore signers = s.getSignerInfos();
Collection c = signers.getSigners();
@@ -103,13 +111,12 @@ public class NullProviderTest
while (it.hasNext())
{
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certsAndCrls.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
+ SignerInformation signer = (SignerInformation)it.next();
+ Collection certCollection = certsAndCrls.getMatches(signer.getSID());
+ Iterator certIt = certCollection.iterator();
+ X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, (Provider)null));
+ assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert)));
}
}
@@ -119,16 +126,15 @@ public class NullProviderTest
List certList = new ArrayList();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- certList.add(keyCert);
+ certList.add(new X509CertificateHolder(keyCert.getEncoded()));
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList));
+ DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().build();
CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
- gen.addSigner(keyPair.getPrivate(), keyCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, (String)null);
+ gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").build(keyPair.getPrivate()), keyCert));
- gen.addCertificatesAndCRLs(certsAndCrls);
+ gen.addCertificates(new CollectionStore(certList));
OutputStream sigOut = gen.open(bOut);
@@ -136,7 +142,7 @@ public class NullProviderTest
sigOut.close();
- CMSSignedDataParser sp = new CMSSignedDataParser(
+ CMSSignedDataParser sp = new CMSSignedDataParser(digCalcProv,
new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray());
sp.getSignedContent().drain();
@@ -147,7 +153,7 @@ public class NullProviderTest
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] contentDigest = md.digest(TEST_MESSAGE.getBytes());
- CertStore certStore = sp.getCertificatesAndCRLs("Collection", (String)null);
+ Store certStore = sp.getCertificates();
SignerInformationStore signers = sp.getSignerInfos();
Collection c = signers.getSigners();
@@ -156,12 +162,12 @@ public class NullProviderTest
while (it.hasNext())
{
SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certStore.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
+ Collection certCollection = certStore.getMatches(signer.getSID());
Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
+ X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
- assertEquals(true, signer.verify(cert, (Provider)null));
+ assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert)));
if (contentDigest != null)
{
@@ -201,15 +207,14 @@ public class NullProviderTest
CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
- edGen.addKeyTransRecipient(keyCert);
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(keyCert));
CMSEnvelopedData ed = edGen.generate(
- new CMSProcessableByteArray(data),
- algorithm, (String)null);
+ new CMSProcessableByteArray(data),
+ new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(algorithm)).build());
RecipientInformationStore recipients = ed.getRecipientInfos();
-
assertEquals(ed.getEncryptionAlgOID(), algorithm);
Collection c = recipients.getRecipients();
@@ -224,7 +229,7 @@ public class NullProviderTest
assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
- byte[] recData = recipient.getContent(keyPair.getPrivate(), (String)null);
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(keyPair.getPrivate()));
assertEquals(true, Arrays.equals(data, recData));
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/Rfc4134Test.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/Rfc4134Test.java
index f36b7b7..2f59702 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/Rfc4134Test.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/Rfc4134Test.java
@@ -10,7 +10,6 @@ import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
-import java.security.cert.CertStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.DSAParams;
@@ -33,6 +32,8 @@ import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.CMSAttributes;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
import org.bouncycastle.cms.CMSEnvelopedDataParser;
@@ -45,8 +46,14 @@ import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.RecipientInformationStore;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
+import org.bouncycastle.cms.jcajce.JcaSignerInfoVerifierBuilder;
import org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter;
+import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.DigestCalculatorProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.bouncycastle.util.Store;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.io.Streams;
@@ -60,6 +67,19 @@ public class Rfc4134Test
private static byte[] sha1 = Hex.decode("406aec085279ba6e16022d9e0629c0229687dd48");
private static final JcaX509CertSelectorConverter selectorConverter = new JcaX509CertSelectorConverter();
+ private static final DigestCalculatorProvider digCalcProv;
+
+ static
+ {
+ try
+ {
+ digCalcProv = new JcaDigestCalculatorProviderBuilder().build();
+ }
+ catch (OperatorCreationException e)
+ {
+ throw new IllegalStateException("can't create default provider!!!");
+ }
+ }
public Rfc4134Test(String name)
{
@@ -87,7 +107,7 @@ public class Rfc4134Test
verifySignatures(signedData);
- CMSSignedDataParser parser = new CMSSignedDataParser(data);
+ CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data);
verifySignatures(parser);
}
@@ -100,7 +120,7 @@ public class Rfc4134Test
verifySignatures(signedData);
- CMSSignedDataParser parser = new CMSSignedDataParser(data);
+ CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data);
verifySignatures(parser);
}
@@ -113,7 +133,7 @@ public class Rfc4134Test
verifySignatures(signedData, sha1);
- CMSSignedDataParser parser = new CMSSignedDataParser(
+ CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv,
new CMSTypedStream(new ByteArrayInputStream(exContent)),
data);
@@ -131,7 +151,7 @@ public class Rfc4134Test
verifySignerInfo4_4(getFirstSignerInfo(signedData.getSignerInfos()), counterSigCert);
- CMSSignedDataParser parser = new CMSSignedDataParser(data);
+ CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data);
verifySignatures(parser);
@@ -146,7 +166,7 @@ public class Rfc4134Test
verifySignatures(signedData);
- CMSSignedDataParser parser = new CMSSignedDataParser(data);
+ CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data);
verifySignatures(parser);
}
@@ -159,7 +179,7 @@ public class Rfc4134Test
verifySignatures(signedData);
- CMSSignedDataParser parser = new CMSSignedDataParser(data);
+ CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data);
verifySignatures(parser);
}
@@ -172,7 +192,7 @@ public class Rfc4134Test
verifySignatures(signedData);
- CMSSignedDataParser parser = new CMSSignedDataParser(data);
+ CMSSignedDataParser parser = new CMSSignedDataParser(digCalcProv, data);
verifySignatures(parser);
}
@@ -260,7 +280,7 @@ public class Rfc4134Test
{
assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
- byte[] recData = recipient.getContent(privKey, BC);
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(privKey).setProvider(BC));
assertEquals(true, Arrays.equals(exContent, recData));
}
@@ -286,7 +306,7 @@ public class Rfc4134Test
CertificateFactory certFact = CertificateFactory.getInstance("X.509", BC);
X509Certificate cert = (X509Certificate)certFact.generateCertificate(new ByteArrayInputStream(certificate));
- assertTrue(csi.verify(cert, BC));
+ assertTrue(csi.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(cert)));
}
private void verifyContentHint(SignerInformation signInfo)
@@ -308,7 +328,7 @@ public class Rfc4134Test
private void verifySignatures(CMSSignedData s, byte[] contentDigest)
throws Exception
{
- CertStore certStore = s.getCertificatesAndCRLs("Collection", BC);
+ Store certStore = s.getCertificates();
SignerInformationStore signers = s.getSignerInfos();
Collection c = signers.getSigners();
@@ -317,10 +337,10 @@ public class Rfc4134Test
while (it.hasNext())
{
SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certStore.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
+ Collection certCollection = certStore.getMatches(signer.getSID());
Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
+ X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
verifySigner(signer, cert);
@@ -329,12 +349,6 @@ public class Rfc4134Test
assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest()));
}
}
-
- Collection certColl = certStore.getCertificates(null);
- Collection crlColl = certStore.getCRLs(null);
-
- assertEquals(certColl.size(), s.getCertificates("Collection", BC).getMatches(null).size());
- assertEquals(crlColl.size(), s.getCRLs("Collection", BC).getMatches(null).size());
}
private void verifySignatures(CMSSignedData s)
@@ -352,7 +366,7 @@ public class Rfc4134Test
sc.drain();
}
- CertStore certs = sp.getCertificatesAndCRLs("Collection", BC);
+ Store certs = sp.getCertificates();
SignerInformationStore signers = sp.getSignerInfos();
Collection c = signers.getSigners();
@@ -361,34 +375,35 @@ public class Rfc4134Test
while (it.hasNext())
{
SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certs.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
+ Collection certCollection = certs.getMatches(signer.getSID());
Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
+ X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
verifySigner(signer, cert);
}
}
- private void verifySigner(SignerInformation signer, X509Certificate cert)
+ private void verifySigner(SignerInformation signer, X509CertificateHolder certHolder)
throws Exception
{
+ X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
if (cert.getPublicKey() instanceof DSAPublicKey)
{
DSAPublicKey key = (DSAPublicKey)cert.getPublicKey();
if (key.getParams() == null)
{
- assertEquals(true, signer.verify(getInheritedKey(key), BC));
+ assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(getInheritedKey(key))));
}
else
{
- assertEquals(true, signer.verify(cert, BC));
+ assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(cert)));
}
}
else
{
- assertEquals(true, signer.verify(cert, BC));
+ assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(digCalcProv).setProvider(BC).build(cert)));
}
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/SignedDataStreamTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/SignedDataStreamTest.java
deleted file mode 100644
index 39b50da..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/SignedDataStreamTest.java
+++ /dev/null
@@ -1,1158 +0,0 @@
-package org.bouncycastle.cms.test;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.security.InvalidKeyException;
-import java.security.KeyPair;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertStore;
-import java.security.cert.CollectionCertStoreParameters;
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.cms.Attribute;
-import org.bouncycastle.asn1.cms.AttributeTable;
-import org.bouncycastle.asn1.cms.CMSAttributes;
-import org.bouncycastle.cms.CMSAttributeTableGenerator;
-import org.bouncycastle.cms.CMSProcessable;
-import org.bouncycastle.cms.CMSProcessableByteArray;
-import org.bouncycastle.cms.CMSSignedData;
-import org.bouncycastle.cms.CMSSignedDataGenerator;
-import org.bouncycastle.cms.CMSSignedDataParser;
-import org.bouncycastle.cms.CMSSignedDataStreamGenerator;
-import org.bouncycastle.cms.CMSSignedGenerator;
-import org.bouncycastle.cms.CMSTypedStream;
-import org.bouncycastle.cms.DefaultSignedAttributeTableGenerator;
-import org.bouncycastle.cms.SignerInformation;
-import org.bouncycastle.cms.SignerInformationStore;
-import org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.x509.X509AttributeCertificate;
-import org.bouncycastle.x509.X509CollectionStoreParameters;
-import org.bouncycastle.x509.X509Store;
-
-public class SignedDataStreamTest
- extends TestCase
-{
- private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
-
- private static final String TEST_MESSAGE = "Hello World!";
- private static String _signDN;
- private static KeyPair _signKP;
- private static X509Certificate _signCert;
-
- private static String _origDN;
- private static KeyPair _origKP;
- private static X509Certificate _origCert;
-
- private static String _reciDN;
- private static KeyPair _reciKP;
- private static X509Certificate _reciCert;
-
- private static KeyPair _origDsaKP;
- private static X509Certificate _origDsaCert;
-
- private static X509CRL _signCrl;
- private static X509CRL _origCrl;
-
- private static boolean _initialised = false;
-
- private static final JcaX509CertSelectorConverter selectorConverter = new JcaX509CertSelectorConverter();
-
- public SignedDataStreamTest(String name)
- {
- super(name);
- }
-
- private static void init()
- throws Exception
- {
- if (!_initialised)
- {
- _initialised = true;
-
- _signDN = "O=Bouncy Castle, C=AU";
- _signKP = CMSTestUtil.makeKeyPair();
- _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN);
-
- _origDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
- _origKP = CMSTestUtil.makeKeyPair();
- _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN);
-
- _origDsaKP = CMSTestUtil.makeDsaKeyPair();
- _origDsaCert = CMSTestUtil.makeCertificate(_origDsaKP, _origDN, _signKP, _signDN);
-
- _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
- _reciKP = CMSTestUtil.makeKeyPair();
- _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN);
-
- _signCrl = CMSTestUtil.makeCrl(_signKP);
- _origCrl = CMSTestUtil.makeCrl(_origKP);
- }
- }
-
- private void verifySignatures(CMSSignedDataParser sp, byte[] contentDigest)
- throws Exception
- {
- CertStore certStore = sp.getCertificatesAndCRLs("Collection", BC);
- SignerInformationStore signers = sp.getSignerInfos();
-
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certStore.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
-
- if (contentDigest != null)
- {
- assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest()));
- }
- }
-
- Collection certColl = certStore.getCertificates(null);
- Collection crlColl = certStore.getCRLs(null);
-
- assertEquals(certColl.size(), sp.getCertificates("Collection", BC).getMatches(null).size());
- assertEquals(crlColl.size(), sp.getCRLs("Collection", BC).getMatches(null).size());
- }
-
- private void verifySignatures(CMSSignedDataParser sp)
- throws Exception
- {
- verifySignatures(sp, null);
- }
-
- private void verifyEncodedData(ByteArrayOutputStream bOut)
- throws Exception
- {
- CMSSignedDataParser sp;
- sp = new CMSSignedDataParser(bOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
-
- sp.close();
- }
-
- private void checkSigParseable(byte[] sig)
- throws Exception
- {
- CMSSignedDataParser sp = new CMSSignedDataParser(sig);
- sp.getVersion();
- CMSTypedStream sc = sp.getSignedContent();
- if (sc != null)
- {
- sc.drain();
- }
- sp.getCertificatesAndCRLs("Collection", BC);
- sp.getSignerInfos();
- sp.close();
- }
-
- public void testEarlyInvalidKeyException() throws Exception
- {
- try
- {
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
- gen.addSigner( _origKP.getPrivate(), _origCert,
- "DSA", // DOESN'T MATCH KEY ALG
- CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- fail("Expected InvalidKeyException in addSigner");
- }
- catch (InvalidKeyException e)
- {
- // Ignore
- }
- }
-
- public void testEarlyNoSuchAlgorithmException() throws Exception
- {
- try
- {
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
- gen.addSigner( _origKP.getPrivate(), _origCert,
- CMSSignedDataStreamGenerator.DIGEST_SHA1, // BAD OID!
- CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- fail("Expected NoSuchAlgorithmException in addSigner");
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignore
- }
- }
-
- public void testSha1EncapsulatedSignature()
- throws Exception
- {
- byte[] encapSigData = Base64.decode(
- "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEH"
- + "AaCAJIAEDEhlbGxvIFdvcmxkIQAAAAAAAKCCBGIwggINMIIBdqADAgECAgEF"
- + "MA0GCSqGSIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJ"
- + "BgNVBAYTAkFVMB4XDTA1MDgwNzA2MjU1OVoXDTA1MTExNTA2MjU1OVowJTEW"
- + "MBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZI"
- + "hvcNAQEBBQADgY0AMIGJAoGBAI1fZGgH9wgC3QiK6yluH6DlLDkXkxYYL+Qf"
- + "nVRszJVYl0LIxZdpb7WEbVpO8fwtEgFtoDsOdxyqh3dTBv+L7NVD/v46kdPt"
- + "xVkSNHRbutJVY8Xn4/TC/CDngqtbpbniMO8n0GiB6vs94gBT20M34j96O2IF"
- + "73feNHP+x8PkJ+dNAgMBAAGjTTBLMB0GA1UdDgQWBBQ3XUfEE6+D+t+LIJgK"
- + "ESSUE58eyzAfBgNVHSMEGDAWgBQ3XUfEE6+D+t+LIJgKESSUE58eyzAJBgNV"
- + "HRMEAjAAMA0GCSqGSIb3DQEBBAUAA4GBAFK3r1stYOeXYJOlOyNGDTWEhZ+a"
- + "OYdFeFaS6c+InjotHuFLAy+QsS8PslE48zYNFEqYygGfLhZDLlSnJ/LAUTqF"
- + "01vlp+Bgn/JYiJazwi5WiiOTf7Th6eNjHFKXS3hfSGPNPIOjvicAp3ce3ehs"
- + "uK0MxgLAaxievzhFfJcGSUMDMIICTTCCAbagAwIBAgIBBzANBgkqhkiG9w0B"
- + "AQQFADAlMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTAe"
- + "Fw0wNTA4MDcwNjI1NTlaFw0wNTExMTUwNjI1NTlaMGUxGDAWBgNVBAMTD0Vy"
- + "aWMgSC4gRWNoaWRuYTEkMCIGCSqGSIb3DQEJARYVZXJpY0Bib3VuY3ljYXN0"
- + "bGUub3JnMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTCB"
- + "nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAgHCJyfwV6/V3kqSu2SOU2E/K"
- + "I+N0XohCMUaxPLLNtNBZ3ijxwaV6JGFz7siTgZD/OGfzir/eZimkt+L1iXQn"
- + "OAB+ZChivKvHtX+dFFC7Vq+E4Uy0Ftqc/wrGxE6DHb5BR0hprKH8wlDS8wSP"
- + "zxovgk4nH0ffUZOoDSuUgjh3gG8CAwEAAaNNMEswHQYDVR0OBBYEFLfY/4EG"
- + "mYrvJa7Cky+K9BJ7YmERMB8GA1UdIwQYMBaAFDddR8QTr4P634sgmAoRJJQT"
- + "nx7LMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEEBQADgYEADIOmpMd6UHdMjkyc"
- + "mIE1yiwfClCsGhCK9FigTg6U1G2FmkBwJIMWBlkeH15uvepsAncsgK+Cn3Zr"
- + "dZMb022mwtTJDtcaOM+SNeuCnjdowZ4i71Hf68siPm6sMlZkhz49rA0Yidoo"
- + "WuzYOO+dggzwDsMldSsvsDo/ARyCGOulDOAxggEvMIIBKwIBATAqMCUxFjAU"
- + "BgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFVAgEHMAkGBSsOAwIa"
- + "BQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEP"
- + "Fw0wNTA4MDcwNjI1NTlaMCMGCSqGSIb3DQEJBDEWBBQu973mCM5UBOl9XwQv"
- + "lfifHCMocTANBgkqhkiG9w0BAQEFAASBgGxnBl2qozYKLgZ0ygqSFgWcRGl1"
- + "LgNuE587LtO+EKkgoc3aFqEdjXlAyP8K7naRsvWnFrsB6pUpnrgI9Z8ZSKv8"
- + "98IlpsSSJ0jBlEb4gzzavwcBpYbr2ryOtDcF+kYmKIpScglyyoLzm+KPXOoT"
- + "n7MsJMoKN3Kd2Vzh6s10PFgeAAAAAAAA");
-
- CMSSignedDataParser sp = new CMSSignedDataParser(encapSigData);
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
- }
-
- public void testSHA1WithRSANoAttributes()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes());
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData s = gen.generate(CMSSignedDataGenerator.DATA, msg, false, BC, false);
-
- CMSSignedDataParser sp = new CMSSignedDataParser(
- new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), s.getEncoded());
-
- sp.getSignedContent().drain();
-
- //
- // compute expected content digest
- //
- MessageDigest md = MessageDigest.getInstance("SHA1", BC);
-
- verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes()));
- }
-
- public void testDSANoAttributes()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes());
-
- certList.add(_origDsaCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origDsaKP.getPrivate(), _origDsaCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData s = gen.generate(CMSSignedDataGenerator.DATA, msg, false, BC, false);
-
- CMSSignedDataParser sp = new CMSSignedDataParser(
- new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), s.getEncoded());
-
- sp.getSignedContent().drain();
-
- //
- // compute expected content digest
- //
- MessageDigest md = MessageDigest.getInstance("SHA1", BC);
-
- verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes()));
- }
-
- public void testSHA1WithRSA()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- certList.add(_signCrl);
- certList.add(_origCrl);
-
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certsAndCrls);
-
- OutputStream sigOut = gen.open(bOut);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- checkSigParseable(bOut.toByteArray());
-
- CMSSignedDataParser sp = new CMSSignedDataParser(
- new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- //
- // compute expected content digest
- //
- MessageDigest md = MessageDigest.getInstance("SHA1", BC);
-
- verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes()));
-
- //
- // try using existing signer
- //
- gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigners(sp.getSignerInfos());
-
- gen.addCertificatesAndCRLs(sp.getCertificatesAndCRLs("Collection", BC));
-
- bOut.reset();
-
- sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- verifyEncodedData(bOut);
-
- //
- // look for the CRLs
- //
- Collection col = certsAndCrls.getCRLs(null);
-
- assertEquals(2, col.size());
- assertTrue(col.contains(_signCrl));
- assertTrue(col.contains(_origCrl));
- }
-
- public void testSHA1WithRSANonData()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- certList.add(_signCrl);
- certList.add(_origCrl);
-
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certsAndCrls);
-
- OutputStream sigOut = gen.open(bOut, "1.2.3.4", true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedDataParser sp = new CMSSignedDataParser(bOut.toByteArray());
-
- CMSTypedStream stream = sp.getSignedContent();
-
- assertEquals(new ASN1ObjectIdentifier("1.2.3.4"), stream.getContentType());
-
- stream.drain();
-
- //
- // compute expected content digest
- //
- MessageDigest md = MessageDigest.getInstance("SHA1", BC);
-
- verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes()));
- }
-
- public void testSHA1AndMD5WithRSA()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_MD5, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- checkSigParseable(bOut.toByteArray());
-
- CMSSignedDataParser sp = new CMSSignedDataParser(
- new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
- }
-
- public void testSHA1WithRSAEncapsulatedBufferedStream()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- //
- // find unbuffered length
- //
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, true);
-
- for (int i = 0; i != 2000; i++)
- {
- sigOut.write(i & 0xff);
- }
-
- sigOut.close();
-
- CMSSignedDataParser sp = new CMSSignedDataParser(bOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
-
- int unbufferedLength = bOut.toByteArray().length;
-
- //
- // find buffered length with buffered stream - should be equal
- //
- bOut = new ByteArrayOutputStream();
-
- gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- sigOut = gen.open(bOut, true);
-
- BufferedOutputStream bfOut = new BufferedOutputStream(sigOut, 300);
-
- for (int i = 0; i != 2000; i++)
- {
- bfOut.write(i & 0xff);
- }
-
- bfOut.close();
-
- verifyEncodedData(bOut);
-
- assertTrue(bOut.toByteArray().length == unbufferedLength);
- }
-
- public void testSHA1WithRSAEncapsulatedBuffered()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- //
- // find unbuffered length
- //
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, true);
-
- for (int i = 0; i != 2000; i++)
- {
- sigOut.write(i & 0xff);
- }
-
- sigOut.close();
-
- CMSSignedDataParser sp = new CMSSignedDataParser(bOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
-
- int unbufferedLength = bOut.toByteArray().length;
-
- //
- // find buffered length - buffer size less than default
- //
- bOut = new ByteArrayOutputStream();
-
- gen = new CMSSignedDataStreamGenerator();
-
- gen.setBufferSize(300);
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- sigOut = gen.open(bOut, true);
-
- for (int i = 0; i != 2000; i++)
- {
- sigOut.write(i & 0xff);
- }
-
- sigOut.close();
-
- verifyEncodedData(bOut);
-
- assertTrue(bOut.toByteArray().length > unbufferedLength);
- }
-
- public void testSHA1WithRSAEncapsulated()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedDataParser sp = new CMSSignedDataParser(bOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
-
- byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(CMSSignedGenerator.DIGEST_SHA1);
-
- AttributeTable table = ((SignerInformation)sp.getSignerInfos().getSigners().iterator().next()).getSignedAttributes();
- Attribute hash = table.get(CMSAttributes.messageDigest);
-
- assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets()));
-
- //
- // try using existing signer
- //
- gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigners(sp.getSignerInfos());
-
- gen.addCertificatesAndCRLs(sp.getCertificatesAndCRLs("Collection", BC));
-
- bOut.reset();
-
- sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedData sd = new CMSSignedData(new CMSProcessableByteArray(TEST_MESSAGE.getBytes()), bOut.toByteArray());
-
- assertEquals(1, sd.getSignerInfos().getSigners().size());
-
- verifyEncodedData(bOut);
- }
-
- public void testSHA1WithRSAEncapsulatedSubjectKeyID()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), CMSTestUtil.createSubjectKeyId(_origCert.getPublicKey()).getKeyIdentifier(), CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedDataParser sp = new CMSSignedDataParser(bOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
-
- byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(CMSSignedGenerator.DIGEST_SHA1);
-
- AttributeTable table = ((SignerInformation)sp.getSignerInfos().getSigners().iterator().next()).getSignedAttributes();
- Attribute hash = table.get(CMSAttributes.messageDigest);
-
- assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets()));
-
- //
- // try using existing signer
- //
- gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigners(sp.getSignerInfos());
-
- gen.addCertificatesAndCRLs(sp.getCertificatesAndCRLs("Collection", BC));
-
- bOut.reset();
-
- sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedData sd = new CMSSignedData(new CMSProcessableByteArray(TEST_MESSAGE.getBytes()), bOut.toByteArray());
-
- assertEquals(1, sd.getSignerInfos().getSigners().size());
-
- verifyEncodedData(bOut);
- }
-
- public void testAttributeGenerators()
- throws Exception
- {
- final ASN1ObjectIdentifier dummyOid1 = new ASN1ObjectIdentifier("1.2.3");
- final ASN1ObjectIdentifier dummyOid2 = new ASN1ObjectIdentifier("1.2.3.4");
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- CMSAttributeTableGenerator signedGen = new DefaultSignedAttributeTableGenerator()
- {
- public AttributeTable getAttributes(Map parameters)
- {
- Hashtable table = createStandardAttributeTable(parameters);
-
- DEROctetString val = new DEROctetString((byte[])parameters.get(CMSAttributeTableGenerator.DIGEST));
- Attribute attr = new Attribute(dummyOid1, new DERSet(val));
-
- table.put(attr.getAttrType(), attr);
-
- return new AttributeTable(table);
- }
- };
-
- CMSAttributeTableGenerator unsignedGen = new CMSAttributeTableGenerator()
- {
- public AttributeTable getAttributes(Map parameters)
- {
- DEROctetString val = new DEROctetString((byte[])parameters.get(CMSAttributeTableGenerator.SIGNATURE));
- Attribute attr = new Attribute(dummyOid2, new DERSet(val));
-
- return new AttributeTable(new DERSet(attr));
- }
- };
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, signedGen, unsignedGen, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedDataParser sp = new CMSSignedDataParser(bOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
-
- //
- // check attributes
- //
- SignerInformationStore signers = sp.getSignerInfos();
-
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- checkAttribute(signer.getContentDigest(), signer.getSignedAttributes().get(dummyOid1));
- checkAttribute(signer.getSignature(), signer.getUnsignedAttributes().get(dummyOid2));
- }
- }
-
- private void checkAttribute(byte[] expected, Attribute attr)
- {
- DEROctetString value = (DEROctetString)attr.getAttrValues().getObjectAt(0);
-
- assertEquals(new DEROctetString(expected), value);
- }
-
- public void testWithAttributeCertificate()
- throws Exception
- {
- List certList = new ArrayList();
-
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- X509AttributeCertificate attrCert = CMSTestUtil.getAttributeCertificate();
-
- X509Store store = X509Store.getInstance("AttributeCertificate/Collection",
- new X509CollectionStoreParameters(Collections.singleton(attrCert)), BC);
-
- gen.addAttributeCertificates(store);
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- OutputStream sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedDataParser sp = new CMSSignedDataParser(bOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- assertEquals(4, sp.getVersion());
-
- store = sp.getAttributeCertificates("Collection", BC);
-
- Collection coll = store.getMatches(null);
-
- assertEquals(1, coll.size());
-
- assertTrue(coll.contains(attrCert));
- }
-
- public void testSignerStoreReplacement()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- byte[] data = TEST_MESSAGE.getBytes();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, false);
-
- sigOut.write(data);
-
- sigOut.close();
-
- checkSigParseable(bOut.toByteArray());
-
- //
- // create new Signer
- //
- ByteArrayInputStream original = new ByteArrayInputStream(bOut.toByteArray());
-
- bOut.reset();
-
- gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA224, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- sigOut = gen.open(bOut);
-
- sigOut.write(data);
-
- sigOut.close();
-
- checkSigParseable(bOut.toByteArray());
-
- CMSSignedData sd = new CMSSignedData(bOut.toByteArray());
-
- //
- // replace signer
- //
- ByteArrayOutputStream newOut = new ByteArrayOutputStream();
-
- CMSSignedDataParser.replaceSigners(original, sd.getSignerInfos(), newOut);
-
- sd = new CMSSignedData(new CMSProcessableByteArray(data), newOut.toByteArray());
- SignerInformation signer = (SignerInformation)sd.getSignerInfos().getSigners().iterator().next();
-
- assertEquals(signer.getDigestAlgOID(), CMSSignedDataStreamGenerator.DIGEST_SHA224);
-
- CMSSignedDataParser sp = new CMSSignedDataParser(new CMSTypedStream(new ByteArrayInputStream(data)), newOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
- }
-
- public void testEncapsulatedSignerStoreReplacement()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- //
- // create new Signer
- //
- ByteArrayInputStream original = new ByteArrayInputStream(bOut.toByteArray());
-
- bOut.reset();
-
- gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA224, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedData sd = new CMSSignedData(bOut.toByteArray());
-
- //
- // replace signer
- //
- ByteArrayOutputStream newOut = new ByteArrayOutputStream();
-
- CMSSignedDataParser.replaceSigners(original, sd.getSignerInfos(), newOut);
-
- sd = new CMSSignedData(newOut.toByteArray());
- SignerInformation signer = (SignerInformation)sd.getSignerInfos().getSigners().iterator().next();
-
- assertEquals(signer.getDigestAlgOID(), CMSSignedDataStreamGenerator.DIGEST_SHA224);
-
- CMSSignedDataParser sp = new CMSSignedDataParser(newOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
- }
-
- public void testCertStoreReplacement()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- byte[] data = TEST_MESSAGE.getBytes();
-
- certList.add(_origDsaCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut);
-
- sigOut.write(data);
-
- sigOut.close();
-
- checkSigParseable(bOut.toByteArray());
-
- //
- // create new certstore with the right certificates
- //
- certList = new ArrayList();
- certList.add(_origCert);
- certList.add(_signCert);
-
- certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- //
- // replace certs
- //
- ByteArrayInputStream original = new ByteArrayInputStream(bOut.toByteArray());
- ByteArrayOutputStream newOut = new ByteArrayOutputStream();
-
- CMSSignedDataParser.replaceCertificatesAndCRLs(original, certs, newOut);
-
- CMSSignedDataParser sp = new CMSSignedDataParser(new CMSTypedStream(new ByteArrayInputStream(data)), newOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
- }
-
- public void testEncapsulatedCertStoreReplacement()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origDsaCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- //
- // create new certstore with the right certificates
- //
- certList = new ArrayList();
- certList.add(_origCert);
- certList.add(_signCert);
-
- certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- //
- // replace certs
- //
- ByteArrayInputStream original = new ByteArrayInputStream(bOut.toByteArray());
- ByteArrayOutputStream newOut = new ByteArrayOutputStream();
-
- CMSSignedDataParser.replaceCertificatesAndCRLs(original, certs, newOut);
-
- CMSSignedDataParser sp = new CMSSignedDataParser(newOut.toByteArray());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
- }
-
- public void testCertOrdering1()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedDataParser sp = new CMSSignedDataParser(bOut.toByteArray());
-
- sp.getSignedContent().drain();
- certs = sp.getCertificatesAndCRLs("Collection", BC);
- Iterator it = certs.getCertificates(null).iterator();
-
- assertEquals(_origCert, it.next());
- assertEquals(_signCert, it.next());
- }
-
- public void testCertOrdering2()
- throws Exception
- {
- List certList = new ArrayList();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- certList.add(_signCert);
- certList.add(_origCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, BC);
-
- gen.addCertificatesAndCRLs(certs);
-
- OutputStream sigOut = gen.open(bOut, true);
-
- sigOut.write(TEST_MESSAGE.getBytes());
-
- sigOut.close();
-
- CMSSignedDataParser sp = new CMSSignedDataParser(bOut.toByteArray());
-
- sp.getSignedContent().drain();
- certs = sp.getCertificatesAndCRLs("Collection", BC);
- Iterator it = certs.getCertificates(null).iterator();
-
- assertEquals(_signCert, it.next());
- assertEquals(_origCert, it.next());
- }
-
- public static Test suite()
- throws Exception
- {
- init();
-
- return new CMSTestSetup(new TestSuite(SignedDataStreamTest.class));
- }
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/SignedDataTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/SignedDataTest.java
deleted file mode 100644
index 160669b..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/SignedDataTest.java
+++ /dev/null
@@ -1,1573 +0,0 @@
-package org.bouncycastle.cms.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertStore;
-import java.security.cert.CollectionCertStoreParameters;
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.cms.Attribute;
-import org.bouncycastle.asn1.cms.AttributeTable;
-import org.bouncycastle.asn1.cms.CMSAttributes;
-import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.cms.CMSConfig;
-import org.bouncycastle.cms.CMSProcessable;
-import org.bouncycastle.cms.CMSProcessableByteArray;
-import org.bouncycastle.cms.CMSSignedData;
-import org.bouncycastle.cms.CMSSignedDataGenerator;
-import org.bouncycastle.cms.CMSSignedDataParser;
-import org.bouncycastle.cms.SignerId;
-import org.bouncycastle.cms.SignerInformation;
-import org.bouncycastle.cms.SignerInformationStore;
-import org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.io.Streams;
-import org.bouncycastle.x509.X509AttributeCertificate;
-import org.bouncycastle.x509.X509CollectionStoreParameters;
-import org.bouncycastle.x509.X509Store;
-
-public class SignedDataTest
- extends TestCase
-{
- private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
-
- boolean DEBUG = true;
-
- private static String _origDN;
- private static KeyPair _origKP;
- private static X509Certificate _origCert;
-
- private static String _signDN;
- private static KeyPair _signKP;
- private static X509Certificate _signCert;
-
- private static KeyPair _signGostKP;
- private static X509Certificate _signGostCert;
-
- private static KeyPair _signEcDsaKP;
- private static X509Certificate _signEcDsaCert;
-
- private static KeyPair _signEcGostKP;
- private static X509Certificate _signEcGostCert;
-
- private static KeyPair _signDsaKP;
- private static X509Certificate _signDsaCert;
-
- private static String _reciDN;
- private static KeyPair _reciKP;
- private static X509Certificate _reciCert;
-
- private static X509CRL _signCrl;
-
- private static boolean _initialised = false;
-
- private byte[] disorderedMessage = Base64.decode(
- "SU9fc3RkaW5fdXNlZABfX2xpYmNfc3RhcnRfbWFpbgBnZXRob3N0aWQAX19n"
- + "bW9uX3M=");
-
- private byte[] disorderedSet = Base64.decode(
- "MIIYXQYJKoZIhvcNAQcCoIIYTjCCGEoCAQExCzAJBgUrDgMCGgUAMAsGCSqG"
- + "SIb3DQEHAaCCFqswggJUMIIBwKADAgECAgMMg6wwCgYGKyQDAwECBQAwbzEL"
- + "MAkGA1UEBhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbI"
- + "dXIgVGVsZWtvbW11bmlrYXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwEx"
- + "MBEGA1UEAxQKNFItQ0EgMTpQTjAiGA8yMDAwMDMyMjA5NDM1MFoYDzIwMDQw"
- + "MTIxMTYwNDUzWjBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1"
- + "bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEh"
- + "MAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1DQSAxOlBOMIGhMA0GCSqGSIb3"
- + "DQEBAQUAA4GPADCBiwKBgQCKHkFTJx8GmoqFTxEOxpK9XkC3NZ5dBEKiUv0I"
- + "fe3QMqeGMoCUnyJxwW0k2/53duHxtv2yHSZpFKjrjvE/uGwdOMqBMTjMzkFg"
- + "19e9JPv061wyADOucOIaNAgha/zFt9XUyrHF21knKCvDNExv2MYIAagkTKaj"
- + "LMAw0bu1J0FadQIFAMAAAAEwCgYGKyQDAwECBQADgYEAgFauXpoTLh3Z3pT/"
- + "3bhgrxO/2gKGZopWGSWSJPNwq/U3x2EuctOJurj+y2inTcJjespThflpN+7Q"
- + "nvsUhXU+jL2MtPlObU0GmLvWbi47cBShJ7KElcZAaxgWMBzdRGqTOdtMv+ev"
- + "2t4igGF/q71xf6J2c3pTLWr6P8s6tzLfOCMwggJDMIIBr6ADAgECAgQAuzyu"
- + "MAoGBiskAwMBAgUAMG8xCzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGll"
- + "cnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0"
- + "MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjVSLUNBIDE6UE4wIhgPMjAwMTA4"
- + "MjAwODA4MjBaGA8yMDA1MDgyMDA4MDgyMFowSzELMAkGA1UEBhMCREUxEjAQ"
- + "BgNVBAoUCVNpZ250cnVzdDEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFDQSBT"
- + "SUdOVFJVU1QgMTpQTjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAhV12"
- + "N2WhlR6f+3CXP57GrBM9la5Vnsu2b92zv5MZqQOPeEsYbZqDCFkYg1bSwsDE"
- + "XsGVQqXdQNAGUaapr/EUVVN+hNZ07GcmC1sPeQECgUkxDYjGi4ihbvzxlahj"
- + "L4nX+UTzJVBfJwXoIvJ+lMHOSpnOLIuEL3SRhBItvRECxN0CAwEAAaMSMBAw"
- + "DgYDVR0PAQH/BAQDAgEGMAoGBiskAwMBAgUAA4GBACDc9Pc6X8sK1cerphiV"
- + "LfFv4kpZb9ev4WPy/C6987Qw1SOTElhZAmxaJQBqmDHWlQ63wj1DEqswk7hG"
- + "LrvQk/iX6KXIn8e64uit7kx6DHGRKNvNGofPjr1WelGeGW/T2ZJKgmPDjCkf"
- + "sIKt2c3gwa2pDn4mmCz/DStUIqcPDbqLMIICVTCCAcGgAwIBAgIEAJ16STAK"
- + "BgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1"
- + "bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEh"
- + "MAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1DQSAxOlBOMCIYDzIwMDEwMjAx"
- + "MTM0NDI1WhgPMjAwNTAzMjIwODU1NTFaMG8xCzAJBgNVBAYTAkRFMT0wOwYD"
- + "VQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0"
- + "aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjZSLUNhIDE6"
- + "UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGLAoGBAIOiqxUkzVyqnvthihnl"
- + "tsE5m1Xn5TZKeR/2MQPStc5hJ+V4yptEtIx+Fn5rOoqT5VEVWhcE35wdbPvg"
- + "JyQFn5msmhPQT/6XSGOlrWRoFummXN9lQzAjCj1sgTcmoLCVQ5s5WpCAOXFw"
- + "VWu16qndz3sPItn3jJ0F3Kh3w79NglvPAgUAwAAAATAKBgYrJAMDAQIFAAOB"
- + "gQBpSRdnDb6AcNVaXSmGo6+kVPIBhot1LzJOGaPyDNpGXxd7LV4tMBF1U7gr"
- + "4k1g9BO6YiMWvw9uiTZmn0CfV8+k4fWEuG/nmafRoGIuay2f+ILuT+C0rnp1"
- + "4FgMsEhuVNJJAmb12QV0PZII+UneyhAneZuQQzVUkTcVgYxogxdSOzCCAlUw"
- + "ggHBoAMCAQICBACdekowCgYGKyQDAwECBQAwbzELMAkGA1UEBhMCREUxPTA7"
- + "BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlr"
- + "YXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNlItQ2Eg"
- + "MTpQTjAiGA8yMDAxMDIwMTEzNDcwN1oYDzIwMDUwMzIyMDg1NTUxWjBvMQsw"
- + "CQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1"
- + "ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEw"
- + "EQYDVQQDFAo1Ui1DQSAxOlBOMIGhMA0GCSqGSIb3DQEBAQUAA4GPADCBiwKB"
- + "gQCKHkFTJx8GmoqFTxEOxpK9XkC3NZ5dBEKiUv0Ife3QMqeGMoCUnyJxwW0k"
- + "2/53duHxtv2yHSZpFKjrjvE/uGwdOMqBMTjMzkFg19e9JPv061wyADOucOIa"
- + "NAgha/zFt9XUyrHF21knKCvDNExv2MYIAagkTKajLMAw0bu1J0FadQIFAMAA"
- + "AAEwCgYGKyQDAwECBQADgYEAV1yTi+2gyB7sUhn4PXmi/tmBxAfe5oBjDW8m"
- + "gxtfudxKGZ6l/FUPNcrSc5oqBYxKWtLmf3XX87LcblYsch617jtNTkMzhx9e"
- + "qxiD02ufcrxz2EVt0Akdqiz8mdVeqp3oLcNU/IttpSrcA91CAnoUXtDZYwb/"
- + "gdQ4FI9l3+qo/0UwggJVMIIBwaADAgECAgQAxIymMAoGBiskAwMBAgUAMG8x"
- + "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm"
- + "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB"
- + "MTARBgNVBAMUCjZSLUNhIDE6UE4wIhgPMjAwMTEwMTUxMzMxNThaGA8yMDA1"
- + "MDYwMTA5NTIxN1owbzELMAkGA1UEBhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVy"
- + "dW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlrYXRpb24gdW5kIFBvc3Qx"
- + "ITAMBgcCggYBCgcUEwExMBEGA1UEAxQKN1ItQ0EgMTpQTjCBoTANBgkqhkiG"
- + "9w0BAQEFAAOBjwAwgYsCgYEAiokD/j6lEP4FexF356OpU5teUpGGfUKjIrFX"
- + "BHc79G0TUzgVxqMoN1PWnWktQvKo8ETaugxLkP9/zfX3aAQzDW4Zki6x6GDq"
- + "fy09Agk+RJvhfbbIzRkV4sBBco0n73x7TfG/9NTgVr/96U+I+z/1j30aboM6"
- + "9OkLEhjxAr0/GbsCBQDAAAABMAoGBiskAwMBAgUAA4GBAHWRqRixt+EuqHhR"
- + "K1kIxKGZL2vZuakYV0R24Gv/0ZR52FE4ECr+I49o8FP1qiGSwnXB0SwjuH2S"
- + "iGiSJi+iH/MeY85IHwW1P5e+bOMvEOFhZhQXQixOD7totIoFtdyaj1XGYRef"
- + "0f2cPOjNJorXHGV8wuBk+/j++sxbd/Net3FtMIICVTCCAcGgAwIBAgIEAMSM"
- + "pzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp"
- + "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z"
- + "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo3Ui1DQSAxOlBOMCIYDzIwMDEx"
- + "MDE1MTMzNDE0WhgPMjAwNTA2MDEwOTUyMTdaMG8xCzAJBgNVBAYTAkRFMT0w"
- + "OwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5p"
- + "a2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjZSLUNh"
- + "IDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGLAoGBAIOiqxUkzVyqnvth"
- + "ihnltsE5m1Xn5TZKeR/2MQPStc5hJ+V4yptEtIx+Fn5rOoqT5VEVWhcE35wd"
- + "bPvgJyQFn5msmhPQT/6XSGOlrWRoFummXN9lQzAjCj1sgTcmoLCVQ5s5WpCA"
- + "OXFwVWu16qndz3sPItn3jJ0F3Kh3w79NglvPAgUAwAAAATAKBgYrJAMDAQIF"
- + "AAOBgQBi5W96UVDoNIRkCncqr1LLG9vF9SGBIkvFpLDIIbcvp+CXhlvsdCJl"
- + "0pt2QEPSDl4cmpOet+CxJTdTuMeBNXxhb7Dvualog69w/+K2JbPhZYxuVFZs"
- + "Zh5BkPn2FnbNu3YbJhE60aIkikr72J4XZsI5DxpZCGh6xyV/YPRdKSljFjCC"
- + "AlQwggHAoAMCAQICAwyDqzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9"
- + "MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVu"
- + "aWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1D"
- + "QSAxOlBOMCIYDzIwMDAwMzIyMDk0MTI3WhgPMjAwNDAxMjExNjA0NTNaMG8x"
- + "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm"
- + "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB"
- + "MTARBgNVBAMUCjRSLUNBIDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGL"
- + "AoGBAI8x26tmrFJanlm100B7KGlRemCD1R93PwdnG7svRyf5ZxOsdGrDszNg"
- + "xg6ouO8ZHQMT3NC2dH8TvO65Js+8bIyTm51azF6clEg0qeWNMKiiXbBXa+ph"
- + "hTkGbXiLYvACZ6/MTJMJ1lcrjpRF7BXtYeYMcEF6znD4pxOqrtbf9z5hAgUA"
- + "wAAAATAKBgYrJAMDAQIFAAOBgQB99BjSKlGPbMLQAgXlvA9jUsDNhpnVm3a1"
- + "YkfxSqS/dbQlYkbOKvCxkPGA9NBxisBM8l1zFynVjJoy++aysRmcnLY/sHaz"
- + "23BF2iU7WERy18H3lMBfYB6sXkfYiZtvQZcWaO48m73ZBySuiV3iXpb2wgs/"
- + "Cs20iqroAWxwq/W/9jCCAlMwggG/oAMCAQICBDsFZ9UwCgYGKyQDAwECBQAw"
- + "bzELMAkGA1UEBhMCREUxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNFItQ0Eg"
- + "MTpQTjE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxl"
- + "a29tbXVuaWthdGlvbiB1bmQgUG9zdDAiGA8xOTk5MDEyMTE3MzUzNFoYDzIw"
- + "MDQwMTIxMTYwMDAyWjBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp"
- + "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z"
- + "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAozUi1DQSAxOlBOMIGfMA0GCSqG"
- + "SIb3DQEBAQUAA4GNADCBiQKBgI4B557mbKQg/AqWBXNJhaT/6lwV93HUl4U8"
- + "u35udLq2+u9phns1WZkdM3gDfEpL002PeLfHr1ID/96dDYf04lAXQfombils"
- + "of1C1k32xOvxjlcrDOuPEMxz9/HDAQZA5MjmmYHAIulGI8Qg4Tc7ERRtg/hd"
- + "0QX0/zoOeXoDSEOBAgTAAAABMAoGBiskAwMBAgUAA4GBAIyzwfT3keHI/n2P"
- + "LrarRJv96mCohmDZNpUQdZTVjGu5VQjVJwk3hpagU0o/t/FkdzAjOdfEw8Ql"
- + "3WXhfIbNLv1YafMm2eWSdeYbLcbB5yJ1od+SYyf9+tm7cwfDAcr22jNRBqx8"
- + "wkWKtKDjWKkevaSdy99sAI8jebHtWz7jzydKMIID9TCCA16gAwIBAgICbMcw"
- + "DQYJKoZIhvcNAQEFBQAwSzELMAkGA1UEBhMCREUxEjAQBgNVBAoUCVNpZ250"
- + "cnVzdDEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFDQSBTSUdOVFJVU1QgMTpQ"
- + "TjAeFw0wNDA3MzAxMzAyNDZaFw0wNzA3MzAxMzAyNDZaMDwxETAPBgNVBAMM"
- + "CFlhY29tOlBOMQ4wDAYDVQRBDAVZYWNvbTELMAkGA1UEBhMCREUxCjAIBgNV"
- + "BAUTATEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIWzLlYLQApocXIp"
- + "pgCCpkkOUVLgcLYKeOd6/bXAnI2dTHQqT2bv7qzfUnYvOqiNgYdF13pOYtKg"
- + "XwXMTNFL4ZOI6GoBdNs9TQiZ7KEWnqnr2945HYx7UpgTBclbOK/wGHuCdcwO"
- + "x7juZs1ZQPFG0Lv8RoiV9s6HP7POqh1sO0P/AgMBAAGjggH1MIIB8TCBnAYD"
- + "VR0jBIGUMIGRgBQcZzNghfnXoXRm8h1+VITC5caNRqFzpHEwbzELMAkGA1UE"
- + "BhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVs"
- + "ZWtvbW11bmlrYXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UE"
- + "AxQKNVItQ0EgMTpQToIEALs8rjAdBgNVHQ4EFgQU2e5KAzkVuKaM9I5heXkz"
- + "bcAIuR8wDgYDVR0PAQH/BAQDAgZAMBIGA1UdIAQLMAkwBwYFKyQIAQEwfwYD"
- + "VR0fBHgwdjB0oCygKoYobGRhcDovL2Rpci5zaWdudHJ1c3QuZGUvbz1TaWdu"
- + "dHJ1c3QsYz1kZaJEpEIwQDEdMBsGA1UEAxMUQ1JMU2lnblNpZ250cnVzdDE6"
- + "UE4xEjAQBgNVBAoTCVNpZ250cnVzdDELMAkGA1UEBhMCREUwYgYIKwYBBQUH"
- + "AQEEVjBUMFIGCCsGAQUFBzABhkZodHRwOi8vZGlyLnNpZ250cnVzdC5kZS9T"
- + "aWdudHJ1c3QvT0NTUC9zZXJ2bGV0L2h0dHBHYXRld2F5LlBvc3RIYW5kbGVy"
- + "MBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEwDgYHAoIGAQoMAAQDAQH/MA0G"
- + "CSqGSIb3DQEBBQUAA4GBAHn1m3GcoyD5GBkKUY/OdtD6Sj38LYqYCF+qDbJR"
- + "6pqUBjY2wsvXepUppEler+stH8mwpDDSJXrJyuzf7xroDs4dkLl+Rs2x+2tg"
- + "BjU+ABkBDMsym2WpwgA8LCdymmXmjdv9tULxY+ec2pjSEzql6nEZNEfrU8nt"
- + "ZCSCavgqW4TtMYIBejCCAXYCAQEwUTBLMQswCQYDVQQGEwJERTESMBAGA1UE"
- + "ChQJU2lnbnRydXN0MSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEUNBIFNJR05U"
- + "UlVTVCAxOlBOAgJsxzAJBgUrDgMCGgUAoIGAMBgGCSqGSIb3DQEJAzELBgkq"
- + "hkiG9w0BBwEwIwYJKoZIhvcNAQkEMRYEFIYfhPoyfGzkLWWSSLjaHb4HQmaK"
- + "MBwGCSqGSIb3DQEJBTEPFw0wNTAzMjQwNzM4MzVaMCEGBSskCAYFMRgWFi92"
- + "YXIvZmlsZXMvdG1wXzEvdGVzdDEwDQYJKoZIhvcNAQEFBQAEgYA2IvA8lhVz"
- + "VD5e/itUxbFboKxeKnqJ5n/KuO/uBCl1N14+7Z2vtw1sfkIG+bJdp3OY2Cmn"
- + "mrQcwsN99Vjal4cXVj8t+DJzFG9tK9dSLvD3q9zT/GQ0kJXfimLVwCa4NaSf"
- + "Qsu4xtG0Rav6bCcnzabAkKuNNvKtH8amSRzk870DBg==");
-
- public static byte[] xtraCounterSig = Base64.decode(
- "MIIR/AYJKoZIhvcNAQcCoIIR7TCCEekCAQExCzAJBgUrDgMCGgUAMBoGCSqG"
- + "SIb3DQEHAaANBAtIZWxsbyB3b3JsZKCCDnkwggTPMIIDt6ADAgECAgRDnYD3"
- + "MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5U"
- + "ZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmlj"
- + "YXRpb24gQXV0aG9yaXR5MB4XDTA4MDkxMjExNDMxMloXDTEwMDkxMjExNDMx"
- + "MlowgdgxCzAJBgNVBAYTAklUMSIwIAYDVQQKDBlJbnRlc2EgUy5wLkEuLzA1"
- + "MjYyODkwMDE0MSowKAYDVQQLDCFCdXNpbmVzcyBDb2xsYWJvcmF0aW9uICYg"
- + "U2VjdXJpdHkxHjAcBgNVBAMMFU1BU1NJTUlMSUFOTyBaSUNDQVJESTERMA8G"
- + "A1UEBAwIWklDQ0FSREkxFTATBgNVBCoMDE1BU1NJTUlMSUFOTzEcMBoGA1UE"
- + "BRMTSVQ6WkNDTVNNNzZIMTRMMjE5WTERMA8GA1UELhMIMDAwMDI1ODUwgaAw"
- + "DQYJKoZIhvcNAQEBBQADgY4AMIGKAoGBALeJTjmyFgx1SIP6c2AuB/kuyHo5"
- + "j/prKELTALsFDimre/Hxr3wOSet1TdQfFzU8Lu+EJqgfV9cV+cI1yeH1rZs7"
- + "lei7L3tX/VR565IywnguX5xwvteASgWZr537Fkws50bvTEMyYOj1Tf3FZvZU"
- + "z4n4OD39KI4mfR9i1eEVIxR3AgQAizpNo4IBoTCCAZ0wHQYDVR0RBBYwFIES"
- + "emljY2FyZGlAaW50ZXNhLml0MC8GCCsGAQUFBwEDBCMwITAIBgYEAI5GAQEw"
- + "CwYGBACORgEDAgEUMAgGBgQAjkYBBDBZBgNVHSAEUjBQME4GBgQAizABATBE"
- + "MEIGCCsGAQUFBwIBFjZodHRwOi8vZS10cnVzdGNvbS5pbnRlc2EuaXQvY2Ff"
- + "cHViYmxpY2EvQ1BTX0lOVEVTQS5odG0wDgYDVR0PAQH/BAQDAgZAMIGDBgNV"
- + "HSMEfDB6gBQZCQOW0bjFWBt+EORuxPagEgkQqKFcpFowWDELMAkGA1UEBhMC"
- + "SVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJbi5U"
- + "ZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHmCBDzRARMwOwYDVR0f"
- + "BDQwMjAwoC6gLIYqaHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L0NSTC9J"
- + "TlRFU0EuY3JsMB0GA1UdDgQWBBTf5ItL8KmQh541Dxt7YxcWI1254TANBgkq"
- + "hkiG9w0BAQUFAAOCAQEAgW+uL1CVWQepbC/wfCmR6PN37Sueb4xiKQj2mTD5"
- + "UZ5KQjpivy/Hbuf0NrfKNiDEhAvoHSPC31ebGiKuTMFNyZPHfPEUnyYGSxea"
- + "2w837aXJFr6utPNQGBRi89kH90sZDlXtOSrZI+AzJJn5QK3F9gjcayU2NZXQ"
- + "MJgRwYmFyn2w4jtox+CwXPQ9E5XgxiMZ4WDL03cWVXDLX00EOJwnDDMUNTRI"
- + "m9Zv+4SKTNlfFbi9UTBqWBySkDzAelsfB2U61oqc2h1xKmCtkGMmN9iZT+Qz"
- + "ZC/vaaT+hLEBFGAH2gwFrYc4/jTBKyBYeU1vsAxsibIoTs1Apgl6MH75qPDL"
- + "BzCCBM8wggO3oAMCAQICBEOdgPcwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE"
- + "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ"
- + "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwOTEy"
- + "MTE0MzEyWhcNMTAwOTEyMTE0MzEyWjCB2DELMAkGA1UEBhMCSVQxIjAgBgNV"
- + "BAoMGUludGVzYSBTLnAuQS4vMDUyNjI4OTAwMTQxKjAoBgNVBAsMIUJ1c2lu"
- + "ZXNzIENvbGxhYm9yYXRpb24gJiBTZWN1cml0eTEeMBwGA1UEAwwVTUFTU0lN"
- + "SUxJQU5PIFpJQ0NBUkRJMREwDwYDVQQEDAhaSUNDQVJESTEVMBMGA1UEKgwM"
- + "TUFTU0lNSUxJQU5PMRwwGgYDVQQFExNJVDpaQ0NNU003NkgxNEwyMTlZMREw"
- + "DwYDVQQuEwgwMDAwMjU4NTCBoDANBgkqhkiG9w0BAQEFAAOBjgAwgYoCgYEA"
- + "t4lOObIWDHVIg/pzYC4H+S7IejmP+msoQtMAuwUOKat78fGvfA5J63VN1B8X"
- + "NTwu74QmqB9X1xX5wjXJ4fWtmzuV6Lsve1f9VHnrkjLCeC5fnHC+14BKBZmv"
- + "nfsWTCznRu9MQzJg6PVN/cVm9lTPifg4Pf0ojiZ9H2LV4RUjFHcCBACLOk2j"
- + "ggGhMIIBnTAdBgNVHREEFjAUgRJ6aWNjYXJkaUBpbnRlc2EuaXQwLwYIKwYB"
- + "BQUHAQMEIzAhMAgGBgQAjkYBATALBgYEAI5GAQMCARQwCAYGBACORgEEMFkG"
- + "A1UdIARSMFAwTgYGBACLMAEBMEQwQgYIKwYBBQUHAgEWNmh0dHA6Ly9lLXRy"
- + "dXN0Y29tLmludGVzYS5pdC9jYV9wdWJibGljYS9DUFNfSU5URVNBLmh0bTAO"
- + "BgNVHQ8BAf8EBAMCBkAwgYMGA1UdIwR8MHqAFBkJA5bRuMVYG34Q5G7E9qAS"
- + "CRCooVykWjBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5BLiBT"
- + "LnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9uIEF1"
- + "dGhvcml0eYIEPNEBEzA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vZS10cnVz"
- + "dGNvbS5pbnRlc2EuaXQvQ1JML0lOVEVTQS5jcmwwHQYDVR0OBBYEFN/ki0vw"
- + "qZCHnjUPG3tjFxYjXbnhMA0GCSqGSIb3DQEBBQUAA4IBAQCBb64vUJVZB6ls"
- + "L/B8KZHo83ftK55vjGIpCPaZMPlRnkpCOmK/L8du5/Q2t8o2IMSEC+gdI8Lf"
- + "V5saIq5MwU3Jk8d88RSfJgZLF5rbDzftpckWvq6081AYFGLz2Qf3SxkOVe05"
- + "Ktkj4DMkmflArcX2CNxrJTY1ldAwmBHBiYXKfbDiO2jH4LBc9D0TleDGIxnh"
- + "YMvTdxZVcMtfTQQ4nCcMMxQ1NEib1m/7hIpM2V8VuL1RMGpYHJKQPMB6Wx8H"
- + "ZTrWipzaHXEqYK2QYyY32JlP5DNkL+9ppP6EsQEUYAfaDAWthzj+NMErIFh5"
- + "TW+wDGyJsihOzUCmCXowfvmo8MsHMIIEzzCCA7egAwIBAgIEQ52A9zANBgkq"
- + "hkiG9w0BAQUFADBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5B"
- + "LiBTLnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9u"
- + "IEF1dGhvcml0eTAeFw0wODA5MTIxMTQzMTJaFw0xMDA5MTIxMTQzMTJaMIHY"
- + "MQswCQYDVQQGEwJJVDEiMCAGA1UECgwZSW50ZXNhIFMucC5BLi8wNTI2Mjg5"
- + "MDAxNDEqMCgGA1UECwwhQnVzaW5lc3MgQ29sbGFib3JhdGlvbiAmIFNlY3Vy"
- + "aXR5MR4wHAYDVQQDDBVNQVNTSU1JTElBTk8gWklDQ0FSREkxETAPBgNVBAQM"
- + "CFpJQ0NBUkRJMRUwEwYDVQQqDAxNQVNTSU1JTElBTk8xHDAaBgNVBAUTE0lU"
- + "OlpDQ01TTTc2SDE0TDIxOVkxETAPBgNVBC4TCDAwMDAyNTg1MIGgMA0GCSqG"
- + "SIb3DQEBAQUAA4GOADCBigKBgQC3iU45shYMdUiD+nNgLgf5Lsh6OY/6ayhC"
- + "0wC7BQ4pq3vx8a98DknrdU3UHxc1PC7vhCaoH1fXFfnCNcnh9a2bO5Xouy97"
- + "V/1UeeuSMsJ4Ll+ccL7XgEoFma+d+xZMLOdG70xDMmDo9U39xWb2VM+J+Dg9"
- + "/SiOJn0fYtXhFSMUdwIEAIs6TaOCAaEwggGdMB0GA1UdEQQWMBSBEnppY2Nh"
- + "cmRpQGludGVzYS5pdDAvBggrBgEFBQcBAwQjMCEwCAYGBACORgEBMAsGBgQA"
- + "jkYBAwIBFDAIBgYEAI5GAQQwWQYDVR0gBFIwUDBOBgYEAIswAQEwRDBCBggr"
- + "BgEFBQcCARY2aHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L2NhX3B1YmJs"
- + "aWNhL0NQU19JTlRFU0EuaHRtMA4GA1UdDwEB/wQEAwIGQDCBgwYDVR0jBHww"
- + "eoAUGQkDltG4xVgbfhDkbsT2oBIJEKihXKRaMFgxCzAJBgNVBAYTAklUMRow"
- + "GAYDVQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5B"
- + "LiAtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ80QETMDsGA1UdHwQ0MDIw"
- + "MKAuoCyGKmh0dHA6Ly9lLXRydXN0Y29tLmludGVzYS5pdC9DUkwvSU5URVNB"
- + "LmNybDAdBgNVHQ4EFgQU3+SLS/CpkIeeNQ8be2MXFiNdueEwDQYJKoZIhvcN"
- + "AQEFBQADggEBAIFvri9QlVkHqWwv8Hwpkejzd+0rnm+MYikI9pkw+VGeSkI6"
- + "Yr8vx27n9Da3yjYgxIQL6B0jwt9XmxoirkzBTcmTx3zxFJ8mBksXmtsPN+2l"
- + "yRa+rrTzUBgUYvPZB/dLGQ5V7Tkq2SPgMySZ+UCtxfYI3GslNjWV0DCYEcGJ"
- + "hcp9sOI7aMfgsFz0PROV4MYjGeFgy9N3FlVwy19NBDicJwwzFDU0SJvWb/uE"
- + "ikzZXxW4vVEwalgckpA8wHpbHwdlOtaKnNodcSpgrZBjJjfYmU/kM2Qv72mk"
- + "/oSxARRgB9oMBa2HOP40wSsgWHlNb7AMbImyKE7NQKYJejB++ajwywcxggM8"
- + "MIIDOAIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5UZS5TLkEu"
- + "IFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmljYXRpb24g"
- + "QXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYB+"
- + "lH2cwLqc91mP8prvgSV+RRzk13dJdZvdoVjgQoFrPhBiZCNIEoHvIhMMA/sM"
- + "X6euSRZk7EjD24FasCEGYyd0mJVLEy6TSPmuW+wWz/28w3a6IWXBGrbb/ild"
- + "/CJMkPgLPGgOVD1WDwiNKwfasiQSFtySf5DPn3jFevdLeMmEY6GCAjIwggEV"
- + "BgkqhkiG9w0BCQYxggEGMIIBAgIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYD"
- + "VQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAt"
- + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJ"
- + "KoZIhvcNAQEBBQAEgYBHlOULfT5GDigIvxP0qZOy8VbpntmzaPF55VV4buKV"
- + "35J+uHp98gXKp0LrHM69V5IRKuyuQzHHFBqsXxsRI9o6KoOfgliD9Xc+BeMg"
- + "dKzQhBhBYoFREq8hQM0nSbqDNHYAQyNHMzUA/ZQUO5dlFuH8Dw3iDYAhNtfd"
- + "PrlchKJthDCCARUGCSqGSIb3DQEJBjGCAQYwggECAgEBMGAwWDELMAkGA1UE"
- + "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ"
- + "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkCBEOdgPcwCQYF"
- + "Kw4DAhoFADANBgkqhkiG9w0BAQEFAASBgEeU5Qt9PkYOKAi/E/Spk7LxVume"
- + "2bNo8XnlVXhu4pXfkn64en3yBcqnQusczr1XkhEq7K5DMccUGqxfGxEj2joq"
- + "g5+CWIP1dz4F4yB0rNCEGEFigVESryFAzSdJuoM0dgBDI0czNQD9lBQ7l2UW"
- + "4fwPDeINgCE2190+uVyEom2E");
-
- byte[] noSignedAttrSample2 = Base64.decode(
- "MIIIlAYJKoZIhvcNAQcCoIIIhTCCCIECAQExCzAJBgUrDgMCGgUAMAsGCSqG"
- + "SIb3DQEHAaCCB3UwggOtMIIDa6ADAgECAgEzMAsGByqGSM44BAMFADCBkDEL"
- + "MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlQYWxvIEFsdG8x"
- + "HTAbBgNVBAoTFFN1biBNaWNyb3N5c3RlbXMgSW5jMSMwIQYDVQQLExpKYXZh"
- + "IFNvZnR3YXJlIENvZGUgU2lnbmluZzEcMBoGA1UEAxMTSkNFIENvZGUgU2ln"
- + "bmluZyBDQTAeFw0wMTA1MjkxNjQ3MTFaFw0wNjA1MjgxNjQ3MTFaMG4xHTAb"
- + "BgNVBAoTFFN1biBNaWNyb3N5c3RlbXMgSW5jMSMwIQYDVQQLExpKYXZhIFNv"
- + "ZnR3YXJlIENvZGUgU2lnbmluZzEoMCYGA1UEAxMfVGhlIExlZ2lvbiBvZiB0"
- + "aGUgQm91bmN5IENhc3RsZTCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OB"
- + "HXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2"
- + "y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUP"
- + "BPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvM"
- + "spK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9"
- + "B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCj"
- + "rh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtV"
- + "JWQBTDv+z0kqA4GEAAKBgBWry/FCAZ6miyy39+ftsa+h9lxoL+JtV0MJcUyQ"
- + "E4VAhpAwWb8vyjba9AwOylYQTktHX5sAkFvjBiU0LOYDbFSTVZSHMRJgfjxB"
- + "SHtICjOEvr1BJrrOrdzqdxcOUge5n7El124BCrv91x5Ol8UTwtiO9LrRXF/d"
- + "SyK+RT5n1klRo3YwdDARBglghkgBhvhCAQEEBAMCAIcwDgYDVR0PAQH/BAQD"
- + "AgHGMB0GA1UdDgQWBBQwMY4NRcco1AO3w1YsokfDLVseEjAPBgNVHRMBAf8E"
- + "BTADAQH/MB8GA1UdIwQYMBaAFGXi9IbJ007wkU5Yomr12HhamsGmMAsGByqG"
- + "SM44BAMFAAMvADAsAhRmigTu6QV0sTfEkVljgij/hhdVfAIUQZvMxAnIHc30"
- + "y/u0C1T5UEG9glUwggPAMIIDfqADAgECAgEQMAsGByqGSM44BAMFADCBkDEL"
- + "MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlQYWxvIEFsdG8x"
- + "HTAbBgNVBAoTFFN1biBNaWNyb3N5c3RlbXMgSW5jMSMwIQYDVQQLExpKYXZh"
- + "IFNvZnR3YXJlIENvZGUgU2lnbmluZzEcMBoGA1UEAxMTSkNFIENvZGUgU2ln"
- + "bmluZyBDQTAeFw0wMTA0MjUwNzAwMDBaFw0yMDA0MjUwNzAwMDBaMIGQMQsw"
- + "CQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0bzEd"
- + "MBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxIzAhBgNVBAsTGkphdmEg"
- + "U29mdHdhcmUgQ29kZSBTaWduaW5nMRwwGgYDVQQDExNKQ0UgQ29kZSBTaWdu"
- + "aW5nIENBMIIBtzCCASwGByqGSM44BAEwggEfAoGBAOuvNwQeylEeaV2w8o/2"
- + "tUkfxqSZBdcpv3S3avUZ2B7kG/gKAZqY/3Cr4kpWhmxTs/zhyIGMMfDE87CL"
- + "5nAG7PdpaNuDTHIpiSk2F1w7SgegIAIqRpdRHXDICBgLzgxum3b3BePn+9Nh"
- + "eeFgmiSNBpWDPFEg4TDPOFeCphpyDc7TAhUAhCVF4bq5qWKreehbMLiJaxv/"
- + "e3UCgYEAq8l0e3Tv7kK1alNNO92QBnJokQ8LpCl2LlU71a5NZVx+KjoEpmem"
- + "0HGqpde34sFyDaTRqh6SVEwgAAmisAlBGTMAssNcrkL4sYvKfJbYEH83RFuq"
- + "zHjI13J2N2tAmahVZvqoAx6LShECactMuCUGHKB30sms0j3pChD6dnC3+9wD"
- + "gYQAAoGALQmYXKy4nMeZfu4gGSo0kPnXq6uu3WtylQ1m+O8nj0Sy7ShEx/6v"
- + "sKYnbwBnRYJbB6hWVjvSKVFhXmk51y50dxLPGUr1LcjLcmHETm/6R0M/FLv6"
- + "vBhmKMLZZot6LS/CYJJLFP5YPiF/aGK+bEhJ+aBLXoWdGRD5FUVRG3HU9wuj"
- + "ZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1Ud"
- + "IwQYMBaAFGXi9IbJ007wkU5Yomr12HhamsGmMB0GA1UdDgQWBBRl4vSGydNO"
- + "8JFOWKJq9dh4WprBpjALBgcqhkjOOAQDBQADLwAwLAIUKvfPPJdd+Xi2CNdB"
- + "tNkNRUzktJwCFEXNdWkOIfod1rMpsun3Mx0z/fxJMYHoMIHlAgEBMIGWMIGQ"
- + "MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0"
- + "bzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxIzAhBgNVBAsTGkph"
- + "dmEgU29mdHdhcmUgQ29kZSBTaWduaW5nMRwwGgYDVQQDExNKQ0UgQ29kZSBT"
- + "aWduaW5nIENBAgEzMAkGBSsOAwIaBQAwCwYHKoZIzjgEAQUABC8wLQIVAIGV"
- + "khm+kbV4a/+EP45PHcq0hIViAhR4M9os6IrJnoEDS3Y3l7O6zrSosA==");
-
- private JcaX509CertSelectorConverter selectorConverter = new JcaX509CertSelectorConverter();
-
- /*
- *
- * INFRASTRUCTURE
- *
- */
-
- public SignedDataTest(String name)
- {
- super(name);
- }
-
- public static void main(String args[])
- {
-
- junit.textui.TestRunner.run(SignedDataTest.class);
- }
-
- public static Test suite()
- throws Exception
- {
- init();
-
- return new CMSTestSetup(new TestSuite(SignedDataTest.class));
- }
-
- private static void init()
- throws Exception
- {
- if (!_initialised)
- {
- _initialised = true;
-
- _origDN = "O=Bouncy Castle, C=AU";
- _origKP = CMSTestUtil.makeKeyPair();
- _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _origKP, _origDN);
-
- _signDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
- _signKP = CMSTestUtil.makeKeyPair();
- _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _origKP, _origDN);
-
- _signGostKP = CMSTestUtil.makeGostKeyPair();
- _signGostCert = CMSTestUtil.makeCertificate(_signGostKP, _signDN, _origKP, _origDN);
-
- _signDsaKP = CMSTestUtil.makeDsaKeyPair();
- _signDsaCert = CMSTestUtil.makeCertificate(_signDsaKP, _signDN, _origKP, _origDN);
-
- _signEcDsaKP = CMSTestUtil.makeEcDsaKeyPair();
- _signEcDsaCert = CMSTestUtil.makeCertificate(_signEcDsaKP, _signDN, _origKP, _origDN);
-
- _signEcGostKP = CMSTestUtil.makeEcGostKeyPair();
- _signEcGostCert = CMSTestUtil.makeCertificate(_signEcGostKP, _signDN, _origKP, _origDN);
-
- _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
- _reciKP = CMSTestUtil.makeKeyPair();
- _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN);
-
- _signCrl = CMSTestUtil.makeCrl(_signKP);
- }
- }
-
- private void verifySignatures(CMSSignedData s, byte[] contentDigest)
- throws Exception
- {
- CertStore certStore = s.getCertificatesAndCRLs("Collection", BC);
- SignerInformationStore signers = s.getSignerInfos();
-
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certStore.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
-
- if (contentDigest != null)
- {
- assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest()));
- }
- }
-
- Collection certColl = certStore.getCertificates(null);
- Collection crlColl = certStore.getCRLs(null);
-
- assertEquals(certColl.size(), s.getCertificates("Collection", BC).getMatches(null).size());
- assertEquals(crlColl.size(), s.getCRLs("Collection", BC).getMatches(null).size());
- }
-
- private void verifySignatures(CMSSignedData s)
- throws Exception
- {
- verifySignatures(s, null);
- }
-
- public void testDetachedVerification()
- throws Exception
- {
- byte[] data = "Hello World!".getBytes();
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray(data);
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_MD5);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData s = gen.generate(msg, BC);
-
- MessageDigest sha1 = MessageDigest.getInstance("SHA1", BC);
- MessageDigest md5 = MessageDigest.getInstance("MD5", BC);
- Map hashes = new HashMap();
- byte[] sha1Hash = sha1.digest(data);
- byte[] md5Hash = md5.digest(data);
-
- hashes.put(CMSSignedDataGenerator.DIGEST_SHA1, sha1Hash);
- hashes.put(CMSSignedDataGenerator.DIGEST_MD5, md5Hash);
-
- s = new CMSSignedData(hashes, s.getEncoded());
-
- verifySignatures(s, null);
- }
-
- public void testSHA1AndMD5WithRSAEncapsulatedRepeated()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_MD5);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData s = gen.generate(msg, true, BC);
-
- ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded());
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
-
- certs = s.getCertificatesAndCRLs("Collection", BC);
-
- SignerInformationStore signers = s.getSignerInfos();
-
- assertEquals(2, signers.size());
-
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
- SignerId sid = null;
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certs.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- sid = signer.getSID();
-
- assertEquals(true, signer.verify(cert, BC));
-
- //
- // check content digest
- //
-
- byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(signer.getDigestAlgOID());
-
- AttributeTable table = signer.getSignedAttributes();
- Attribute hash = table.get(CMSAttributes.messageDigest);
-
- assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets()));
- }
-
- c = signers.getSigners(sid);
-
- assertEquals(2, c.size());
-
-
- //
- // try using existing signer
- //
-
- gen = new CMSSignedDataGenerator();
-
- gen.addSigners(s.getSignerInfos());
-
- gen.addCertificatesAndCRLs(s.getCertificatesAndCRLs("Collection", BC));
-
- s = gen.generate(msg, true, BC);
-
- bIn = new ByteArrayInputStream(s.getEncoded());
- aIn = new ASN1InputStream(bIn);
-
- s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
-
- certs = s.getCertificatesAndCRLs("Collection", BC);
-
- signers = s.getSignerInfos();
- c = signers.getSigners();
- it = c.iterator();
-
- assertEquals(2, c.size());
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certs.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
- }
-
- checkSignerStoreReplacement(s, signers);
- }
-
- public void testSHA1WithRSANoAttributes()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello world!".getBytes());
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData s = gen.generate(CMSSignedDataGenerator.DATA, msg, false, BC, false);
-
- //
- // compute expected content digest
- //
- MessageDigest md = MessageDigest.getInstance("SHA1", BC);
-
- verifySignatures(s, md.digest("Hello world!".getBytes()));
- }
-
- public void testSHA1WithRSAViaConfig()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello world!".getBytes());
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- // set some bogus mappings.
- CMSConfig.setSigningEncryptionAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption.getId(), "XXXX");
- CMSConfig.setSigningDigestAlgorithmMapping(OIWObjectIdentifiers.idSHA1.getId(), "YYYY");
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData s;
-
- try
- {
- // try the bogus mappings
- s = gen.generate(CMSSignedDataGenerator.DATA, msg, false, BC, false);
- }
- catch (NoSuchAlgorithmException e)
- {
- if (!e.getMessage().startsWith("Unknown signature type requested: YYYYWITHXXXX"))
- {
- throw e;
- }
- }
- finally
- {
- // reset to the real ones
- CMSConfig.setSigningEncryptionAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption.getId(), "RSA");
- CMSConfig.setSigningDigestAlgorithmMapping(OIWObjectIdentifiers.idSHA1.getId(), "SHA1");
- }
-
- s = gen.generate(CMSSignedDataGenerator.DATA, msg, false, BC, false);
-
- //
- // compute expected content digest
- //
- MessageDigest md = MessageDigest.getInstance("SHA1", BC);
-
- verifySignatures(s, md.digest("Hello world!".getBytes()));
- }
-
- public void testSHA1WithRSAAndAttributeTable()
- throws Exception
- {
- MessageDigest md = MessageDigest.getInstance("SHA1", BC);
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello world!".getBytes());
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- Attribute attr = new Attribute(CMSAttributes.messageDigest,
- new DERSet(
- new DEROctetString(
- md.digest("Hello world!".getBytes()))));
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(attr);
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1, new AttributeTable(v), null);
-
- gen.addCertificatesAndCRLs(certs);
-
-
- CMSSignedData s = gen.generate(CMSSignedDataGenerator.DATA, null, false, BC);
-
- //
- // the signature is detached, so need to add msg before passing on
- //
- s = new CMSSignedData(msg, s.getEncoded());
- //
- // compute expected content digest
- //
-
- verifySignatures(s, md.digest("Hello world!".getBytes()));
- }
-
- public void testSHA1WithRSAEncapsulated()
- throws Exception
- {
- encapsulatedTest(_signKP, _signCert, CMSSignedDataGenerator.DIGEST_SHA1);
- }
-
- public void testSHA1WithRSAEncapsulatedSubjectKeyID()
- throws Exception
- {
- subjectKeyIDTest(_signKP, _signCert, CMSSignedDataGenerator.DIGEST_SHA1);
- }
-
- public void testSHA1WithRSAPSS()
- throws Exception
- {
- rsaPSSTest("SHA1", CMSSignedDataGenerator.DIGEST_SHA1);
- }
-
- public void testSHA224WithRSAPSS()
- throws Exception
- {
- rsaPSSTest("SHA224", CMSSignedDataGenerator.DIGEST_SHA224);
- }
-
- public void testSHA256WithRSAPSS()
- throws Exception
- {
- rsaPSSTest("SHA256", CMSSignedDataGenerator.DIGEST_SHA256);
- }
-
- public void testSHA384WithRSAPSS()
- throws Exception
- {
- rsaPSSTest("SHA384", CMSSignedDataGenerator.DIGEST_SHA384);
- }
-
- public void testSHA224WithRSAEncapsulated()
- throws Exception
- {
- encapsulatedTest(_signKP, _signCert, CMSSignedDataGenerator.DIGEST_SHA224);
- }
-
- public void testSHA256WithRSAEncapsulated()
- throws Exception
- {
- encapsulatedTest(_signKP, _signCert, CMSSignedDataGenerator.DIGEST_SHA256);
- }
-
- public void testRIPEMD128WithRSAEncapsulated()
- throws Exception
- {
- encapsulatedTest(_signKP, _signCert, CMSSignedDataGenerator.DIGEST_RIPEMD128);
- }
-
- public void testRIPEMD160WithRSAEncapsulated()
- throws Exception
- {
- encapsulatedTest(_signKP, _signCert, CMSSignedDataGenerator.DIGEST_RIPEMD160);
- }
-
- public void testRIPEMD256WithRSAEncapsulated()
- throws Exception
- {
- encapsulatedTest(_signKP, _signCert, CMSSignedDataGenerator.DIGEST_RIPEMD256);
- }
-
- public void testECDSAEncapsulated()
- throws Exception
- {
- encapsulatedTest(_signEcDsaKP, _signEcDsaCert, CMSSignedDataGenerator.DIGEST_SHA1);
- }
-
- public void testECDSAEncapsulatedSubjectKeyID()
- throws Exception
- {
- subjectKeyIDTest(_signEcDsaKP, _signEcDsaCert, CMSSignedDataGenerator.DIGEST_SHA1);
- }
-
- public void testECDSASHA224Encapsulated()
- throws Exception
- {
- encapsulatedTest(_signEcDsaKP, _signEcDsaCert, CMSSignedDataGenerator.DIGEST_SHA224);
- }
-
- public void testECDSASHA256Encapsulated()
- throws Exception
- {
- encapsulatedTest(_signEcDsaKP, _signEcDsaCert, CMSSignedDataGenerator.DIGEST_SHA256);
- }
-
- public void testECDSASHA384Encapsulated()
- throws Exception
- {
- encapsulatedTest(_signEcDsaKP, _signEcDsaCert, CMSSignedDataGenerator.DIGEST_SHA384);
- }
-
- public void testECDSASHA512Encapsulated()
- throws Exception
- {
- encapsulatedTest(_signEcDsaKP, _signEcDsaCert, CMSSignedDataGenerator.DIGEST_SHA512);
- }
-
- public void testECDSASHA512EncapsulatedWithKeyFactoryAsEC()
- throws Exception
- {
- X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(_signEcDsaKP.getPublic().getEncoded());
- PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(_signEcDsaKP.getPrivate().getEncoded());
- KeyFactory keyFact = KeyFactory.getInstance("EC", BC);
- KeyPair kp = new KeyPair(keyFact.generatePublic(pubSpec), keyFact.generatePrivate(privSpec));
-
- encapsulatedTest(kp, _signEcDsaCert, CMSSignedDataGenerator.DIGEST_SHA512);
- }
-
- public void testDSAEncapsulated()
- throws Exception
- {
- encapsulatedTest(_signDsaKP, _signDsaCert, CMSSignedDataGenerator.DIGEST_SHA1);
- }
-
- public void testDSAEncapsulatedSubjectKeyID()
- throws Exception
- {
- subjectKeyIDTest(_signDsaKP, _signDsaCert, CMSSignedDataGenerator.DIGEST_SHA1);
- }
-
- public void testGOST3411WithGOST3410Encapsulated()
- throws Exception
- {
- encapsulatedTest(_signGostKP, _signGostCert, CMSSignedDataGenerator.DIGEST_GOST3411);
- }
-
- public void testGOST3411WithECGOST3410Encapsulated()
- throws Exception
- {
- encapsulatedTest(_signEcGostKP, _signEcGostCert, CMSSignedDataGenerator.DIGEST_GOST3411);
- }
-
- public void testSHA1WithRSACounterSignature()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
- certList.add(_signCert);
- certList.add(_origCert);
-
- certList.add(_signCrl);
-
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_signKP.getPrivate(), _signCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certsAndCrls);
-
- CMSSignedData s = gen.generate(msg, true, BC);
- SignerInformation origSigner = (SignerInformation)s.getSignerInfos().getSigners().toArray()[0];
- SignerInformationStore counterSigners1 = gen.generateCounterSigners(origSigner, BC);
- SignerInformationStore counterSigners2 = gen.generateCounterSigners(origSigner, BC);
-
- SignerInformation signer1 = SignerInformation.addCounterSigners(origSigner, counterSigners1);
- SignerInformation signer2 = SignerInformation.addCounterSigners(signer1, counterSigners2);
-
- SignerInformationStore cs = signer2.getCounterSignatures();
- Collection csSigners = cs.getSigners();
- assertEquals(2, csSigners.size());
-
- Iterator it = csSigners.iterator();
- while (it.hasNext())
- {
- SignerInformation cSigner = (SignerInformation)it.next();
- Collection certCollection = certsAndCrls.getCertificates(selectorConverter.getCertSelector(cSigner.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertNull(cSigner.getSignedAttributes().get(PKCSObjectIdentifiers.pkcs_9_at_contentType));
- assertEquals(true, cSigner.verify(cert, BC));
- }
- }
-
- private void rsaPSSTest(String digestName, String digestOID)
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello world!".getBytes());
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.ENCRYPTION_RSA_PSS, digestOID);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData s = gen.generate(CMSSignedDataGenerator.DATA, msg, false, BC, false);
-
- //
- // compute expected content digest
- //
- MessageDigest md = MessageDigest.getInstance(digestName, BC);
-
- verifySignatures(s, md.digest("Hello world!".getBytes()));
- }
-
- private void subjectKeyIDTest(
- KeyPair signaturePair,
- X509Certificate signatureCert,
- String digestAlgorithm)
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
- certList.add(signatureCert);
- certList.add(_origCert);
-
- certList.add(_signCrl);
-
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(signaturePair.getPrivate(), CMSTestUtil.createSubjectKeyId(signatureCert.getPublicKey()).getKeyIdentifier(), digestAlgorithm);
-
- gen.addCertificatesAndCRLs(certsAndCrls);
-
- CMSSignedData s = gen.generate(msg, true, BC);
-
- assertEquals(3, s.getVersion());
-
- ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded());
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
-
- certsAndCrls = s.getCertificatesAndCRLs("Collection", BC);
-
- SignerInformationStore signers = s.getSignerInfos();
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certsAndCrls.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
- }
-
- //
- // check for CRLs
- //
- Collection crls = certsAndCrls.getCRLs(null);
-
- assertEquals(1, crls.size());
-
- assertTrue(crls.contains(_signCrl));
-
- //
- // try using existing signer
- //
-
- gen = new CMSSignedDataGenerator();
-
- gen.addSigners(s.getSignerInfos());
-
- gen.addCertificatesAndCRLs(s.getCertificatesAndCRLs("Collection", BC));
-
- s = gen.generate(msg, true, BC);
-
- bIn = new ByteArrayInputStream(s.getEncoded());
- aIn = new ASN1InputStream(bIn);
-
- s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
-
- certsAndCrls = s.getCertificatesAndCRLs("Collection", BC);
-
- signers = s.getSignerInfos();
- c = signers.getSigners();
- it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certsAndCrls.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
- }
-
- checkSignerStoreReplacement(s, signers);
- }
-
- private void encapsulatedTest(
- KeyPair signaturePair,
- X509Certificate signatureCert,
- String digestAlgorithm)
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
- certList.add(signatureCert);
- certList.add(_origCert);
-
- certList.add(_signCrl);
-
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(signaturePair.getPrivate(), signatureCert, digestAlgorithm);
-
- gen.addCertificatesAndCRLs(certsAndCrls);
-
- CMSSignedData s = gen.generate(msg, true, BC);
-
- ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded());
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
-
- certsAndCrls = s.getCertificatesAndCRLs("Collection", BC);
-
- SignerInformationStore signers = s.getSignerInfos();
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certsAndCrls.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
- }
-
- //
- // check for CRLs
- //
- Collection crls = certsAndCrls.getCRLs(null);
-
- assertEquals(1, crls.size());
-
- assertTrue(crls.contains(_signCrl));
-
- //
- // try using existing signer
- //
-
- gen = new CMSSignedDataGenerator();
-
- gen.addSigners(s.getSignerInfos());
-
- gen.addCertificatesAndCRLs(s.getCertificatesAndCRLs("Collection", BC));
-
- s = gen.generate(msg, true, BC);
-
- bIn = new ByteArrayInputStream(s.getEncoded());
- aIn = new ASN1InputStream(bIn);
-
- s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
-
- certsAndCrls = s.getCertificatesAndCRLs("Collection", BC);
-
- signers = s.getSignerInfos();
- c = signers.getSigners();
- it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certsAndCrls.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
- }
-
- checkSignerStoreReplacement(s, signers);
- }
-
- //
- // signerInformation store replacement test.
- //
- private void checkSignerStoreReplacement(
- CMSSignedData orig,
- SignerInformationStore signers)
- throws Exception
- {
- CMSSignedData s = CMSSignedData.replaceSigners(orig, signers);
-
- CertStore certs = s.getCertificatesAndCRLs("Collection", BC);
-
- signers = s.getSignerInfos();
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certs.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
- }
- }
-
- public void testUnsortedAttributes()
- throws Exception
- {
- CMSSignedData s = new CMSSignedData(new CMSProcessableByteArray(disorderedMessage), disorderedSet);
-
- CertStore certs = s.getCertificatesAndCRLs("Collection", BC);
-
- SignerInformationStore signers = s.getSignerInfos();
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certs.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
- }
- }
-
- public void testNullContentWithSigner()
- throws Exception
- {
- List certList = new ArrayList();
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData s = gen.generate(null, false, BC);
-
- ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded());
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
-
- verifySignatures(s);
- }
-
- public void testWithAttributeCertificate()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
-
- certList.add(_signDsaCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- X509AttributeCertificate attrCert = CMSTestUtil.getAttributeCertificate();
-
- X509Store store = X509Store.getInstance("AttributeCertificate/Collection",
- new X509CollectionStoreParameters(Collections.singleton(attrCert)), BC);
-
- gen.addAttributeCertificates(store);
-
- CMSSignedData sd = gen.generate(msg, BC);
-
- assertEquals(4, sd.getVersion());
-
- store = sd.getAttributeCertificates("Collection", BC);
-
- Collection coll = store.getMatches(null);
-
- assertEquals(1, coll.size());
-
- assertTrue(coll.contains(attrCert));
-
- //
- // create new certstore
- //
- certList = new ArrayList();
- certList.add(_origCert);
- certList.add(_signCert);
-
- certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
-
- //
- // replace certs
- //
- sd = CMSSignedData.replaceCertificatesAndCRLs(sd, certs);
-
- verifySignatures(sd);
- }
-
- public void testCertStoreReplacement()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
-
- certList.add(_signDsaCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData sd = gen.generate(msg, BC);
-
- //
- // create new certstore
- //
- certList = new ArrayList();
- certList.add(_origCert);
- certList.add(_signCert);
-
- certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- //
- // replace certs
- //
- sd = CMSSignedData.replaceCertificatesAndCRLs(sd, certs);
-
- verifySignatures(sd);
- }
-
- public void testEncapsulatedCertStoreReplacement()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
-
- certList.add(_signDsaCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData sd = gen.generate(msg, true, BC);
-
- //
- // create new certstore
- //
- certList = new ArrayList();
- certList.add(_origCert);
- certList.add(_signCert);
-
- certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- //
- // replace certs
- //
- sd = CMSSignedData.replaceCertificatesAndCRLs(sd, certs);
-
- verifySignatures(sd);
- }
-
- public void testCertOrdering1()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
- certList.add(_origCert);
- certList.add(_signCert);
- certList.add(_signDsaCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData sd = gen.generate(msg, true, BC);
-
- certs = sd.getCertificatesAndCRLs("Collection", BC);
- Iterator it = certs.getCertificates(null).iterator();
-
- assertEquals(_origCert, it.next());
- assertEquals(_signCert, it.next());
- assertEquals(_signDsaCert, it.next());
- }
-
- public void testCertOrdering2()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
- certList.add(_signCert);
- certList.add(_signDsaCert);
- certList.add(_origCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData sd = gen.generate(msg, true, BC);
-
- certs = sd.getCertificatesAndCRLs("Collection", BC);
- Iterator it = certs.getCertificates(null).iterator();
-
- assertEquals(_signCert, it.next());
- assertEquals(_signDsaCert, it.next());
- assertEquals(_origCert, it.next());
- }
-
- public void testSignerStoreReplacement()
- throws Exception
- {
- List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray("Hello World!".getBytes());
-
- certList.add(_origCert);
- certList.add(_signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), BC);
-
- CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA1);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData original = gen.generate(msg, true, BC);
-
- //
- // create new Signer
- //
- gen = new CMSSignedDataGenerator();
-
- gen.addSigner(_origKP.getPrivate(), _origCert, CMSSignedDataGenerator.DIGEST_SHA224);
-
- gen.addCertificatesAndCRLs(certs);
-
- CMSSignedData newSD = gen.generate(msg, true, BC);
-
- //
- // replace signer
- //
- CMSSignedData sd = CMSSignedData.replaceSigners(original, newSD.getSignerInfos());
-
- SignerInformation signer = (SignerInformation)sd.getSignerInfos().getSigners().iterator().next();
-
- assertEquals(CMSSignedDataGenerator.DIGEST_SHA224, signer.getDigestAlgOID());
-
- // we use a parser here as it requires the digests to be correct in the digest set, if it
- // isn't we'll get a NullPointerException
- CMSSignedDataParser sp = new CMSSignedDataParser(sd.getEncoded());
-
- sp.getSignedContent().drain();
-
- verifySignatures(sp);
- }
-
- public void testEncapsulatedSamples()
- throws Exception
- {
- testSample("PSSSignDataSHA1Enc.sig");
- testSample("PSSSignDataSHA256Enc.sig");
- testSample("PSSSignDataSHA512Enc.sig");
- }
-
- public void testSamples()
- throws Exception
- {
- testSample("PSSSignData.data", "PSSSignDataSHA1.sig");
- testSample("PSSSignData.data", "PSSSignDataSHA256.sig");
- testSample("PSSSignData.data", "PSSSignDataSHA512.sig");
- }
-
- public void testCounterSig()
- throws Exception
- {
- CMSSignedData sig = new CMSSignedData(getInput("counterSig.p7m"));
-
- SignerInformationStore ss = sig.getSignerInfos();
- Collection signers = ss.getSigners();
-
- SignerInformationStore cs = ((SignerInformation)signers.iterator().next()).getCounterSignatures();
- Collection csSigners = cs.getSigners();
- assertEquals(1, csSigners.size());
-
- Iterator it = csSigners.iterator();
- while (it.hasNext())
- {
- SignerInformation cSigner = (SignerInformation)it.next();
- Collection certCollection = sig.getCertificatesAndCRLs("Collection", BC).getCertificates(selectorConverter.getCertSelector(cSigner.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertNull(cSigner.getSignedAttributes().get(PKCSObjectIdentifiers.pkcs_9_at_contentType));
- assertEquals(true, cSigner.verify(cert, BC));
- }
-
- verifySignatures(sig);
- }
-
- private void testSample(String sigName)
- throws Exception
- {
- CMSSignedData sig = new CMSSignedData(getInput(sigName));
-
- verifySignatures(sig);
- }
-
- private void testSample(String messageName, String sigName)
- throws Exception
- {
- CMSSignedData sig = new CMSSignedData(new CMSProcessableByteArray(getInput(messageName)), getInput(sigName));
-
- verifySignatures(sig);
- }
-
- private byte[] getInput(String name)
- throws IOException
- {
- return Streams.readAll(getClass().getResourceAsStream(name));
- }
-
- public void testForMultipleCounterSignatures()
- throws Exception
- {
- CMSSignedData sd = new CMSSignedData(xtraCounterSig);
-
- for (Iterator sI = sd.getSignerInfos().getSigners().iterator(); sI.hasNext();)
- {
- SignerInformation sigI = (SignerInformation)sI.next();
-
- SignerInformationStore counter = sigI.getCounterSignatures();
- List sigs = new ArrayList(counter.getSigners());
-
- assertEquals(2, sigs.size());
- }
- }
-
- private void verifySignatures(CMSSignedDataParser sp)
- throws Exception
- {
- CertStore certs = sp.getCertificatesAndCRLs("Collection", BC);
- SignerInformationStore signers = sp.getSignerInfos();
-
- Collection c = signers.getSigners();
- Iterator it = c.iterator();
-
- while (it.hasNext())
- {
- SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certs.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
-
- Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
-
- assertEquals(true, signer.verify(cert, BC));
- }
- }
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/test/SunProviderTest.java b/bcpkix/src/main/java/org/bouncycastle/cms/test/SunProviderTest.java
index 9412b99..3ec8c5a 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/test/SunProviderTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/test/SunProviderTest.java
@@ -14,8 +14,6 @@ import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
-import java.security.cert.CertStore;
-import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,23 +26,37 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.X509Name;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
-import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSSignedDataParser;
import org.bouncycastle.cms.CMSSignedDataStreamGenerator;
+import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.CMSTypedStream;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.RecipientInformationStore;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
+import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
+import org.bouncycastle.cms.jcajce.JcaSignerInfoVerifierBuilder;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter;
+import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
+import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
+import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
+import org.bouncycastle.operator.DigestCalculatorProvider;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.bouncycastle.util.CollectionStore;
+import org.bouncycastle.util.Store;
import org.bouncycastle.x509.X509V3CertificateGenerator;
public class SunProviderTest
@@ -73,27 +85,26 @@ public class SunProviderTest
throws Exception
{
List certList = new ArrayList();
- CMSProcessable msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes());
+ CMSTypedData msg = new CMSProcessableByteArray(TEST_MESSAGE.getBytes());
- certList.add(keyCert);
+ certList.add(new X509CertificateHolder(keyCert.getEncoded()));
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), "SUN");
+ DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().build();
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
- gen.addSigner(keyPair.getPrivate(), keyCert, CMSSignedDataGenerator.DIGEST_SHA1);
+ gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").setProvider("SunRsaSign").build(keyPair.getPrivate()), keyCert));
- gen.addCertificatesAndCRLs(certsAndCrls);
+ gen.addCertificates(new CollectionStore(certList));
- CMSSignedData s = gen.generate(msg, true, "SunRsaSign");
+ CMSSignedData s = gen.generate(msg, true);
ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded());
ASN1InputStream aIn = new ASN1InputStream(bIn);
s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject()));
- certsAndCrls = s.getCertificatesAndCRLs("Collection", "SUN");
+ Store certsAndCrls = s.getCertificates();
SignerInformationStore signers = s.getSignerInfos();
Collection c = signers.getSigners();
@@ -102,12 +113,12 @@ public class SunProviderTest
while (it.hasNext())
{
SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certsAndCrls.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
+ Collection certCollection = certsAndCrls.getMatches(signer.getSID());
Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
+ X509Certificate cert = new JcaX509CertificateConverter().getCertificate((X509CertificateHolder)certIt.next());
- assertEquals(true, signer.verify(cert, "SunRsaSign"));
+ assertEquals(true, signer.verify(new JcaSignerInfoVerifierBuilder(new JcaDigestCalculatorProviderBuilder().build()).setProvider("SunRsaSign").build(cert)));
}
}
@@ -117,16 +128,15 @@ public class SunProviderTest
List certList = new ArrayList();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- certList.add(keyCert);
+ certList.add(new X509CertificateHolder(keyCert.getEncoded()));
- CertStore certsAndCrls = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), "SUN");
+ DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().build();
CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
- gen.addSigner(keyPair.getPrivate(), keyCert, CMSSignedDataStreamGenerator.DIGEST_SHA1, "SunRsaSign");
+ gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA1withRSA").setProvider("SunRsaSign").build(keyPair.getPrivate()), keyCert));
- gen.addCertificatesAndCRLs(certsAndCrls);
+ gen.addCertificates(new CollectionStore(certList));
OutputStream sigOut = gen.open(bOut);
@@ -134,7 +144,7 @@ public class SunProviderTest
sigOut.close();
- CMSSignedDataParser sp = new CMSSignedDataParser(
+ CMSSignedDataParser sp = new CMSSignedDataParser(digCalcProv,
new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray());
sp.getSignedContent().drain();
@@ -145,7 +155,7 @@ public class SunProviderTest
MessageDigest md = MessageDigest.getInstance("SHA1", "SUN");
byte[] contentDigest = md.digest(TEST_MESSAGE.getBytes());
- CertStore certStore = sp.getCertificatesAndCRLs("Collection", "SUN");
+ Store certStore = sp.getCertificates();
SignerInformationStore signers = sp.getSignerInfos();
Collection c = signers.getSigners();
@@ -154,12 +164,12 @@ public class SunProviderTest
while (it.hasNext())
{
SignerInformation signer = (SignerInformation)it.next();
- Collection certCollection = certStore.getCertificates(selectorConverter.getCertSelector(signer.getSID()));
+ Collection certCollection = certStore.getMatches(signer.getSID());
Iterator certIt = certCollection.iterator();
- X509Certificate cert = (X509Certificate)certIt.next();
+ X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
- assertEquals(true, signer.verify(cert, "SunRsaSign"));
+ assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("SunRsaSign").build(new JcaX509CertificateConverter().getCertificate(cert))));
if (contentDigest != null)
{
@@ -199,11 +209,11 @@ public class SunProviderTest
CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
- edGen.addKeyTransRecipient(keyCert);
+ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(keyCert).setProvider("SunJCE"));
CMSEnvelopedData ed = edGen.generate(
new CMSProcessableByteArray(data),
- algorithm, "SunJCE");
+ new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(algorithm)).setProvider("SunJCE").build());
RecipientInformationStore recipients = ed.getRecipientInfos();
@@ -222,7 +232,7 @@ public class SunProviderTest
assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());
- byte[] recData = recipient.getContent(keyPair.getPrivate(), "SunJCE");
+ byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(keyPair.getPrivate()).setProvider("SunJCE"));
assertEquals(true, Arrays.equals(data, recData));
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/dvcs/package.html b/bcpkix/src/main/java/org/bouncycastle/dvcs/package.html
deleted file mode 100644
index aecbd70..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/dvcs/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for dealing "Internet X.509 Public Key Infrastructure Data Validation and Certification Server Protocols" - RFC 3029.
-</body>
-</html>
diff --git a/bcpkix/src/main/java/org/bouncycastle/eac/package.html b/bcpkix/src/main/java/org/bouncycastle/eac/package.html
deleted file mode 100644
index 97c41fa..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/eac/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Base classes Extended Access Control (EAC) Certificates as described in "Technical Guideline, Advanced Security Mechanisms for Machine Readable Travel Documents, Extended Access Control (EAC), Version 1.0.1, BSI 2006".
-</body>
-</html>
diff --git a/bcpkix/src/main/java/org/bouncycastle/mozilla/package.html b/bcpkix/src/main/java/org/bouncycastle/mozilla/package.html
deleted file mode 100644
index dd2203e..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/mozilla/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support class for mozilla signed public key and challenge.
-</body>
-</html>
diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/PEMReader.java b/bcpkix/src/main/java/org/bouncycastle/openssl/PEMReader.java
deleted file mode 100644
index b11ae12..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/openssl/PEMReader.java
+++ /dev/null
@@ -1,1023 +0,0 @@
-package org.bouncycastle.openssl;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.Reader;
-import java.security.AlgorithmParameters;
-import java.security.Key;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.PublicKey;
-import java.security.Security;
-import java.security.cert.CertificateFactory;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.DSAPrivateKeySpec;
-import java.security.spec.DSAPublicKeySpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.RSAPrivateCrtKeySpec;
-import java.security.spec.RSAPublicKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-import javax.crypto.Cipher;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.PBEKeySpec;
-import javax.crypto.spec.PBEParameterSpec;
-import javax.crypto.spec.RC2ParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
-import org.bouncycastle.asn1.pkcs.EncryptionScheme;
-import org.bouncycastle.asn1.pkcs.KeyDerivationFunc;
-import org.bouncycastle.asn1.pkcs.PBEParameter;
-import org.bouncycastle.asn1.pkcs.PBES2Parameters;
-import org.bouncycastle.asn1.pkcs.PBKDF2Params;
-import org.bouncycastle.asn1.pkcs.PKCS12PBEParams;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.pkcs.RSAPublicKey;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
-import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.jce.ECNamedCurveTable;
-import org.bouncycastle.jce.PKCS10CertificationRequest;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.io.pem.PemHeader;
-import org.bouncycastle.util.io.pem.PemObject;
-import org.bouncycastle.util.io.pem.PemObjectParser;
-import org.bouncycastle.util.io.pem.PemReader;
-import org.bouncycastle.x509.X509V2AttributeCertificate;
-
-/**
- * Class for reading OpenSSL PEM encoded streams containing
- * X509 certificates, PKCS8 encoded keys and PKCS7 objects.
- * <p>
- * In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and
- * Certificates will be returned using the appropriate java.security type (KeyPair, PublicKey, X509Certificate,
- * or X509CRL). In the case of a Certificate Request a PKCS10CertificationRequest will be returned.
- * </p>
- *
- * @deprecated use PEMParser
- */
-public class PEMReader
- extends PemReader
-{
- private final Map parsers = new HashMap();
-
- private PasswordFinder pFinder;
-
-
- /**
- * Create a new PEMReader
- *
- * @param reader the Reader
- * @deprecated use PEMParser
- */
- public PEMReader(
- Reader reader)
- {
- this(reader, null, "BC");
- }
-
- /**
- * Create a new PEMReader with a password finder
- *
- * @param reader the Reader
- * @param pFinder the password finder
- * @deprecated use PEMParser
- */
- public PEMReader(
- Reader reader,
- PasswordFinder pFinder)
- {
- this(reader, pFinder, "BC");
- }
-
- /**
- * Create a new PEMReader with a password finder
- *
- * @param reader the Reader
- * @param pFinder the password finder
- * @param provider the cryptography provider to use
- * @deprecated use PEMParser
- */
- public PEMReader(
- Reader reader,
- PasswordFinder pFinder,
- String provider)
- {
- this(reader, pFinder, provider, provider);
- }
-
- /**
- * Create a new PEMReader with a password finder and differing providers for secret and public key
- * operations.
- *
- * @param reader the Reader
- * @param pFinder the password finder
- * @param symProvider provider to use for symmetric operations
- * @param asymProvider provider to use for asymmetric (public/private key) operations
- * @deprecated use PEMParser
- */
- public PEMReader(
- Reader reader,
- PasswordFinder pFinder,
- String symProvider,
- String asymProvider)
- {
- super(reader);
-
- this.pFinder = pFinder;
-
- parsers.put("CERTIFICATE REQUEST", new PKCS10CertificationRequestParser());
- parsers.put("NEW CERTIFICATE REQUEST", new PKCS10CertificationRequestParser());
- parsers.put("CERTIFICATE", new X509CertificateParser(asymProvider));
- parsers.put("X509 CERTIFICATE", new X509CertificateParser(asymProvider));
- parsers.put("X509 CRL", new X509CRLParser(asymProvider));
- parsers.put("PKCS7", new PKCS7Parser());
- parsers.put("ATTRIBUTE CERTIFICATE", new X509AttributeCertificateParser());
- parsers.put("EC PARAMETERS", new ECNamedCurveSpecParser());
- parsers.put("PUBLIC KEY", new PublicKeyParser(asymProvider));
- parsers.put("RSA PUBLIC KEY", new RSAPublicKeyParser(asymProvider));
- parsers.put("RSA PRIVATE KEY", new RSAKeyPairParser(symProvider, asymProvider));
- parsers.put("DSA PRIVATE KEY", new DSAKeyPairParser(symProvider, asymProvider));
- parsers.put("EC PRIVATE KEY", new ECDSAKeyPairParser(symProvider, asymProvider));
- parsers.put("ENCRYPTED PRIVATE KEY", new EncryptedPrivateKeyParser(symProvider, asymProvider));
- parsers.put("PRIVATE KEY", new PrivateKeyParser(asymProvider));
- }
-
- public Object readObject()
- throws IOException
- {
- PemObject obj = readPemObject();
-
- if (obj != null)
- {
- String type = obj.getType();
- if (parsers.containsKey(type))
- {
- return ((PemObjectParser)parsers.get(type)).parseObject(obj);
- }
- else
- {
- throw new IOException("unrecognised object: " + type);
- }
- }
-
- return null;
- }
-
- private abstract class KeyPairParser
- implements PemObjectParser
- {
- protected String symProvider;
-
- public KeyPairParser(String symProvider)
- {
- this.symProvider = symProvider;
- }
-
- /**
- * Read a Key Pair
- */
- protected ASN1Sequence readKeyPair(
- PemObject obj)
- throws IOException
- {
- boolean isEncrypted = false;
- String dekInfo = null;
- List headers = obj.getHeaders();
-
- for (Iterator it = headers.iterator(); it.hasNext(); )
- {
- PemHeader hdr = (PemHeader)it.next();
-
- if (hdr.getName().equals("Proc-Type") && hdr.getValue().equals("4,ENCRYPTED"))
- {
- isEncrypted = true;
- }
- else if (hdr.getName().equals("DEK-Info"))
- {
- dekInfo = hdr.getValue();
- }
- }
-
- //
- // extract the key
- //
- byte[] keyBytes = obj.getContent();
-
- if (isEncrypted)
- {
- if (pFinder == null)
- {
- throw new PasswordException("No password finder specified, but a password is required");
- }
-
- char[] password = pFinder.getPassword();
-
- if (password == null)
- {
- throw new PasswordException("Password is null, but a password is required");
- }
-
- StringTokenizer tknz = new StringTokenizer(dekInfo, ",");
- String dekAlgName = tknz.nextToken();
- byte[] iv = Hex.decode(tknz.nextToken());
-
- keyBytes = crypt(false, symProvider, keyBytes, password, dekAlgName, iv);
- }
-
- try
- {
- return ASN1Sequence.getInstance(ASN1Primitive.fromByteArray(keyBytes));
- }
- catch (IOException e)
- {
- if (isEncrypted)
- {
- throw new PEMException("exception decoding - please check password and data.", e);
- }
- else
- {
- throw new PEMException(e.getMessage(), e);
- }
- }
- catch (IllegalArgumentException e)
- {
- if (isEncrypted)
- {
- throw new PEMException("exception decoding - please check password and data.", e);
- }
- else
- {
- throw new PEMException(e.getMessage(), e);
- }
- }
- }
- }
-
- private class DSAKeyPairParser
- extends KeyPairParser
- {
- private String asymProvider;
-
- public DSAKeyPairParser(String symProvider, String asymProvider)
- {
- super(symProvider);
-
- this.asymProvider = asymProvider;
- }
-
- public Object parseObject(PemObject obj)
- throws IOException
- {
- try
- {
- ASN1Sequence seq = readKeyPair(obj);
-
- if (seq.size() != 6)
- {
- throw new PEMException("malformed sequence in DSA private key");
- }
-
- // DERInteger v = (DERInteger)seq.getObjectAt(0);
- DERInteger p = (DERInteger)seq.getObjectAt(1);
- DERInteger q = (DERInteger)seq.getObjectAt(2);
- DERInteger g = (DERInteger)seq.getObjectAt(3);
- DERInteger y = (DERInteger)seq.getObjectAt(4);
- DERInteger x = (DERInteger)seq.getObjectAt(5);
-
- DSAPrivateKeySpec privSpec = new DSAPrivateKeySpec(
- x.getValue(), p.getValue(),
- q.getValue(), g.getValue());
- DSAPublicKeySpec pubSpec = new DSAPublicKeySpec(
- y.getValue(), p.getValue(),
- q.getValue(), g.getValue());
-
- KeyFactory fact = KeyFactory.getInstance("DSA", asymProvider);
-
- return new KeyPair(
- fact.generatePublic(pubSpec),
- fact.generatePrivate(privSpec));
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PEMException(
- "problem creating DSA private key: " + e.toString(), e);
- }
- }
- }
-
- private class ECDSAKeyPairParser
- extends KeyPairParser
- {
- private String asymProvider;
-
- public ECDSAKeyPairParser(String symProvider, String asymProvider)
- {
- super(symProvider);
-
- this.asymProvider = asymProvider;
- }
-
- public Object parseObject(PemObject obj)
- throws IOException
- {
- try
- {
- ASN1Sequence seq = readKeyPair(obj);
-
- org.bouncycastle.asn1.sec.ECPrivateKey pKey = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(seq);
- AlgorithmIdentifier algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, pKey.getParameters());
- PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey);
- SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pKey.getPublicKey().getBytes());
-
- PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privInfo.getEncoded());
- X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubInfo.getEncoded());
-
-
- KeyFactory fact = KeyFactory.getInstance("ECDSA", asymProvider);
-
-
- return new KeyPair(
- fact.generatePublic(pubSpec),
- fact.generatePrivate(privSpec));
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PEMException(
- "problem creating EC private key: " + e.toString(), e);
- }
- }
- }
-
- private class RSAKeyPairParser
- extends KeyPairParser
- {
- private String asymProvider;
-
- public RSAKeyPairParser(String symProvider, String asymProvider)
- {
- super(symProvider);
-
- this.asymProvider = asymProvider;
- }
-
- public Object parseObject(PemObject obj)
- throws IOException
- {
- try
- {
- ASN1Sequence seq = readKeyPair(obj);
-
- if (seq.size() != 9)
- {
- throw new PEMException("malformed sequence in RSA private key");
- }
-
- org.bouncycastle.asn1.pkcs.RSAPrivateKey keyStruct = org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(seq);
-
- RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(
- keyStruct.getModulus(), keyStruct.getPublicExponent());
- RSAPrivateCrtKeySpec privSpec = new RSAPrivateCrtKeySpec(
- keyStruct.getModulus(), keyStruct.getPublicExponent(), keyStruct.getPrivateExponent(),
- keyStruct.getPrime1(), keyStruct.getPrime2(),
- keyStruct.getExponent1(), keyStruct.getExponent2(),
- keyStruct.getCoefficient());
-
- KeyFactory fact = KeyFactory.getInstance("RSA", asymProvider);
-
- return new KeyPair(
- fact.generatePublic(pubSpec),
- fact.generatePrivate(privSpec));
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PEMException(
- "problem creating RSA private key: " + e.toString(), e);
- }
- }
- }
-
- private class PublicKeyParser
- implements PemObjectParser
- {
- private String provider;
-
- public PublicKeyParser(String provider)
- {
- this.provider = provider;
- }
-
- public Object parseObject(PemObject obj)
- throws IOException
- {
- KeySpec keySpec = new X509EncodedKeySpec(obj.getContent());
- String[] algorithms = {"DSA", "RSA"};
- for (int i = 0; i < algorithms.length; i++)
- {
- try
- {
- KeyFactory keyFact = KeyFactory.getInstance(algorithms[i], provider);
- PublicKey pubKey = keyFact.generatePublic(keySpec);
-
- return pubKey;
- }
- catch (NoSuchAlgorithmException e)
- {
- // ignore
- }
- catch (InvalidKeySpecException e)
- {
- // ignore
- }
- catch (NoSuchProviderException e)
- {
- throw new RuntimeException("can't find provider " + provider);
- }
- }
-
- return null;
- }
- }
-
- private class RSAPublicKeyParser
- implements PemObjectParser
- {
- private String provider;
-
- public RSAPublicKeyParser(String provider)
- {
- this.provider = provider;
- }
-
- public Object parseObject(PemObject obj)
- throws IOException
- {
- try
- {
- ASN1InputStream ais = new ASN1InputStream(obj.getContent());
- Object asnObject = ais.readObject();
- ASN1Sequence sequence = (ASN1Sequence)asnObject;
- RSAPublicKey rsaPubStructure = RSAPublicKey.getInstance(sequence);
- RSAPublicKeySpec keySpec = new RSAPublicKeySpec(
- rsaPubStructure.getModulus(),
- rsaPubStructure.getPublicExponent());
-
-
- KeyFactory keyFact = KeyFactory.getInstance("RSA", provider);
-
- return keyFact.generatePublic(keySpec);
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (NoSuchProviderException e)
- {
- throw new IOException("can't find provider " + provider);
- }
- catch (Exception e)
- {
- throw new PEMException("problem extracting key: " + e.toString(), e);
- }
- }
- }
-
- private class X509CertificateParser
- implements PemObjectParser
- {
- private String provider;
-
- public X509CertificateParser(String provider)
- {
- this.provider = provider;
- }
-
- /**
- * Reads in a X509Certificate.
- *
- * @return the X509Certificate
- * @throws IOException if an I/O error occured
- */
- public Object parseObject(PemObject obj)
- throws IOException
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(obj.getContent());
-
- try
- {
- CertificateFactory certFact
- = CertificateFactory.getInstance("X.509", provider);
-
- return certFact.generateCertificate(bIn);
- }
- catch (Exception e)
- {
- throw new PEMException("problem parsing cert: " + e.toString(), e);
- }
- }
- }
-
- private class X509CRLParser
- implements PemObjectParser
- {
- private String provider;
-
- public X509CRLParser(String provider)
- {
- this.provider = provider;
- }
-
- /**
- * Reads in a X509CRL.
- *
- * @return the X509Certificate
- * @throws IOException if an I/O error occured
- */
- public Object parseObject(PemObject obj)
- throws IOException
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(obj.getContent());
-
- try
- {
- CertificateFactory certFact
- = CertificateFactory.getInstance("X.509", provider);
-
- return certFact.generateCRL(bIn);
- }
- catch (Exception e)
- {
- throw new PEMException("problem parsing cert: " + e.toString(), e);
- }
- }
- }
-
- private class PKCS10CertificationRequestParser
- implements PemObjectParser
- {
- /**
- * Reads in a PKCS10 certification request.
- *
- * @return the certificate request.
- * @throws IOException if an I/O error occured
- */
- public Object parseObject(PemObject obj)
- throws IOException
- {
- try
- {
- return new PKCS10CertificationRequest(obj.getContent());
- }
- catch (Exception e)
- {
- throw new PEMException("problem parsing certrequest: " + e.toString(), e);
- }
- }
- }
-
- private class PKCS7Parser
- implements PemObjectParser
- {
- /**
- * Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS
- * API.
- *
- * @return the X509Certificate
- * @throws IOException if an I/O error occured
- */
- public Object parseObject(PemObject obj)
- throws IOException
- {
- try
- {
- ASN1InputStream aIn = new ASN1InputStream(obj.getContent());
-
- return ContentInfo.getInstance(aIn.readObject());
- }
- catch (Exception e)
- {
- throw new PEMException("problem parsing PKCS7 object: " + e.toString(), e);
- }
- }
- }
-
- private class X509AttributeCertificateParser
- implements PemObjectParser
- {
- public Object parseObject(PemObject obj)
- throws IOException
- {
- return new X509V2AttributeCertificate(obj.getContent());
- }
- }
-
- private class ECNamedCurveSpecParser
- implements PemObjectParser
- {
- public Object parseObject(PemObject obj)
- throws IOException
- {
- try
- {
- DERObjectIdentifier oid = (DERObjectIdentifier)ASN1Primitive.fromByteArray(obj.getContent());
-
- Object params = ECNamedCurveTable.getParameterSpec(oid.getId());
-
- if (params == null)
- {
- throw new IOException("object ID not found in EC curve table");
- }
-
- return params;
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PEMException("exception extracting EC named curve: " + e.toString());
- }
- }
- }
-
- private class EncryptedPrivateKeyParser
- implements PemObjectParser
- {
- private String symProvider;
- private String asymProvider;
-
- public EncryptedPrivateKeyParser(String symProvider, String asymProvider)
- {
- this.symProvider = symProvider;
- this.asymProvider = asymProvider;
- }
-
- /**
- * Reads in a X509CRL.
- *
- * @return the X509Certificate
- * @throws IOException if an I/O error occured
- */
- public Object parseObject(PemObject obj)
- throws IOException
- {
- try
- {
- EncryptedPrivateKeyInfo info = EncryptedPrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(obj.getContent()));
- AlgorithmIdentifier algId = info.getEncryptionAlgorithm();
-
- if (pFinder == null)
- {
- throw new PEMException("no PasswordFinder specified");
- }
-
- if (PEMUtilities.isPKCS5Scheme2(algId.getAlgorithm()))
- {
- PBES2Parameters params = PBES2Parameters.getInstance(algId.getParameters());
- KeyDerivationFunc func = params.getKeyDerivationFunc();
- EncryptionScheme scheme = params.getEncryptionScheme();
- PBKDF2Params defParams = (PBKDF2Params)func.getParameters();
-
- int iterationCount = defParams.getIterationCount().intValue();
- byte[] salt = defParams.getSalt();
-
- String algorithm = scheme.getAlgorithm().getId();
-
- SecretKey key = generateSecretKeyForPKCS5Scheme2(algorithm, pFinder.getPassword(), salt, iterationCount);
-
- Cipher cipher = Cipher.getInstance(algorithm, symProvider);
- AlgorithmParameters algParams = AlgorithmParameters.getInstance(algorithm, symProvider);
-
- algParams.init(scheme.getParameters().toASN1Primitive().getEncoded());
-
- cipher.init(Cipher.DECRYPT_MODE, key, algParams);
-
- PrivateKeyInfo pInfo = PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(cipher.doFinal(info.getEncryptedData())));
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pInfo.getEncoded());
-
- KeyFactory keyFact = KeyFactory.getInstance(pInfo.getPrivateKeyAlgorithm().getAlgorithm().getId(), asymProvider);
-
- return keyFact.generatePrivate(keySpec);
- }
- else if (PEMUtilities.isPKCS12(algId.getAlgorithm()))
- {
- PKCS12PBEParams params = PKCS12PBEParams.getInstance(algId.getParameters());
- String algorithm = algId.getAlgorithm().getId();
- PBEKeySpec pbeSpec = new PBEKeySpec(pFinder.getPassword());
-
- SecretKeyFactory secKeyFact = SecretKeyFactory.getInstance(algorithm, symProvider);
- PBEParameterSpec defParams = new PBEParameterSpec(params.getIV(), params.getIterations().intValue());
-
- Cipher cipher = Cipher.getInstance(algorithm, symProvider);
-
- cipher.init(Cipher.DECRYPT_MODE, secKeyFact.generateSecret(pbeSpec), defParams);
-
- PrivateKeyInfo pInfo = PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(cipher.doFinal(info.getEncryptedData())));
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pInfo.getEncoded());
-
- KeyFactory keyFact = KeyFactory.getInstance(pInfo.getPrivateKeyAlgorithm().getAlgorithm().getId(), asymProvider);
-
- return keyFact.generatePrivate(keySpec);
- }
- else if (PEMUtilities.isPKCS5Scheme1(algId.getAlgorithm()))
- {
- PBEParameter params = PBEParameter.getInstance(algId.getParameters());
- String algorithm = algId.getAlgorithm().getId();
- PBEKeySpec pbeSpec = new PBEKeySpec(pFinder.getPassword());
-
- SecretKeyFactory secKeyFact = SecretKeyFactory.getInstance(algorithm, symProvider);
- PBEParameterSpec defParams = new PBEParameterSpec(params.getSalt(), params.getIterationCount().intValue());
-
- Cipher cipher = Cipher.getInstance(algorithm, symProvider);
-
- cipher.init(Cipher.DECRYPT_MODE, secKeyFact.generateSecret(pbeSpec), defParams);
-
- PrivateKeyInfo pInfo = PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(cipher.doFinal(info.getEncryptedData())));
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pInfo.getEncoded());
-
- KeyFactory keyFact = KeyFactory.getInstance(pInfo.getPrivateKeyAlgorithm().getAlgorithm().getId(), asymProvider);
-
- return keyFact.generatePrivate(keySpec);
- }
- else
- {
- throw new PEMException("Unknown algorithm: " + algId.getAlgorithm());
- }
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new PEMException("problem parsing ENCRYPTED PRIVATE KEY: " + e.toString(), e);
- }
- }
- }
-
- private class PrivateKeyParser
- implements PemObjectParser
- {
- private String provider;
-
- public PrivateKeyParser(String provider)
- {
- this.provider = provider;
- }
-
- public Object parseObject(PemObject obj)
- throws IOException
- {
- try
- {
- PrivateKeyInfo info = PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(obj.getContent()));
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(obj.getContent());
-
- KeyFactory keyFact = KeyFactory.getInstance(info.getPrivateKeyAlgorithm().getAlgorithm().getId(), provider);
-
- return keyFact.generatePrivate(keySpec);
- }
- catch (Exception e)
- {
- throw new PEMException("problem parsing PRIVATE KEY: " + e.toString(), e);
- }
- }
- }
-
- static byte[] crypt(
- boolean encrypt,
- String provider,
- byte[] bytes,
- char[] password,
- String dekAlgName,
- byte[] iv)
- throws IOException
- {
- Provider prov = null;
- if (provider != null)
- {
- prov = Security.getProvider(provider);
- if (prov == null)
- {
- throw new EncryptionException("cannot find provider: " + provider);
- }
- }
-
- return crypt(encrypt, prov, bytes, password, dekAlgName, iv);
- }
-
- static byte[] crypt(
- boolean encrypt,
- Provider provider,
- byte[] bytes,
- char[] password,
- String dekAlgName,
- byte[] iv)
- throws IOException
- {
- AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
- String alg;
- String blockMode = "CBC";
- String padding = "PKCS5Padding";
- Key sKey;
-
- // Figure out block mode and padding.
- if (dekAlgName.endsWith("-CFB"))
- {
- blockMode = "CFB";
- padding = "NoPadding";
- }
- if (dekAlgName.endsWith("-ECB") ||
- "DES-EDE".equals(dekAlgName) ||
- "DES-EDE3".equals(dekAlgName))
- {
- // ECB is actually the default (though seldom used) when OpenSSL
- // uses DES-EDE (des2) or DES-EDE3 (des3).
- blockMode = "ECB";
- paramSpec = null;
- }
- if (dekAlgName.endsWith("-OFB"))
- {
- blockMode = "OFB";
- padding = "NoPadding";
- }
-
-
- // Figure out algorithm and key size.
- if (dekAlgName.startsWith("DES-EDE"))
- {
- alg = "DESede";
- // "DES-EDE" is actually des2 in OpenSSL-speak!
- // "DES-EDE3" is des3.
- boolean des2 = !dekAlgName.startsWith("DES-EDE3");
- sKey = getKey(password, alg, 24, iv, des2);
- }
- else if (dekAlgName.startsWith("DES-"))
- {
- alg = "DES";
- sKey = getKey(password, alg, 8, iv);
- }
- else if (dekAlgName.startsWith("BF-"))
- {
- alg = "Blowfish";
- sKey = getKey(password, alg, 16, iv);
- }
- else if (dekAlgName.startsWith("RC2-"))
- {
- alg = "RC2";
- int keyBits = 128;
- if (dekAlgName.startsWith("RC2-40-"))
- {
- keyBits = 40;
- }
- else if (dekAlgName.startsWith("RC2-64-"))
- {
- keyBits = 64;
- }
- sKey = getKey(password, alg, keyBits / 8, iv);
- if (paramSpec == null) // ECB block mode
- {
- paramSpec = new RC2ParameterSpec(keyBits);
- }
- else
- {
- paramSpec = new RC2ParameterSpec(keyBits, iv);
- }
- }
- else if (dekAlgName.startsWith("AES-"))
- {
- alg = "AES";
- byte[] salt = iv;
- if (salt.length > 8)
- {
- salt = new byte[8];
- System.arraycopy(iv, 0, salt, 0, 8);
- }
-
- int keyBits;
- if (dekAlgName.startsWith("AES-128-"))
- {
- keyBits = 128;
- }
- else if (dekAlgName.startsWith("AES-192-"))
- {
- keyBits = 192;
- }
- else if (dekAlgName.startsWith("AES-256-"))
- {
- keyBits = 256;
- }
- else
- {
- throw new EncryptionException("unknown AES encryption with private key");
- }
- sKey = getKey(password, "AES", keyBits / 8, salt);
- }
- else
- {
- throw new EncryptionException("unknown encryption with private key");
- }
-
- String transformation = alg + "/" + blockMode + "/" + padding;
-
- try
- {
- Cipher c = Cipher.getInstance(transformation, provider);
- int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
-
- if (paramSpec == null) // ECB block mode
- {
- c.init(mode, sKey);
- }
- else
- {
- c.init(mode, sKey, paramSpec);
- }
- return c.doFinal(bytes);
- }
- catch (Exception e)
- {
- throw new EncryptionException("exception using cipher - please check password and data.", e);
- }
- }
-
- private static SecretKey getKey(
- char[] password,
- String algorithm,
- int keyLength,
- byte[] salt)
- {
- return getKey(password, algorithm, keyLength, salt, false);
- }
-
- private static SecretKey getKey(
- char[] password,
- String algorithm,
- int keyLength,
- byte[] salt,
- boolean des2)
- {
- OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator();
-
- pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt);
-
- KeyParameter keyParam;
- keyParam = (KeyParameter)pGen.generateDerivedParameters(keyLength * 8);
- byte[] key = keyParam.getKey();
- if (des2 && key.length >= 24)
- {
- // For DES2, we must copy first 8 bytes into the last 8 bytes.
- System.arraycopy(key, 0, key, 16, 8);
- }
- return new javax.crypto.spec.SecretKeySpec(key, algorithm);
- }
-
-
- public static SecretKey generateSecretKeyForPKCS5Scheme2(String algorithm, char[] password, byte[] salt, int iterationCount)
- {
- PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
-
- generator.init(
- PBEParametersGenerator.PKCS5PasswordToBytes(password),
- salt,
- iterationCount);
-
- return new SecretKeySpec(((KeyParameter)generator.generateDerivedParameters(PEMUtilities.getKeySize(algorithm))).getKey(), algorithm);
- }
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/PEMWriter.java b/bcpkix/src/main/java/org/bouncycastle/openssl/PEMWriter.java
index c9ef265..e46c836 100644
--- a/bcpkix/src/main/java/org/bouncycastle/openssl/PEMWriter.java
+++ b/bcpkix/src/main/java/org/bouncycastle/openssl/PEMWriter.java
@@ -2,10 +2,8 @@ package org.bouncycastle.openssl;
import java.io.IOException;
import java.io.Writer;
-import java.security.SecureRandom;
import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
-import org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder;
import org.bouncycastle.util.io.pem.PemGenerationException;
import org.bouncycastle.util.io.pem.PemObjectGenerator;
import org.bouncycastle.util.io.pem.PemWriter;
@@ -16,8 +14,6 @@ import org.bouncycastle.util.io.pem.PemWriter;
public class PEMWriter
extends PemWriter
{
- private String provider;
-
/**
* Base constructor.
*
@@ -25,26 +21,12 @@ public class PEMWriter
*/
public PEMWriter(Writer out)
{
- this(out, "BC");
- }
-
- /**
- * @deprecated use constructor that just takes out, and writeObject(PEMEncryptor)
- * @param out
- * @param provider
- */
- public PEMWriter(
- Writer out,
- String provider)
- {
super(out);
-
- this.provider = provider;
}
public void writeObject(
- Object obj)
- throws IOException
+ Object obj)
+ throws IOException
{
writeObject(obj, null);
}
@@ -75,17 +57,4 @@ public class PEMWriter
{
super.writeObject(obj);
}
-
- /**
- * @deprecated use writeObject(obj, PEMEncryptor)
- */
- public void writeObject(
- Object obj,
- String algorithm,
- char[] password,
- SecureRandom random)
- throws IOException
- {
- this.writeObject(obj, new JcePEMEncryptorBuilder(algorithm).setSecureRandom(random).setProvider(provider).build(password));
- }
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/PKCS8Generator.java b/bcpkix/src/main/java/org/bouncycastle/openssl/PKCS8Generator.java
index 448d885..f822cba 100644
--- a/bcpkix/src/main/java/org/bouncycastle/openssl/PKCS8Generator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/openssl/PKCS8Generator.java
@@ -3,20 +3,12 @@ package org.bouncycastle.openssl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.Provider;
-import java.security.SecureRandom;
-import java.security.Security;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder;
-import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.OutputEncryptor;
import org.bouncycastle.util.io.pem.PemGenerationException;
import org.bouncycastle.util.io.pem.PemObject;
@@ -40,56 +32,6 @@ public class PKCS8Generator
private PrivateKeyInfo key;
private OutputEncryptor outputEncryptor;
- private JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder;
-
- /**
- * Constructor for an unencrypted private key PEM object.
- *
- * @param key private key to be encoded.
- * @deprecated use JcaPKCS8Generator
- */
- public PKCS8Generator(PrivateKey key)
- {
- this.key = PrivateKeyInfo.getInstance(key.getEncoded());
- }
-
- /**
- * Constructor for an encrypted private key PEM object.
- *
- * @param key private key to be encoded
- * @param algorithm encryption algorithm to use
- * @param provider name of provider to use
- * @throws NoSuchProviderException if provider cannot be found
- * @throws NoSuchAlgorithmException if algorithm/mode cannot be found
- * @deprecated use JcaPKCS8Generator
- */
- public PKCS8Generator(PrivateKey key, ASN1ObjectIdentifier algorithm, String provider)
- throws NoSuchProviderException, NoSuchAlgorithmException
- {
- Provider prov = Security.getProvider(provider);
-
- if (prov == null)
- {
- throw new NoSuchProviderException("cannot find provider: " + provider);
- }
-
- init(key, algorithm, prov);
- }
-
- /**
- * Constructor for an encrypted private key PEM object.
- *
- * @param key private key to be encoded
- * @param algorithm encryption algorithm to use
- * @param provider provider to use
- * @throws NoSuchAlgorithmException if algorithm/mode cannot be found
- * @deprecated use JcaPKCS8Generator
- */
- public PKCS8Generator(PrivateKey key, ASN1ObjectIdentifier algorithm, Provider provider)
- throws NoSuchAlgorithmException
- {
- init(key, algorithm, provider);
- }
/**
* Base constructor.
@@ -100,60 +42,9 @@ public class PKCS8Generator
this.outputEncryptor = outputEncryptor;
}
- private void init(PrivateKey key, ASN1ObjectIdentifier algorithm, Provider provider)
- throws NoSuchAlgorithmException
- {
- this.key = PrivateKeyInfo.getInstance(key.getEncoded());
- this.encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(algorithm);
-
- encryptorBuilder.setProvider(provider);
- }
-
- /**
- * @deprecated ignored in the updated case.
- */
- public PKCS8Generator setSecureRandom(SecureRandom random)
- {
- encryptorBuilder.setRandom(random);
-
- return this;
- }
-
- /**
- * @deprecated ignored in the updated case.
- */
- public PKCS8Generator setPassword(char[] password)
- {
- encryptorBuilder.setPasssword(password);
-
- return this;
- }
-
- /**
- * @deprecated ignored in the updated case.
- */
- public PKCS8Generator setIterationCount(int iterationCount)
- {
- encryptorBuilder.setIterationCount(iterationCount);
-
- return this;
- }
-
public PemObject generate()
throws PemGenerationException
{
- try
- {
- if (encryptorBuilder != null)
- {
- outputEncryptor = encryptorBuilder.build();
- }
- }
- catch (OperatorCreationException e)
- {
- throw new PemGenerationException("unable to create operator: " + e.getMessage(), e);
- }
-
if (outputEncryptor != null)
{
return generate(key, outputEncryptor);
diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JcaPEMKeyConverter.java b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JcaPEMKeyConverter.java
index 4d55aa3..d332ca1 100644
--- a/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JcaPEMKeyConverter.java
+++ b/bcpkix/src/main/java/org/bouncycastle/openssl/jcajce/JcaPEMKeyConverter.java
@@ -2,13 +2,20 @@ package org.bouncycastle.openssl.jcajce;
import java.security.KeyFactory;
import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
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.jcajce.DefaultJcaJceHelper;
@@ -22,6 +29,15 @@ public class JcaPEMKeyConverter
{
private JcaJceHelper helper = new DefaultJcaJceHelper();
+ private static final Map algorithms = new HashMap();
+
+ static
+ {
+ algorithms.put(X9ObjectIdentifiers.id_ecPublicKey, "ECDSA");
+ algorithms.put(PKCSObjectIdentifiers.rsaEncryption, "RSA");
+ algorithms.put(X9ObjectIdentifiers.id_dsa, "DSA");
+ }
+
public JcaPEMKeyConverter setProvider(Provider provider)
{
this.helper = new ProviderJcaJceHelper(provider);
@@ -41,14 +57,7 @@ public class JcaPEMKeyConverter
{
try
{
- String algorithm = keyPair.getPrivateKeyInfo().getPrivateKeyAlgorithm().getAlgorithm().getId();
-
- if (X9ObjectIdentifiers.id_ecPublicKey.getId().equals(algorithm))
- {
- algorithm = "ECDSA";
- }
-
- KeyFactory keyFactory = helper.createKeyFactory(algorithm);
+ KeyFactory keyFactory = getKeyFactory(keyPair.getPrivateKeyInfo().getPrivateKeyAlgorithm());
return new KeyPair(keyFactory.generatePublic(new X509EncodedKeySpec(keyPair.getPublicKeyInfo().getEncoded())),
keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyPair.getPrivateKeyInfo().getEncoded())));
@@ -64,14 +73,7 @@ public class JcaPEMKeyConverter
{
try
{
- String algorithm = publicKeyInfo.getAlgorithm().getAlgorithm().getId();
-
- if (X9ObjectIdentifiers.id_ecPublicKey.getId().equals(algorithm))
- {
- algorithm = "ECDSA";
- }
-
- KeyFactory keyFactory = helper.createKeyFactory(algorithm);
+ KeyFactory keyFactory = getKeyFactory(publicKeyInfo.getAlgorithm());
return keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyInfo.getEncoded()));
}
@@ -86,14 +88,7 @@ public class JcaPEMKeyConverter
{
try
{
- String algorithm = privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm().getId();
-
- if (X9ObjectIdentifiers.id_ecPublicKey.getId().equals(algorithm))
- {
- algorithm = "ECDSA";
- }
-
- KeyFactory keyFactory = helper.createKeyFactory(algorithm);
+ KeyFactory keyFactory = getKeyFactory(privateKeyInfo.getPrivateKeyAlgorithm());
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded()));
}
@@ -102,4 +97,19 @@ public class JcaPEMKeyConverter
throw new PEMException("unable to convert key pair: " + e.getMessage(), e);
}
}
+
+ private KeyFactory getKeyFactory(AlgorithmIdentifier algId)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ ASN1ObjectIdentifier algorithm = algId.getAlgorithm();
+
+ String algName = (String)algorithms.get(algorithm);
+
+ if (algName == null)
+ {
+ algName = algorithm.getId();
+ }
+
+ return helper.createKeyFactory(algName);
+ }
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/package.html b/bcpkix/src/main/java/org/bouncycastle/openssl/package.html
deleted file mode 100644
index 7e60a79..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/openssl/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for dealing with OpenSSL PEM files.
-</body>
-</html>
diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/openssl/test/AllTests.java
index eb1d4da..faae18e 100644
--- a/bcpkix/src/main/java/org/bouncycastle/openssl/test/AllTests.java
+++ b/bcpkix/src/main/java/org/bouncycastle/openssl/test/AllTests.java
@@ -15,14 +15,18 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.openssl.PEMReader;
+import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.openssl.PKCS8Generator;
-import org.bouncycastle.openssl.PasswordFinder;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator;
+import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder;
import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
+import org.bouncycastle.pkcs.PKCSException;
import org.bouncycastle.util.test.SimpleTestResult;
public class
@@ -30,12 +34,14 @@ public class
extends TestCase
{
public void testOpenSSL()
- {
- Security.addProvider(new BouncyCastleProvider());
+ {
+ if (Security.getProvider("BC") == null)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+ }
org.bouncycastle.util.test.Test[] tests = new org.bouncycastle.util.test.Test[]
{
- new ReaderTest(),
new WriterTest(),
new ParserTest()
};
@@ -54,51 +60,27 @@ public class
public void testPKCS8Encrypted()
throws Exception
{
+ if (Security.getProvider("BC") == null)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
kpGen.initialize(1024);
PrivateKey key = kpGen.generateKeyPair().getPrivate();
- encryptedTest(key, PKCS8Generator.AES_256_CBC);
- encryptedTest(key, PKCS8Generator.DES3_CBC);
- encryptedTest(key, PKCS8Generator.PBE_SHA1_3DES);
encryptedTestNew(key, PKCS8Generator.AES_256_CBC);
encryptedTestNew(key, PKCS8Generator.DES3_CBC);
encryptedTestNew(key, PKCS8Generator.PBE_SHA1_3DES);
}
- private void encryptedTest(PrivateKey key, ASN1ObjectIdentifier algorithm)
- throws NoSuchProviderException, NoSuchAlgorithmException, IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut), "BC");
- PKCS8Generator pkcs8 = new PKCS8Generator(key, algorithm, "BC");
-
- pkcs8.setPassword("hello".toCharArray());
-
- pWrt.writeObject(pkcs8);
-
- pWrt.close();
-
- PEMReader pRd = new PEMReader(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray())), new PasswordFinder()
- {
- public char[] getPassword()
- {
- return "hello".toCharArray();
- }
- });
-
- PrivateKey rdKey = (PrivateKey)pRd.readObject();
-
- assertEquals(key, rdKey);
- }
-
private void encryptedTestNew(PrivateKey key, ASN1ObjectIdentifier algorithm)
- throws NoSuchProviderException, NoSuchAlgorithmException, IOException, OperatorCreationException
+ throws NoSuchProviderException, NoSuchAlgorithmException, IOException, OperatorCreationException, PKCSException
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut), "BC");
+ PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut));
JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(algorithm);
@@ -111,44 +93,12 @@ public class
pWrt.close();
- PEMReader pRd = new PEMReader(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray())), new PasswordFinder()
- {
- public char[] getPassword()
- {
- return "hello".toCharArray();
- }
- });
-
- PrivateKey rdKey = (PrivateKey)pRd.readObject();
-
- assertEquals(key, rdKey);
- }
-
- public void testPKCS8Plain()
- throws Exception
- {
- KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
+ PEMParser pRd = new PEMParser(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray())));
- kpGen.initialize(1024);
+ PKCS8EncryptedPrivateKeyInfo pInfo = (PKCS8EncryptedPrivateKeyInfo)pRd.readObject();
- PrivateKey key = kpGen.generateKeyPair().getPrivate();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut));
- PKCS8Generator pkcs8 = new PKCS8Generator(key);
+ PrivateKey rdKey = new JcaPEMKeyConverter().setProvider("BC").getPrivateKey(pInfo.decryptPrivateKeyInfo(new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider("BC").build("hello".toCharArray())));
- pWrt.writeObject(pkcs8);
-
- pWrt.close();
-
- PEMReader pRd = new PEMReader(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray())), new PasswordFinder()
- {
- public char[] getPassword()
- {
- return "hello".toCharArray();
- }
- });
-
- PrivateKey rdKey = (PrivateKey)pRd.readObject();
assertEquals(key, rdKey);
}
@@ -156,6 +106,11 @@ public class
public void testPKCS8PlainNew()
throws Exception
{
+ if (Security.getProvider("BC") == null)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
kpGen.initialize(1024);
@@ -169,15 +124,11 @@ public class
pWrt.close();
- PEMReader pRd = new PEMReader(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray())), new PasswordFinder()
- {
- public char[] getPassword()
- {
- return "hello".toCharArray();
- }
- });
+ PEMParser pRd = new PEMParser(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray())));
+
+ PrivateKeyInfo kp = (PrivateKeyInfo)pRd.readObject();
- PrivateKey rdKey = (PrivateKey)pRd.readObject();
+ PrivateKey rdKey = new JcaPEMKeyConverter().setProvider("BC").getPrivateKey(kp);
assertEquals(key, rdKey);
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/test/ReaderTest.java b/bcpkix/src/main/java/org/bouncycastle/openssl/test/ReaderTest.java
deleted file mode 100644
index 23aee08..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/openssl/test/ReaderTest.java
+++ /dev/null
@@ -1,417 +0,0 @@
-package org.bouncycastle.openssl.test;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.Signature;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.interfaces.RSAPrivateKey;
-
-import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
-import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
-import org.bouncycastle.openssl.PEMReader;
-import org.bouncycastle.openssl.PEMWriter;
-import org.bouncycastle.openssl.PasswordFinder;
-import org.bouncycastle.util.test.SimpleTest;
-
-/**
- * basic class for reading test.pem - the password is "secret"
- */
-public class ReaderTest
- extends SimpleTest
-{
- private static class Password
- implements PasswordFinder
- {
- char[] password;
-
- Password(
- char[] word)
- {
- this.password = word;
- }
-
- public char[] getPassword()
- {
- return password;
- }
- }
-
- public String getName()
- {
- return "PEMReaderTest";
- }
-
- private PEMReader openPEMResource(
- String fileName,
- PasswordFinder pGet)
- {
- InputStream res = this.getClass().getResourceAsStream(fileName);
- Reader fRd = new BufferedReader(new InputStreamReader(res));
- return new PEMReader(fRd, pGet);
- }
-
- public void performTest()
- throws Exception
- {
- PasswordFinder pGet = new Password("secret".toCharArray());
- PEMReader pemRd = openPEMResource("test.pem", pGet);
- Object o;
- KeyPair pair;
-
- while ((o = pemRd.readObject()) != null)
- {
- if (o instanceof KeyPair)
- {
- //pair = (KeyPair)o;
-
- //System.out.println(pair.getPublic());
- //System.out.println(pair.getPrivate());
- }
- else
- {
- //System.out.println(o.toString());
- }
- }
-
- // test bogus lines before begin are ignored.
- pemRd = openPEMResource("extratest.pem", pGet);
-
- while ((o = pemRd.readObject()) != null)
- {
- if (!(o instanceof X509Certificate))
- {
- fail("wrong object found");
- }
- }
-
- //
- // pkcs 7 data
- //
- pemRd = openPEMResource("pkcs7.pem", null);
- ContentInfo d = (ContentInfo)pemRd.readObject();
-
- if (!d.getContentType().equals(CMSObjectIdentifiers.envelopedData))
- {
- fail("failed envelopedData check");
- }
-
- //
- // ECKey
- //
- pemRd = openPEMResource("eckey.pem", null);
- ECNamedCurveParameterSpec spec = (ECNamedCurveParameterSpec)pemRd.readObject();
-
- pair = (KeyPair)pemRd.readObject();
- Signature sgr = Signature.getInstance("ECDSA", "BC");
-
- sgr.initSign(pair.getPrivate());
-
- byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
-
- sgr.update(message);
-
- byte[] sigBytes = sgr.sign();
-
- sgr.initVerify(pair.getPublic());
-
- sgr.update(message);
-
- if (!sgr.verify(sigBytes))
- {
- fail("EC verification failed");
- }
-
- if (!pair.getPublic().getAlgorithm().equals("ECDSA"))
- {
- fail("wrong algorithm name on public got: " + pair.getPublic().getAlgorithm());
- }
-
- if (!pair.getPrivate().getAlgorithm().equals("ECDSA"))
- {
- fail("wrong algorithm name on private");
- }
-
- //
- // writer/parser test
- //
- KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
-
- pair = kpGen.generateKeyPair();
-
- keyPairTest("RSA", pair);
-
- kpGen = KeyPairGenerator.getInstance("DSA", "BC");
- kpGen.initialize(512, new SecureRandom());
- pair = kpGen.generateKeyPair();
-
- keyPairTest("DSA", pair);
-
- //
- // PKCS7
- //
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut));
-
- pWrt.writeObject(d);
-
- pWrt.close();
-
- pemRd = new PEMReader(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray())));
- d = (ContentInfo)pemRd.readObject();
-
- if (!d.getContentType().equals(CMSObjectIdentifiers.envelopedData))
- {
- fail("failed envelopedData recode check");
- }
-
-
- // OpenSSL test cases (as embedded resources)
- doOpenSslDsaTest("unencrypted");
- doOpenSslRsaTest("unencrypted");
-
- doOpenSslTests("aes128");
- doOpenSslTests("aes192");
- doOpenSslTests("aes256");
- doOpenSslTests("blowfish");
- doOpenSslTests("des1");
- doOpenSslTests("des2");
- doOpenSslTests("des3");
- doOpenSslTests("rc2_128");
-
- doOpenSslDsaTest("rc2_40_cbc");
- doOpenSslRsaTest("rc2_40_cbc");
- doOpenSslDsaTest("rc2_64_cbc");
- doOpenSslRsaTest("rc2_64_cbc");
-
- doDudPasswordTest("7fd98", 0, "corrupted stream - out of bounds length found");
- doDudPasswordTest("ef677", 1, "corrupted stream - out of bounds length found");
- doDudPasswordTest("800ce", 2, "unknown tag 26 encountered");
- doDudPasswordTest("b6cd8", 3, "DEF length 81 object truncated by 56");
- doDudPasswordTest("28ce09", 4, "DEF length 110 object truncated by 28");
- doDudPasswordTest("2ac3b9", 5, "DER length more than 4 bytes: 11");
- doDudPasswordTest("2cba96", 6, "DEF length 100 object truncated by 35");
- doDudPasswordTest("2e3354", 7, "DEF length 42 object truncated by 9");
- doDudPasswordTest("2f4142", 8, "DER length more than 4 bytes: 14");
- doDudPasswordTest("2fe9bb", 9, "DER length more than 4 bytes: 65");
- doDudPasswordTest("3ee7a8", 10, "DER length more than 4 bytes: 57");
- doDudPasswordTest("41af75", 11, "unknown tag 16 encountered");
- doDudPasswordTest("1704a5", 12, "corrupted stream detected");
- doDudPasswordTest("1c5822", 13, "unknown object in getInstance: org.bouncycastle.asn1.DERUTF8String");
- doDudPasswordTest("5a3d16", 14, "corrupted stream detected");
- doDudPasswordTest("8d0c97", 15, "corrupted stream detected");
- doDudPasswordTest("bc0daf", 16, "corrupted stream detected");
- doDudPasswordTest("aaf9c4d",17, "corrupted stream - out of bounds length found");
-
- doNoPasswordTest();
-
- // encrypted private key test
- pGet = new Password("password".toCharArray());
- pemRd = openPEMResource("enckey.pem", pGet);
-
- RSAPrivateCrtKey privKey = (RSAPrivateCrtKey)pemRd.readObject();
-
- if (!privKey.getPublicExponent().equals(new BigInteger("10001", 16)))
- {
- fail("decryption of private key data check failed");
- }
-
- // general PKCS8 test
- pGet = new Password("password".toCharArray());
- pemRd = openPEMResource("pkcs8test.pem", pGet);
-
- while ((privKey = (RSAPrivateCrtKey)pemRd.readObject()) != null)
- {
- if (!privKey.getPublicExponent().equals(new BigInteger("10001", 16)))
- {
- fail("decryption of private key data check failed");
- }
- }
- }
-
- private void keyPairTest(
- String name,
- KeyPair pair)
- throws IOException
- {
- PEMReader pemRd;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- PEMWriter pWrt = new PEMWriter(new OutputStreamWriter(bOut));
-
- pWrt.writeObject(pair.getPublic());
-
- pWrt.close();
-
- pemRd = new PEMReader(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray())));
-
- PublicKey k = (PublicKey)pemRd.readObject();
- if (!k.equals(pair.getPublic()))
- {
- fail("Failed public key read: " + name);
- }
-
- bOut = new ByteArrayOutputStream();
- pWrt = new PEMWriter(new OutputStreamWriter(bOut));
-
- pWrt.writeObject(pair.getPrivate());
-
- pWrt.close();
-
- pemRd = new PEMReader(new InputStreamReader(new ByteArrayInputStream(bOut.toByteArray())));
-
- KeyPair kPair = (KeyPair)pemRd.readObject();
- if (!kPair.getPrivate().equals(pair.getPrivate()))
- {
- fail("Failed private key read: " + name);
- }
-
- if (!kPair.getPublic().equals(pair.getPublic()))
- {
- fail("Failed private key public read: " + name);
- }
- }
-
- private void doOpenSslTests(
- String baseName)
- throws IOException
- {
- doOpenSslDsaModesTest(baseName);
- doOpenSslRsaModesTest(baseName);
- }
-
- private void doOpenSslDsaModesTest(
- String baseName)
- throws IOException
- {
- doOpenSslDsaTest(baseName + "_cbc");
- doOpenSslDsaTest(baseName + "_cfb");
- doOpenSslDsaTest(baseName + "_ecb");
- doOpenSslDsaTest(baseName + "_ofb");
- }
-
- private void doOpenSslRsaModesTest(
- String baseName)
- throws IOException
- {
- doOpenSslRsaTest(baseName + "_cbc");
- doOpenSslRsaTest(baseName + "_cfb");
- doOpenSslRsaTest(baseName + "_ecb");
- doOpenSslRsaTest(baseName + "_ofb");
- }
-
- private void doOpenSslDsaTest(
- String name)
- throws IOException
- {
- String fileName = "dsa/openssl_dsa_" + name + ".pem";
-
- doOpenSslTestFile(fileName, DSAPrivateKey.class);
- }
-
- private void doOpenSslRsaTest(
- String name)
- throws IOException
- {
- String fileName = "rsa/openssl_rsa_" + name + ".pem";
-
- doOpenSslTestFile(fileName, RSAPrivateKey.class);
- }
-
- private void doOpenSslTestFile(
- String fileName,
- Class expectedPrivKeyClass)
- throws IOException
- {
- PEMReader pr = openPEMResource("data/" + fileName, new Password("changeit".toCharArray()));
- Object o = pr.readObject();
-
- if (o == null || !(o instanceof KeyPair))
- {
- fail("Didn't find OpenSSL key");
- }
-
- KeyPair kp = (KeyPair) o;
- PrivateKey privKey = kp.getPrivate();
-
- if (!expectedPrivKeyClass.isInstance(privKey))
- {
- fail("Returned key not of correct type");
- }
- }
-
- private void doDudPasswordTest(String password, int index, String message)
- {
- // illegal state exception check - in this case the wrong password will
- // cause an underlying class cast exception.
- try
- {
- PasswordFinder pGet = new Password(password.toCharArray());
-
- PEMReader pemRd = openPEMResource("test.pem", pGet);
- Object o;
-
- while ((o = pemRd.readObject()) != null)
- {
- }
-
- fail("issue not detected: " + index);
- }
- catch (IOException e)
- {
- if (e.getCause() != null && !e.getCause().getMessage().equals(message))
- {
- e.printStackTrace();
- fail("issue " + index + " exception thrown, but wrong message");
- }
- else if (e.getCause() == null && !e.getMessage().equals(message))
- {
- e.printStackTrace();
- fail("issue " + index + " exception thrown, but wrong message");
- }
- }
- }
-
- private void doNoPasswordTest()
- throws IOException
- {
- PasswordFinder pGet = new Password("".toCharArray());
-
- PEMReader pemRd = openPEMResource("smimenopw.pem", pGet);
- Object o;
- PrivateKey key = null;
-
- while ((o = pemRd.readObject()) != null)
- {
- key = (PrivateKey)o;
- }
-
- if (key == null)
- {
- fail("private key not detected");
- }
- }
-
- public static void main(
- String[] args)
- {
- Security.addProvider(new BouncyCastleProvider());
-
- runTest(new ReaderTest());
- }
-}
diff --git a/bcpkix/src/main/java/org/bouncycastle/openssl/test/WriterTest.java b/bcpkix/src/main/java/org/bouncycastle/openssl/test/WriterTest.java
index cb911eb..e41efd6 100644
--- a/bcpkix/src/main/java/org/bouncycastle/openssl/test/WriterTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/openssl/test/WriterTest.java
@@ -18,13 +18,18 @@ import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.List;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.openssl.PEMReader;
+import org.bouncycastle.openssl.PEMEncryptedKeyPair;
+import org.bouncycastle.openssl.PEMKeyPair;
+import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.openssl.PasswordFinder;
+import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
+import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
+import org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.io.pem.PemHeader;
import org.bouncycastle.util.io.pem.PemObject;
-import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.test.SimpleTest;
public class WriterTest
@@ -154,23 +159,23 @@ public class WriterTest
throws IOException
{
StringWriter sw = new StringWriter();
- PEMWriter pw = new PEMWriter(sw, provider);
+ PEMWriter pw = new PEMWriter(sw);
pw.writeObject(akp);
pw.close();
String data = sw.toString();
- PEMReader pr = new PEMReader(new StringReader(data));
+ PEMParser pr = new PEMParser(new StringReader(data));
Object o = pr.readObject();
- if (o == null || !(o instanceof KeyPair))
+ if (o == null || !(o instanceof PEMKeyPair))
{
fail("Didn't find OpenSSL key");
}
- KeyPair kp = (KeyPair) o;
+ KeyPair kp = new JcaPEMKeyConverter().setProvider("BC").getKeyPair((PEMKeyPair)o);
PrivateKey privKey = kp.getPrivate();
if (!akp.equals(privKey))
@@ -186,14 +191,14 @@ public class WriterTest
throws IOException
{
StringWriter sw = new StringWriter();
- PEMWriter pw = new PEMWriter(sw, provider);
+ PEMWriter pw = new PEMWriter(sw);
- pw.writeObject(akp, algorithm, testPassword, random);
+ pw.writeObject(new JcaMiscPEMGenerator(akp, new JcePEMEncryptorBuilder(algorithm).setSecureRandom(random).build(testPassword)));
pw.close();
String data = sw.toString();
- PemReader pRaw = new PemReader(new StringReader(data));
+ PEMParser pRaw = new PEMParser(new StringReader(data));
PemObject pemObject = pRaw.readPemObject();
List headers = pemObject.getHeaders();
@@ -215,16 +220,16 @@ public class WriterTest
}
}
- PEMReader pr = new PEMReader(new StringReader(data), new Password(testPassword), provider);
+ PEMParser pr = new PEMParser(new StringReader(data));
Object o = pr.readObject();
- if (o == null || !(o instanceof KeyPair))
+ if (o == null || !(o instanceof PEMEncryptedKeyPair))
{
fail("Didn't find OpenSSL key");
}
- KeyPair kp = (KeyPair) o;
+ KeyPair kp = new JcaPEMKeyConverter().setProvider("BC").getKeyPair(((PEMEncryptedKeyPair)o).decryptKeyPair(new JcePEMDecryptorProviderBuilder().setProvider("BC").build(testPassword)));
PrivateKey privKey = kp.getPrivate();
if (!akp.equals(privKey))
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/BufferingContentSigner.java b/bcpkix/src/main/java/org/bouncycastle/operator/BufferingContentSigner.java
new file mode 100644
index 0000000..d174367
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/BufferingContentSigner.java
@@ -0,0 +1,70 @@
+package org.bouncycastle.operator;
+
+import java.io.OutputStream;
+
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.util.io.BufferingOutputStream;
+
+/**
+ * A class that explicitly buffers the data to be signed, sending it in one
+ * block when ready for signing.
+ */
+public class BufferingContentSigner
+ implements ContentSigner
+{
+ private final ContentSigner contentSigner;
+ private final OutputStream output;
+
+ /**
+ * Base constructor.
+ *
+ * @param contentSigner the content signer to be wrapped.
+ */
+ public BufferingContentSigner(ContentSigner contentSigner)
+ {
+ this.contentSigner = contentSigner;
+ this.output = new BufferingOutputStream(contentSigner.getOutputStream());
+ }
+
+ /**
+ * Base constructor.
+ *
+ * @param contentSigner the content signer to be wrapped.
+ * @param bufferSize the size of the internal buffer to use.
+ */
+ public BufferingContentSigner(ContentSigner contentSigner, int bufferSize)
+ {
+ this.contentSigner = contentSigner;
+ this.output = new BufferingOutputStream(contentSigner.getOutputStream(), bufferSize);
+ }
+
+ /**
+ * Return the algorithm identifier supported by this signer.
+ *
+ * @return algorithm identifier for the signature generated.
+ */
+ public AlgorithmIdentifier getAlgorithmIdentifier()
+ {
+ return contentSigner.getAlgorithmIdentifier();
+ }
+
+ /**
+ * Return the buffering stream.
+ *
+ * @return the output stream used to accumulate the data.
+ */
+ public OutputStream getOutputStream()
+ {
+ return output;
+ }
+
+ /**
+ * Generate signature from internally buffered data.
+ *
+ * @return the signature calculated from the bytes written to the buffering stream.
+ */
+ public byte[] getSignature()
+ {
+ return contentSigner.getSignature();
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java
index 234c38b..a1c6ba1 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeyProvider.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSecretKeySizeProvider.java
@@ -5,16 +5,17 @@ import java.util.HashMap;
import java.util.Map;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.util.Integers;
-public class DefaultSecretKeyProvider
+public class DefaultSecretKeySizeProvider
implements SecretKeySizeProvider
{
- public static final SecretKeySizeProvider INSTANCE = new DefaultSecretKeyProvider();
+ public static final SecretKeySizeProvider INSTANCE = new DefaultSecretKeySizeProvider();
private static final Map KEY_SIZES;
@@ -24,7 +25,7 @@ public class DefaultSecretKeyProvider
keySizes.put(new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"), Integers.valueOf(128));
- keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), Integers.valueOf(192));
+ keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC, Integers.valueOf(192));
keySizes.put(NISTObjectIdentifiers.id_aes128_CBC, Integers.valueOf(128));
keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192));
@@ -34,21 +35,35 @@ public class DefaultSecretKeyProvider
keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192));
keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256));
+ keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256));
+
KEY_SIZES = Collections.unmodifiableMap(keySizes);
}
public int getKeySize(AlgorithmIdentifier algorithmIdentifier)
{
- // TODO: not all ciphers/oid relationships are this simple.
- Integer keySize = (Integer)KEY_SIZES.get(algorithmIdentifier.getAlgorithm());
+ int keySize = getKeySize(algorithmIdentifier.getAlgorithm());
- if (keySize != null)
+ // just need the OID
+ if (keySize > 0)
{
- return keySize.intValue();
+ return keySize;
}
+ // TODO: support OID/Parameter key sizes (e.g. RC2).
+
return -1;
}
+ public int getKeySize(ASN1ObjectIdentifier algorithm)
+ {
+ Integer keySize = (Integer)KEY_SIZES.get(algorithm);
+
+ if (keySize != null)
+ {
+ return keySize.intValue();
+ }
+ return -1;
+ }
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java b/bcpkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java
index 15d7a67..5f92ef0 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/SecretKeySizeProvider.java
@@ -1,8 +1,17 @@
package org.bouncycastle.operator;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
public interface SecretKeySizeProvider
{
int getKeySize(AlgorithmIdentifier algorithmIdentifier);
+
+ /**
+ * Return the key size implied by the OID, if one exists.
+ *
+ * @param algorithm the OID of the algorithm of interest.
+ * @return -1 if there is no fixed key size associated with the OID, or more information is required.
+ */
+ int getKeySize(ASN1ObjectIdentifier algorithm);
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaAlgorithmParametersConverter.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaAlgorithmParametersConverter.java
new file mode 100644
index 0000000..d4e2162
--- /dev/null
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaAlgorithmParametersConverter.java
@@ -0,0 +1,73 @@
+package org.bouncycastle.operator.jcajce;
+
+
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.MGF1ParameterSpec;
+
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.PSource;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.RSAESOAEPparams;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
+
+public class JcaAlgorithmParametersConverter
+{
+ public JcaAlgorithmParametersConverter()
+ {
+ }
+
+ public AlgorithmIdentifier getAlgorithmIdentifier(ASN1ObjectIdentifier algId, AlgorithmParameters parameters)
+ throws InvalidAlgorithmParameterException
+ {
+ try
+ {
+ ASN1Encodable params = ASN1Primitive.fromByteArray(parameters.getEncoded());
+
+ return new AlgorithmIdentifier(algId, params);
+ }
+ catch (IOException e)
+ {
+ throw new InvalidAlgorithmParameterException("unable to encode parameters object: " + e.getMessage());
+ }
+ }
+
+ public AlgorithmIdentifier getAlgorithmIdentifier(ASN1ObjectIdentifier algorithm, AlgorithmParameterSpec algorithmSpec)
+ throws InvalidAlgorithmParameterException
+ {
+ if (algorithmSpec instanceof OAEPParameterSpec)
+ {
+ if (algorithmSpec.equals(OAEPParameterSpec.DEFAULT))
+ {
+ return new AlgorithmIdentifier(algorithm,
+ new RSAESOAEPparams(RSAESOAEPparams.DEFAULT_HASH_ALGORITHM, RSAESOAEPparams.DEFAULT_MASK_GEN_FUNCTION, RSAESOAEPparams.DEFAULT_P_SOURCE_ALGORITHM));
+ }
+ else
+ {
+ OAEPParameterSpec oaepSpec = (OAEPParameterSpec)algorithmSpec;
+ PSource pSource = oaepSpec.getPSource();
+
+ if (!oaepSpec.getMGFAlgorithm().equals(OAEPParameterSpec.DEFAULT.getMGFAlgorithm()))
+ {
+ throw new InvalidAlgorithmParameterException("only " + OAEPParameterSpec.DEFAULT.getMGFAlgorithm() + " mask generator supported.");
+ }
+
+ AlgorithmIdentifier hashAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find(oaepSpec.getDigestAlgorithm());
+ AlgorithmIdentifier mgf1HashAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find((((MGF1ParameterSpec)oaepSpec.getMGFParameters()).getDigestAlgorithm()));
+ return new AlgorithmIdentifier(algorithm,
+ new RSAESOAEPparams(hashAlgorithm, new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, mgf1HashAlgorithm),
+ new AlgorithmIdentifier(PKCSObjectIdentifiers.id_pSpecified, new DEROctetString(((PSource.PSpecified)pSource).getValue()))));
+ }
+ }
+
+ throw new InvalidAlgorithmParameterException("unknown parameter spec passed.");
+ }
+}
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
index 56c3771..87a6699 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
@@ -12,6 +12,7 @@ import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.jcajce.DefaultJcaJceHelper;
@@ -144,6 +145,12 @@ public class JcaContentVerifierProviderBuilder
};
}
+ public ContentVerifierProvider build(SubjectPublicKeyInfo publicKey)
+ throws OperatorCreationException
+ {
+ return this.build(helper.convertPublicKey(publicKey));
+ }
+
private SignatureOutputStream createSignatureStream(AlgorithmIdentifier algorithm, PublicKey publicKey)
throws OperatorCreationException
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java
index 9413f96..9140ef2 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java
@@ -1,5 +1,6 @@
package org.bouncycastle.operator.jcajce;
+import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -80,10 +81,18 @@ public class JceAsymmetricKeyUnwrapper
Key sKey = null;
Cipher keyCipher = helper.createAsymmetricWrapper(this.getAlgorithmIdentifier().getAlgorithm(), extraMappings);
+ AlgorithmParameters algParams = helper.createAlgorithmParameters(this.getAlgorithmIdentifier());
try
{
- keyCipher.init(Cipher.UNWRAP_MODE, privKey);
+ if (algParams != null)
+ {
+ keyCipher.init(Cipher.UNWRAP_MODE, privKey, algParams);
+ }
+ else
+ {
+ keyCipher.init(Cipher.UNWRAP_MODE, privKey);
+ }
sKey = keyCipher.unwrap(encryptedKey, helper.getKeyAlgorithmName(encryptedKeyAlgorithm.getAlgorithm()), Cipher.SECRET_KEY);
}
catch (GeneralSecurityException e)
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyWrapper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyWrapper.java
index 4a2ffae..d19dbcf 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyWrapper.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyWrapper.java
@@ -1,6 +1,8 @@
package org.bouncycastle.operator.jcajce;
+import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
import java.security.Provider;
import java.security.ProviderException;
import java.security.PublicKey;
@@ -12,6 +14,7 @@ import java.util.Map;
import javax.crypto.Cipher;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jcajce.DefaultJcaJceHelper;
import org.bouncycastle.jcajce.NamedJcaJceHelper;
@@ -40,6 +43,19 @@ public class JceAsymmetricKeyWrapper
this(certificate.getPublicKey());
}
+ /**
+ * Create a wrapper, overriding the algorithm type that is stored in the public key.
+ *
+ * @param algorithmIdentifier identifier for encryption algorithm to be used.
+ * @param publicKey the public key to be used.
+ */
+ public JceAsymmetricKeyWrapper(AlgorithmIdentifier algorithmIdentifier, PublicKey publicKey)
+ {
+ super(algorithmIdentifier);
+
+ this.publicKey = publicKey;
+ }
+
public JceAsymmetricKeyWrapper setProvider(Provider provider)
{
this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider));
@@ -86,13 +102,25 @@ public class JceAsymmetricKeyWrapper
throws OperatorException
{
Cipher keyEncryptionCipher = helper.createAsymmetricWrapper(getAlgorithmIdentifier().getAlgorithm(), extraMappings);
+ AlgorithmParameters algParams = helper.createAlgorithmParameters(this.getAlgorithmIdentifier());
+
byte[] encryptedKeyBytes = null;
try
{
- keyEncryptionCipher.init(Cipher.WRAP_MODE, publicKey, random);
+ if (algParams != null)
+ {
+ keyEncryptionCipher.init(Cipher.WRAP_MODE, publicKey, algParams, random);
+ }
+ else
+ {
+ keyEncryptionCipher.init(Cipher.WRAP_MODE, publicKey, random);
+ }
encryptedKeyBytes = keyEncryptionCipher.wrap(OperatorUtils.getJceKey(encryptionKey));
}
+ catch (InvalidKeyException e)
+ {
+ }
catch (GeneralSecurityException e)
{
}
@@ -114,6 +142,10 @@ public class JceAsymmetricKeyWrapper
keyEncryptionCipher.init(Cipher.ENCRYPT_MODE, publicKey, random);
encryptedKeyBytes = keyEncryptionCipher.doFinal(OperatorUtils.getJceKey(encryptionKey).getEncoded());
}
+ catch (InvalidKeyException e)
+ {
+ throw new OperatorException("unable to encrypt contents key", e);
+ }
catch (GeneralSecurityException e)
{
throw new OperatorException("unable to encrypt contents key", e);
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java
index bdffa53..2e0bcc1 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java
@@ -4,14 +4,18 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
+import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
import java.security.spec.PSSParameterSpec;
+import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
@@ -29,9 +33,11 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSASSAPSSparams;
import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.jcajce.JcaJceHelper;
+import org.bouncycastle.jcajce.JcaJceUtils;
import org.bouncycastle.operator.OperatorCreationException;
class OperatorHelper
@@ -181,6 +187,41 @@ class OperatorHelper
}
}
+ AlgorithmParameters createAlgorithmParameters(AlgorithmIdentifier cipherAlgId)
+ throws OperatorCreationException
+ {
+ AlgorithmParameters parameters;
+
+ if (cipherAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption))
+ {
+ return null;
+ }
+
+ try
+ {
+ parameters = helper.createAlgorithmParameters(cipherAlgId.getAlgorithm().getId());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ return null; // There's a good chance there aren't any!
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new OperatorCreationException("cannot create algorithm parameters: " + e.getMessage(), e);
+ }
+
+ try
+ {
+ parameters.init(cipherAlgId.getParameters().toASN1Primitive().getEncoded());
+ }
+ catch (IOException e)
+ {
+ throw new OperatorCreationException("cannot initialise algorithm parameters: " + e.getMessage(), e);
+ }
+
+ return parameters;
+ }
+
MessageDigest createDigest(AlgorithmIdentifier digAlgId)
throws GeneralSecurityException
{
@@ -258,7 +299,7 @@ class OperatorHelper
{
AlgorithmParameters params = helper.createAlgorithmParameters(algName);
- params.init(algorithm.getParameters().toASN1Primitive().getEncoded(), "ASN.1");
+ JcaJceUtils.loadParameters(params, algorithm.getParameters());
PSSParameterSpec spec = (PSSParameterSpec)params.getParameterSpec(PSSParameterSpec.class);
sig.setParameter(spec);
@@ -367,6 +408,33 @@ class OperatorHelper
}
}
+ public PublicKey convertPublicKey(SubjectPublicKeyInfo publicKeyInfo)
+ throws OperatorCreationException
+ {
+ try
+ {
+ KeyFactory keyFact = helper.createKeyFactory(publicKeyInfo.getAlgorithm().getAlgorithm().getId());
+
+ return keyFact.generatePublic(new X509EncodedKeySpec(publicKeyInfo.getEncoded()));
+ }
+ catch (IOException e)
+ {
+ throw new OperatorCreationException("cannot get encoded form of key: " + e.getMessage(), e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new OperatorCreationException("cannot create key factory: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new OperatorCreationException("cannot find factory provider: " + e.getMessage(), e);
+ }
+ catch (InvalidKeySpecException e)
+ {
+ throw new OperatorCreationException("cannot create key factory: " + e.getMessage(), e);
+ }
+ }
+
// TODO: put somewhere public so cause easily accessed
private static class OpCertificateException
extends CertificateException
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/package.html b/bcpkix/src/main/java/org/bouncycastle/operator/package.html
deleted file mode 100644
index b64343a..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/operator/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Basic operators for doing encryption, signing, and digest operations.
-</body>
-</html>
diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java
index 79ab492..5379d47 100644
--- a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java
@@ -11,8 +11,10 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
+import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.cryptopro.GOST28147Parameters;
import org.bouncycastle.asn1.pkcs.PBES2Parameters;
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.asn1.pkcs.PKCS12PBEParams;
@@ -23,19 +25,19 @@ import org.bouncycastle.jcajce.JcaJceHelper;
import org.bouncycastle.jcajce.NamedJcaJceHelper;
import org.bouncycastle.jcajce.ProviderJcaJceHelper;
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
-import org.bouncycastle.operator.DefaultSecretKeyProvider;
-import org.bouncycastle.operator.GenericKey;
+import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
+import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
+import org.bouncycastle.operator.DefaultSecretKeySizeProvider;
import org.bouncycastle.operator.InputDecryptor;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.SecretKeySizeProvider;
-import org.bouncycastle.operator.jcajce.JceGenericKey;
public class JcePKCSPBEInputDecryptorProviderBuilder
{
private JcaJceHelper helper = new DefaultJcaJceHelper();
private boolean wrongPKCS12Zero = false;
- private SecretKeySizeProvider keySizeProvider = DefaultSecretKeyProvider.INSTANCE;
+ private SecretKeySizeProvider keySizeProvider = DefaultSecretKeySizeProvider.INSTANCE;
public JcePKCSPBEInputDecryptorProviderBuilder()
{
@@ -125,13 +127,31 @@ public class JcePKCSPBEInputDecryptorProviderBuilder
SecretKeyFactory keyFact = helper.createSecretKeyFactory(alg.getKeyDerivationFunc().getAlgorithm().getId());
- key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme)));
+ if (func.isDefaultPrf())
+ {
+ key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme)));
+ }
+ else
+ {
+ key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme), func.getPrf()));
+ }
cipher = helper.createCipher(alg.getEncryptionScheme().getAlgorithm().getId());
encryptionAlg = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
- cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ASN1OctetString.getInstance(alg.getEncryptionScheme().getParameters()).getOctets()));
+ ASN1Encodable encParams = alg.getEncryptionScheme().getParameters();
+ if (encParams instanceof ASN1OctetString)
+ {
+ cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ASN1OctetString.getInstance(encParams).getOctets()));
+ }
+ else
+ {
+ // TODO: at the moment it's just GOST, but...
+ GOST28147Parameters gParams = GOST28147Parameters.getInstance(encParams);
+
+ cipher.init(Cipher.DECRYPT_MODE, key, new GOST28147ParameterSpec(gParams.getEncryptionParamSet(), gParams.getIV()));
+ }
}
}
catch (Exception e)
@@ -150,11 +170,6 @@ public class JcePKCSPBEInputDecryptorProviderBuilder
{
return new CipherInputStream(input, cipher);
}
-
- public GenericKey getKey()
- {
- return new JceGenericKey(encryptionAlg, key);
- }
};
}
};
diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java
index b37d2cb..fe53d58 100644
--- a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java
@@ -26,7 +26,7 @@ import org.bouncycastle.jcajce.DefaultJcaJceHelper;
import org.bouncycastle.jcajce.JcaJceHelper;
import org.bouncycastle.jcajce.NamedJcaJceHelper;
import org.bouncycastle.jcajce.ProviderJcaJceHelper;
-import org.bouncycastle.operator.DefaultSecretKeyProvider;
+import org.bouncycastle.operator.DefaultSecretKeySizeProvider;
import org.bouncycastle.operator.GenericKey;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.OutputEncryptor;
@@ -38,7 +38,7 @@ public class JcePKCSPBEOutputEncryptorBuilder
private ASN1ObjectIdentifier algorithm;
private ASN1ObjectIdentifier keyEncAlgorithm;
private SecureRandom random;
- private SecretKeySizeProvider keySizeProvider = DefaultSecretKeyProvider.INSTANCE;
+ private SecretKeySizeProvider keySizeProvider = DefaultSecretKeySizeProvider.INSTANCE;
public JcePKCSPBEOutputEncryptorBuilder(ASN1ObjectIdentifier algorithm)
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/package.html b/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/package.html
deleted file mode 100644
index 9b10dc4..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/pkcs/jcajce/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<body bgcolor="#ffffff">
-JCA extensions to the PKCS#10 certification request package.
-</body>
-</html> \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/package.html b/bcpkix/src/main/java/org/bouncycastle/pkcs/package.html
deleted file mode 100644
index c83de7c..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/pkcs/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<body bgcolor="#ffffff">
-Basic support package for handling and creating PKCS#10 certification requests, PKCS#8 encrypted keys and PKCS#12 keys stores.
-</body>
-</html> \ No newline at end of file
diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/test/PfxPduTest.java b/bcpkix/src/main/java/org/bouncycastle/pkcs/test/PfxPduTest.java
index 9c4d138..2bbf9ea 100644
--- a/bcpkix/src/main/java/org/bouncycastle/pkcs/test/PfxPduTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/test/PfxPduTest.java
@@ -19,6 +19,7 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.DERBMPString;
import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.Attribute;
import org.bouncycastle.asn1.pkcs.ContentInfo;
@@ -455,6 +456,74 @@ public class PfxPduTest
+ "LgBvAHIAZzAxMCEwCQYFKw4DAhoFAAQUc8hyg5aq/58lH3whwo66zJkWY28E"
+ "CKHZUIQsQX9hAgIIAA==");
+ private byte[] gostPfx = Base64.decode(
+ "MIIHEgIBAzCCBssGCSqGSIb3DQEHAaCCBrwEgga4MIIGtDCCBYEGCSqGSIb3"
+ + "DQEHBqCCBXIwggVuAgEAMIIFZwYJKoZIhvcNAQcBMFUGCSqGSIb3DQEFDTBI"
+ + "MCcGCSqGSIb3DQEFDDAaBAi114+lRrpkXAICCAAwCgYGKoUDAgIKBQAwHQYG"
+ + "KoUDAgIVMBMECLEIQPMsz/ZZBgcqhQMCAh8BgIIFAbu13yJiW/BnSKYKbtv9"
+ + "tDJoTv6l9BVpCCI4tvpzJnMeLBJyVZU4JevcJNii+R1LilVuuB+xc8e7/P4G"
+ + "6TILWmnnispr9KPRAbYRfoCJOa59+TYJMur58wwDuYgMapQAFzsvpzyUWi62"
+ + "o3uQbbLKO9hQCeJW2L+K9cbg8k33MjXMLpnblKpqmZbHTmBJDFR3xGw7IEjD"
+ + "UNqruu7DlHY6jctiVJSii9UNEVetSo9AAzfROxRjROg38VsWxLyO9wEMBv/8"
+ + "H8ur+zOtmQPGqirNXmN+pa08OvZin9kh7CgswW03xIbfsdGGGLRAWtvCnEwJ"
+ + "mS2tEfH1SZcuVLpMomhq3FU/jsc12k+vq/jw4I2cmfDL41ieK72bwNj8xUXu"
+ + "JHeoFSPGX4z+nsJUrFbFG4VBuDs2Y0SCWLyYZvdjvJwYjfqtyi/RoFSZjGHF"
+ + "crstf9YNQ0vW0efCJ7pUBH44OrbnCx5ng2U5jFm1b3HBIKA2RX+Tlhv14MgT"
+ + "KSftPZ67eSmgdsyPuQAdMu6fEdBMpVKMNZNRV565690sqi+1jOmH94TUX8XU"
+ + "2pRQj6eGGLq6lgGnnDabcePUEPXW8zW2KYrDKYJ/1QZmVGldvlqnjZMNhIO+"
+ + "Afsqax/P8RBjMduGqdilGdRzbN8PdhVaN0Ys+WzFxiS9gtaA2yPzcQuedWDN"
+ + "T7sIrfIapgFYmmHRQ7ht4AKj+lmOyNadONYw+ww+8RzHB1d2Kk+iXeZCtvH0"
+ + "XFWJZtuoGKSt/gkI0E2vpDfMbLaczaRC7ityO0iJs25ozP4JhZRBVvOmpxc9"
+ + "YuIetbTnTf1TLJKXDgt1IwPZeugbofSeiNv117lx8VgtvMYFD4W+WQlB8HnO"
+ + "C8NOYjkMPElc6PCMB9gGm0cIu1fKLvY8ycLav93JJjdDuC0kgKLb2+8mC5+2"
+ + "DdMkcfgW6hy4c98xnJs8enCww3A4xkRbMU13zMq70liqmKHV2SSurg5hwUHM"
+ + "ZthT8p988ZBrnqW24lXfMBqTK4YtIBMeMnvKocYBXr96ig3GfahI1Aj2Bw2e"
+ + "bpZTVeayYUd+2xX8JJMdqna6Q61AL8/eUhJUETz5+fgQJtPjcKmdJfVHO6nB"
+ + "vOk1t/rjK17eiXLxHCyvfP+Tw8lSFOhcvr4eIeG8WfsWNRu2eKKosOU7uash"
+ + "QpnvQieqDeijuRxf+tbbJ5D86inwbJqdxra7wNuZXmiaB9gFDzNbNjhtL+6i"
+ + "gUyX/iQHKi9bNK+PH6pdH/gkwnG/juhdgqoNY6GRty/LUOPgXD+r5e/ST16R"
+ + "vnlwrlKp5FzRWBEkem+dhelj3rb+cxKEyvPe3TvIUFcmIlV1VCRQ1fBHtX18"
+ + "eC3a3GprH8c40z3S/kdyk7GlFQ27DRLka+iDN05b+MP5jlgvfqYBKxwLfeNu"
+ + "MpxWoCUvYWiQdMih86/l0H+0o5UB8SqRbpuvr6fY910JCk0hDaO1pgB3HlRz"
+ + "k1vb46pg25heXQm3JmO+ghxjOGliYBWjl8p7AfRS9cjS8ca+X02Mv9Viv7Ce"
+ + "3+Gz0MVwfK98viJ3CFxkaEBlM2LM0IeUQbkHG+YwYaTSfl4GYyrug4F0ZdrA"
+ + "KeY9/kIxa/OJxjcIMs2H+2mSpxmrb7ylmHZ2RB8ITiduRVtO091hn/J7N+eT"
+ + "h6BvLBKIFU+UFUdgjxoDNDk7ao++Mu9T3dQfceFBOYzW9vMQgX30yaPLSdan"
+ + "ZMAP0VtiNjCCASsGCSqGSIb3DQEHAaCCARwEggEYMIIBFDCCARAGCyqGSIb3"
+ + "DQEMCgECoIGyMIGvMFUGCSqGSIb3DQEFDTBIMCcGCSqGSIb3DQEFDDAaBAiQ"
+ + "Owewo16xzQICCAAwCgYGKoUDAgIKBQAwHQYGKoUDAgIVMBMECHSCNJJcQ2VI"
+ + "BgcqhQMCAh8BBFYCyRRpFtZgnsxeK7ZHT+aOyoVmzhtnLrqoBHgV4nJJW2/e"
+ + "UcJjc2Rlbzfd+3L/GWcRGF8Bgn+MjiaAqE64Rzaao9t2hc3myw1WrCfPnoEx"
+ + "VI7OPBM5FzFMMCMGCSqGSIb3DQEJFTEWBBTV7LvI27QWRmHD45X2WKXYs3ct"
+ + "AzAlBgkqhkiG9w0BCRQxGB4WAGMAcABfAGUAeABwAG8AcgB0AGUAZDA+MC4w"
+ + "CgYGKoUDAgIJBQAEIJbGZorQsNM63+xozwEI561cTFVCbyHAEEpkvF3eijT8"
+ + "BAgY5sDtkrVeBQICCAA=");
+
+ private byte[] gostPfxFoo123 = Base64.decode(
+ "MIID6gIBAzCCA6MGCSqGSIb3DQEHAaCCA5QEggOQMIIDjDCCApQGCSqGSIb3"
+ + "DQEHBqCCAoUwggKBAgEAMIICegYJKoZIhvcNAQcBMFUGCSqGSIb3DQEFDTBI"
+ + "MCcGCSqGSIb3DQEFDDAaBAhIVrbUVNoQ2wICCAAwCgYGKoUDAgIKBQAwHQYG"
+ + "KoUDAgIVMBMECBLmAh+XCCYhBgcqhQMCAh8BgIICFP9hQLgDq5SORy2npOdo"
+ + "1bvoGl9Qdga1kV9s2c1/Y1kTGpuiYKfm5Il+PurzYdE5t/Wi2+SxoePm/AKA"
+ + "x1Ep5btK/002wnyRbUKdjgF1r7fMXRrd5Ioy8lYxB1v6qhHmzE5fz7FxY+iV"
+ + "Z70dSRS0JkTasI8MRsFLkJJfDb9twgoch8lYGFfYirHLcVy4xxA3JO9VSHm2"
+ + "8nuSWSnsmGN0ufPX14UpV2RFe3Rt0gZ0Jc8u2h2Mo0sIoVU6HVwdXzoe6LN7"
+ + "1NPZdRuhVtjxEvjDAvNJ8WHXQnBQMai2nVAj87uNr6OHLRs+foEccEY9WpPQ"
+ + "GPt4XbPt4MtmVctT2+Gsvf6Ws2UCx6hD4k8i28a6xS8lhTVam2g/2Z5cxtUV"
+ + "HxYt7j13HjuQVsuSNdgtrUnw3l43LnBxRZhlFz0r2zrvTB04ynenS+lGdVuG"
+ + "0TauIH+rdP1ubujw6lFdG9RNgUxWvS5IdwbFGX73a+ZrWiYJeERX11N/6r3g"
+ + "0EqVFNH9t/ROsdAtCCe2FycQoOSb+VxPU6I+SHjwe7Oa7R8Xxazh/eWTsV59"
+ + "QzPuLriUMbyYdQIf4xdclgcJoxFElopgl4orRfzH3XQsVbtTxN33lwjkE0j/"
+ + "686VtcO+b+dU7+BEB7O5yDcx1tupgre0ha/0KOlYfPvmbogGdDf0r6MOwrS7"
+ + "QFXxKlHfp8vn4mNwoy7pjrzjmjclkbkwgfEGCSqGSIb3DQEHAaCB4wSB4DCB"
+ + "3TCB2gYLKoZIhvcNAQwKAQKggaMwgaAwVQYJKoZIhvcNAQUNMEgwJwYJKoZI"
+ + "hvcNAQUMMBoECLD6Ld7TqurqAgIIADAKBgYqhQMCAgoFADAdBgYqhQMCAhUw"
+ + "EwQIoYXV7LETOEAGByqFAwICHwEERyBQK9LuYnOO0ELrge+a6JFeAVwPL85V"
+ + "ip2Kj/GfD3nzZR4tPzCwAt79RriKQklNqa3uCc9o0C9Zk5Qcj36SqiXxD1tz"
+ + "Ea63MSUwIwYJKoZIhvcNAQkVMRYEFKjg5gKM+i+vFhSwaga8YGaZ5thVMD4w"
+ + "LjAKBgYqhQMCAgkFAAQgIwD0CRCwva2Bjdlv5g970H2bCB1aafBNr/hxJLZE"
+ + "Ey4ECAW3VYXJzJpYAgIIAA==");
+
/**
* we generate the CA's certificate
*/
@@ -1042,6 +1111,90 @@ public class PfxPduTest
}
}
+ public void testGOST1()
+ throws Exception
+ {
+ char[] password = "1".toCharArray();
+
+ InputDecryptorProvider inputDecryptorProvider = new JcePKCSPBEInputDecryptorProviderBuilder()
+ .setProvider("BC").build(password);
+ PKCS12PfxPdu pfx = new PKCS12PfxPdu(gostPfx);
+
+ assertTrue(pfx.hasMac());
+ assertTrue(pfx.isMacValid(new JcePKCS12MacCalculatorBuilderProvider().setProvider("BC"), password));
+
+ ContentInfo[] infos = pfx.getContentInfos();
+
+ for (int i = 0; i != infos.length; i++)
+ {
+ if (infos[i].getContentType().equals(PKCSObjectIdentifiers.encryptedData))
+ {
+ PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i], inputDecryptorProvider);
+
+ PKCS12SafeBag[] bags = dataFact.getSafeBags();
+
+ // TODO: finish!
+// assertEquals(3, bags.length);
+// assertEquals(PKCSObjectIdentifiers.certBag, bags[0].getType());
+ }
+ else
+ {
+ PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i]);
+
+ PKCS12SafeBag[] bags = dataFact.getSafeBags();
+
+ assertEquals(1, bags.length);
+ assertEquals(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag, bags[0].getType());
+
+ PKCS8EncryptedPrivateKeyInfo encInfo = (PKCS8EncryptedPrivateKeyInfo)bags[0].getBagValue();
+ PrivateKeyInfo info = encInfo.decryptPrivateKeyInfo(inputDecryptorProvider);
+ assertEquals(CryptoProObjectIdentifiers.gostR3410_2001, info.getPrivateKeyAlgorithm().getAlgorithm());
+ }
+ }
+ }
+
+ public void testGOST2()
+ throws Exception
+ {
+ char[] password = "foo123".toCharArray();
+
+ InputDecryptorProvider inputDecryptorProvider = new JcePKCSPBEInputDecryptorProviderBuilder()
+ .setProvider("BC").build(password);
+ PKCS12PfxPdu pfx = new PKCS12PfxPdu(gostPfxFoo123);
+
+ assertTrue(pfx.hasMac());
+ assertTrue(pfx.isMacValid(new JcePKCS12MacCalculatorBuilderProvider().setProvider("BC"), password));
+
+ ContentInfo[] infos = pfx.getContentInfos();
+
+ for (int i = 0; i != infos.length; i++)
+ {
+ if (infos[i].getContentType().equals(PKCSObjectIdentifiers.encryptedData))
+ {
+ PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i], inputDecryptorProvider);
+
+ PKCS12SafeBag[] bags = dataFact.getSafeBags();
+
+ // TODO: finish!
+// assertEquals(3, bags.length);
+// assertEquals(PKCSObjectIdentifiers.certBag, bags[0].getType());
+ }
+ else
+ {
+ PKCS12SafeBagFactory dataFact = new PKCS12SafeBagFactory(infos[i]);
+
+ PKCS12SafeBag[] bags = dataFact.getSafeBags();
+
+ assertEquals(1, bags.length);
+ assertEquals(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag, bags[0].getType());
+
+ PKCS8EncryptedPrivateKeyInfo encInfo = (PKCS8EncryptedPrivateKeyInfo)bags[0].getBagValue();
+ PrivateKeyInfo info = encInfo.decryptPrivateKeyInfo(inputDecryptorProvider);
+ assertEquals(CryptoProObjectIdentifiers.gostR3410_2001, info.getPrivateKeyAlgorithm().getAlgorithm());
+ }
+ }
+ }
+
private X509Certificate[] createCertChain(KeyFactory fact, PublicKey pubKey)
throws Exception
{
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/TSPUtil.java b/bcpkix/src/main/java/org/bouncycastle/tsp/TSPUtil.java
index 76054b9..d757071 100644
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/TSPUtil.java
+++ b/bcpkix/src/main/java/org/bouncycastle/tsp/TSPUtil.java
@@ -1,26 +1,17 @@
package org.bouncycastle.tsp;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.Provider;
-import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.cms.Attribute;
import org.bouncycastle.asn1.cms.AttributeTable;
@@ -35,7 +26,6 @@ import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.ExtensionsGenerator;
import org.bouncycastle.asn1.x509.KeyPurposeId;
-import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.operator.DigestCalculator;
@@ -46,7 +36,6 @@ import org.bouncycastle.util.Integers;
public class TSPUtil
{
- private static Set EMPTY_SET = Collections.unmodifiableSet(new HashSet());
private static List EMPTY_LIST = Collections.unmodifiableList(new ArrayList());
private static final Map digestLengths = new HashMap();
@@ -82,64 +71,6 @@ public class TSPUtil
digestNames.put(CryptoProObjectIdentifiers.gostR3411.getId(), "GOST3411");
}
- /**
- * Fetches the signature time-stamp attributes from a SignerInformation object.
- * Checks that the MessageImprint for each time-stamp matches the signature field.
- * (see RFC 3161 Appendix A).
- *
- * @param signerInfo a SignerInformation to search for time-stamps
- * @param provider an optional provider to use to create MessageDigest instances
- * @return a collection of TimeStampToken objects
- * @throws TSPValidationException
- * @deprecated use getSignatureTimestamps(SignerInformation, DigestCalculatorProvider)
- */
- public static Collection getSignatureTimestamps(SignerInformation signerInfo, Provider provider)
- throws TSPValidationException
- {
- List timestamps = new ArrayList();
-
- AttributeTable unsignedAttrs = signerInfo.getUnsignedAttributes();
- if (unsignedAttrs != null)
- {
- ASN1EncodableVector allTSAttrs = unsignedAttrs.getAll(
- PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
- for (int i = 0; i < allTSAttrs.size(); ++i)
- {
- Attribute tsAttr = (Attribute)allTSAttrs.get(i);
- ASN1Set tsAttrValues = tsAttr.getAttrValues();
- for (int j = 0; j < tsAttrValues.size(); ++j)
- {
- try
- {
- ContentInfo contentInfo = ContentInfo.getInstance(tsAttrValues.getObjectAt(j));
- TimeStampToken timeStampToken = new TimeStampToken(contentInfo);
- TimeStampTokenInfo tstInfo = timeStampToken.getTimeStampInfo();
-
- MessageDigest digest = createDigestInstance(tstInfo.getMessageImprintAlgOID().getId(), provider);
- byte[] expectedDigest = digest.digest(signerInfo.getSignature());
-
- if (!Arrays.constantTimeAreEqual(expectedDigest, tstInfo.getMessageImprintDigest()))
- {
- throw new TSPValidationException("Incorrect digest in message imprint");
- }
-
- timestamps.add(timeStampToken);
- }
- catch (NoSuchAlgorithmException e)
- {
- throw new TSPValidationException("Unknown hash algorithm specified in timestamp");
- }
- catch (Exception e)
- {
- throw new TSPValidationException("Timestamp could not be parsed");
- }
- }
- }
- }
-
- return timestamps;
- }
-
/**
* Fetches the signature time-stamp attributes from a SignerInformation object.
* Checks that the MessageImprint for each time-stamp matches the signature field.
@@ -207,56 +138,9 @@ public class TSPUtil
* Validate the passed in certificate as being of the correct type to be used
* for time stamping. To be valid it must have an ExtendedKeyUsage extension
* which has a key purpose identifier of id-kp-timeStamping.
- *
- * @param cert the certificate of interest.
- * @throws TSPValidationException if the certicate fails on one of the check points.
- */
- public static void validateCertificate(
- X509Certificate cert)
- throws TSPValidationException
- {
- if (cert.getVersion() != 3)
- {
- throw new IllegalArgumentException("Certificate must have an ExtendedKeyUsage extension.");
- }
-
- byte[] ext = cert.getExtensionValue(X509Extensions.ExtendedKeyUsage.getId());
- if (ext == null)
- {
- throw new TSPValidationException("Certificate must have an ExtendedKeyUsage extension.");
- }
-
- if (!cert.getCriticalExtensionOIDs().contains(X509Extensions.ExtendedKeyUsage.getId()))
- {
- throw new TSPValidationException("Certificate must have an ExtendedKeyUsage extension marked as critical.");
- }
-
- ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(ext));
-
- try
- {
- aIn = new ASN1InputStream(new ByteArrayInputStream(((ASN1OctetString)aIn.readObject()).getOctets()));
-
- ExtendedKeyUsage extKey = ExtendedKeyUsage.getInstance(aIn.readObject());
-
- if (!extKey.hasKeyPurposeId(KeyPurposeId.id_kp_timeStamping) || extKey.size() != 1)
- {
- throw new TSPValidationException("ExtendedKeyUsage not solely time stamping.");
- }
- }
- catch (IOException e)
- {
- throw new TSPValidationException("cannot process ExtendedKeyUsage extension");
- }
- }
-
- /**
- * Validate the passed in certificate as being of the correct type to be used
- * for time stamping. To be valid it must have an ExtendedKeyUsage extension
- * which has a key purpose identifier of id-kp-timeStamping.
*
* @param cert the certificate of interest.
- * @throws TSPValidationException if the certicate fails on one of the check points.
+ * @throws TSPValidationException if the certificate fails on one of the check points.
*/
public static void validateCertificate(
X509CertificateHolder cert)
@@ -286,23 +170,6 @@ public class TSPUtil
}
}
- /*
- * Return the digest algorithm using one of the standard JCA string
- * representations rather than the algorithm identifier (if possible).
- */
- static String getDigestAlgName(
- String digestAlgOID)
- {
- String digestName = (String)digestNames.get(digestAlgOID);
-
- if (digestName != null)
- {
- return digestName;
- }
-
- return digestAlgOID;
- }
-
static int getDigestLength(
String digestAlgOID)
throws TSPException
@@ -317,47 +184,6 @@ public class TSPUtil
throw new TSPException("digest algorithm cannot be found.");
}
- static MessageDigest createDigestInstance(String digestAlgOID, Provider provider)
- throws NoSuchAlgorithmException
- {
- String digestName = TSPUtil.getDigestAlgName(digestAlgOID);
-
- if (provider != null)
- {
- try
- {
- return MessageDigest.getInstance(digestName, provider);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignore
- }
- }
-
- return MessageDigest.getInstance(digestName);
- }
-
- static Set getCriticalExtensionOIDs(X509Extensions extensions)
- {
- if (extensions == null)
- {
- return EMPTY_SET;
- }
-
- return Collections.unmodifiableSet(new HashSet(java.util.Arrays.asList(extensions.getCriticalExtensionOIDs())));
- }
-
- static Set getNonCriticalExtensionOIDs(X509Extensions extensions)
- {
- if (extensions == null)
- {
- return EMPTY_SET;
- }
-
- // TODO: should probably produce a set that imposes correct ordering
- return Collections.unmodifiableSet(new HashSet(java.util.Arrays.asList(extensions.getNonCriticalExtensionOIDs())));
- }
-
static List getExtensionOIDs(Extensions extensions)
{
if (extensions == null)
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampRequest.java b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampRequest.java
index 8acc41b..696c2d8 100644
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampRequest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampRequest.java
@@ -4,7 +4,6 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
-import java.security.NoSuchProviderException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
@@ -58,9 +57,15 @@ public class TimeStampRequest
public TimeStampRequest(InputStream in)
throws IOException
{
+ this(loadRequest(in));
+ }
+
+ private static TimeStampReq loadRequest(InputStream in)
+ throws IOException
+ {
try
{
- this.req = TimeStampReq.getInstance(new ASN1InputStream(in).readObject());
+ return TimeStampReq.getInstance(new ASN1InputStream(in).readObject());
}
catch (ClassCastException e)
{
@@ -126,27 +131,6 @@ public class TimeStampRequest
/**
* Validate the timestamp request, checking the digest to see if it is of an
* accepted type and whether it is of the correct length for the algorithm specified.
- *
- * @param algorithms a set of String OIDS giving accepted algorithms.
- * @param policies if non-null a set of policies we are willing to sign under.
- * @param extensions if non-null a set of extensions we are willing to accept.
- * @param provider the provider to confirm the digest size against.
- * @throws TSPException if the request is invalid, or processing fails.
- * @deprecated use validate method without provider argument.
- */
- public void validate(
- Set algorithms,
- Set policies,
- Set extensions,
- String provider)
- throws TSPException, NoSuchProviderException
- {
- validate(algorithms, policies, extensions);
- }
-
- /**
- * Validate the timestamp request, checking the digest to see if it is of an
- * accepted type and whether it is of the correct length for the algorithm specified.
*
* @param algorithms a set of OIDs giving accepted algorithms.
* @param policies if non-null a set of policies OIDs we are willing to sign under.
@@ -228,34 +212,6 @@ public class TimeStampRequest
return TSPUtil.getExtensionOIDs(extensions);
}
- /* (non-Javadoc)
- * @see java.security.cert.X509Extension#getExtensionValue(java.lang.String)
- * @deprecated use getExtension(ASN1ObjectIdentifier)
- */
- public byte[] getExtensionValue(String oid)
- {
- Extensions exts = req.getExtensions();
-
- if (exts != null)
- {
- Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid));
-
- if (ext != null)
- {
- try
- {
- return ext.getExtnValue().getEncoded();
- }
- catch (Exception e)
- {
- throw new RuntimeException("error encoding " + e.toString());
- }
- }
- }
-
- return null;
- }
-
/**
* Returns a set of ASN1ObjectIdentifiers giving the non-critical extensions.
* @return a set of ASN1ObjectIdentifiers.
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampResponseGenerator.java b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampResponseGenerator.java
index 15f5b13..7b7c757 100644
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampResponseGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampResponseGenerator.java
@@ -1,17 +1,13 @@
package org.bouncycastle.tsp;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERInteger;
@@ -142,82 +138,6 @@ public class TimeStampResponseGenerator
/**
* Return an appropriate TimeStampResponse.
* <p>
- * If genTime is null a timeNotAvailable error response will be returned.
- *
- * @param request the request this response is for.
- * @param serialNumber serial number for the response token.
- * @param genTime generation time for the response token.
- * @param provider provider to use for signature calculation.
- * @deprecated use method that does not require provider
- * @return
- * @throws NoSuchAlgorithmException
- * @throws NoSuchProviderException
- * @throws TSPException
- */
- public TimeStampResponse generate(
- TimeStampRequest request,
- BigInteger serialNumber,
- Date genTime,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, TSPException
- {
- TimeStampResp resp;
-
- try
- {
- if (genTime == null)
- {
- throw new TSPValidationException("The time source is not available.", PKIFailureInfo.timeNotAvailable);
- }
-
- request.validate(acceptedAlgorithms, acceptedPolicies, acceptedExtensions, provider);
-
- status = PKIStatus.GRANTED;
- this.addStatusString("Operation Okay");
-
- PKIStatusInfo pkiStatusInfo = getPKIStatusInfo();
-
- ContentInfo tstTokenContentInfo = null;
- try
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(tokenGenerator.generate(request, serialNumber, genTime, provider).toCMSSignedData().getEncoded());
- ASN1InputStream aIn = new ASN1InputStream(bIn);
-
- tstTokenContentInfo = ContentInfo.getInstance(aIn.readObject());
- }
- catch (java.io.IOException ioEx)
- {
- throw new TSPException(
- "Timestamp token received cannot be converted to ContentInfo", ioEx);
- }
-
- resp = new TimeStampResp(pkiStatusInfo, tstTokenContentInfo);
- }
- catch (TSPValidationException e)
- {
- status = PKIStatus.REJECTION;
-
- this.setFailInfoField(e.getFailureCode());
- this.addStatusString(e.getMessage());
-
- PKIStatusInfo pkiStatusInfo = getPKIStatusInfo();
-
- resp = new TimeStampResp(pkiStatusInfo, null);
- }
-
- try
- {
- return new TimeStampResponse(resp);
- }
- catch (IOException e)
- {
- throw new TSPException("created badly formatted response!");
- }
- }
-
- /**
- * Return an appropriate TimeStampResponse.
- * <p>
* If genTime is null a timeNotAvailable error response will be returned. Calling generate() is the
* equivalent of:
* <pre>
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampToken.java b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampToken.java
index bc4a631..0422998 100644
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampToken.java
+++ b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampToken.java
@@ -4,14 +4,6 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.cert.CertStore;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Date;
@@ -32,7 +24,6 @@ import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.IssuerSerial;
-import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessable;
@@ -40,13 +31,14 @@ import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerId;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationVerifier;
-import org.bouncycastle.jce.PrincipalUtil;
-import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Store;
+/**
+ * Carrier class for a TimeStampToken.
+ */
public class TimeStampToken
{
CMSSignedData tsToken;
@@ -158,17 +150,6 @@ public class TimeStampToken
return tsaSignerInfo.getUnsignedAttributes();
}
- /**
- * @deprecated use getCertificates() or getCRLs()
- */
- public CertStore getCertificatesAndCRLs(
- String type,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
- {
- return tsToken.getCertificatesAndCRLs(type, provider);
- }
-
public Store getCertificates()
{
return tsToken.getCertificates();
@@ -188,90 +169,6 @@ public class TimeStampToken
* Validate the time stamp token.
* <p>
* To be valid the token must be signed by the passed in certificate and
- * the certificate must be the one referred to by the SigningCertificate
- * attribute included in the hashed attributes of the token. The
- * certificate must also have the ExtendedKeyUsageExtension with only
- * KeyPurposeId.id_kp_timeStamping and have been valid at the time the
- * timestamp was created.
- * </p>
- * <p>
- * A successful call to validate means all the above are true.
- * </p>
- * @deprecated
- */
- public void validate(
- X509Certificate cert,
- String provider)
- throws TSPException, TSPValidationException,
- CertificateExpiredException, CertificateNotYetValidException, NoSuchProviderException
- {
- try
- {
- if (!Arrays.constantTimeAreEqual(certID.getCertHash(), MessageDigest.getInstance(certID.getHashAlgorithmName()).digest(cert.getEncoded())))
- {
- throw new TSPValidationException("certificate hash does not match certID hash.");
- }
-
- if (certID.getIssuerSerial() != null)
- {
- if (!certID.getIssuerSerial().getSerial().getValue().equals(cert.getSerialNumber()))
- {
- throw new TSPValidationException("certificate serial number does not match certID for signature.");
- }
-
- GeneralName[] names = certID.getIssuerSerial().getIssuer().getNames();
- X509Principal principal = PrincipalUtil.getIssuerX509Principal(cert);
- boolean found = false;
-
- for (int i = 0; i != names.length; i++)
- {
- if (names[i].getTagNo() == 4 && new X509Principal(X509Name.getInstance(names[i].getName())).equals(principal))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- throw new TSPValidationException("certificate name does not match certID for signature. ");
- }
- }
-
- TSPUtil.validateCertificate(cert);
-
- cert.checkValidity(tstInfo.getGenTime());
-
- if (!tsaSignerInfo.verify(cert, provider))
- {
- throw new TSPValidationException("signature not created by certificate.");
- }
- }
- catch (CMSException e)
- {
- if (e.getUnderlyingException() != null)
- {
- throw new TSPException(e.getMessage(), e.getUnderlyingException());
- }
- else
- {
- throw new TSPException("CMS exception: " + e, e);
- }
- }
- catch (NoSuchAlgorithmException e)
- {
- throw new TSPException("cannot find algorithm: " + e, e);
- }
- catch (CertificateEncodingException e)
- {
- throw new TSPException("problem processing certificate: " + e, e);
- }
- }
-
- /**
- * Validate the time stamp token.
- * <p>
- * To be valid the token must be signed by the passed in certificate and
* the certificate must be the one referred to by the SigningCertificate
* attribute included in the hashed attributes of the token. The
* certificate must also have the ExtendedKeyUsageExtension with only
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenGenerator.java b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenGenerator.java
index 1a1cec1..008ca95 100644
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/tsp/TimeStampTokenGenerator.java
@@ -1,26 +1,10 @@
package org.bouncycastle.tsp;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.cert.CRLException;
-import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Date;
-import java.util.Hashtable;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -30,8 +14,6 @@ import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.cms.Attribute;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.ess.ESSCertID;
import org.bouncycastle.asn1.ess.ESSCertIDv2;
@@ -44,24 +26,17 @@ import org.bouncycastle.asn1.tsp.MessageImprint;
import org.bouncycastle.asn1.tsp.TSTInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.cert.jcajce.JcaX509CRLHolder;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.IssuerSerial;
+import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.CMSAttributeTableGenerationException;
import org.bouncycastle.cms.CMSAttributeTableGenerator;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
-import org.bouncycastle.cms.CMSSignedGenerator;
-import org.bouncycastle.cms.DefaultSignedAttributeTableGenerator;
import org.bouncycastle.cms.SignerInfoGenerator;
-import org.bouncycastle.cms.SimpleAttributeTableGenerator;
-import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
-import org.bouncycastle.jce.interfaces.GOST3410PrivateKey;
import org.bouncycastle.operator.DigestCalculator;
-import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
-import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.CollectionStore;
import org.bouncycastle.util.Store;
@@ -105,12 +80,6 @@ public class TimeStampTokenGenerator
private ASN1ObjectIdentifier tsaPolicyOID;
- PrivateKey key;
- X509Certificate cert;
- String digestOID;
- AttributeTable signedAttr;
- AttributeTable unsignedAttr;
-
private List certs = new ArrayList();
private List crls = new ArrayList();
private List attrCerts = new ArrayList();
@@ -134,6 +103,29 @@ public class TimeStampTokenGenerator
ASN1ObjectIdentifier tsaPolicy)
throws IllegalArgumentException, TSPException
{
+ this(signerInfoGen, digestCalculator, tsaPolicy, false);
+ }
+
+ /**
+ * Basic Constructor - set up a calculator based on signerInfoGen with a ESSCertID calculated from
+ * the signer's associated certificate using the sha1DigestCalculator. If alternate values are required
+ * for id-aa-signingCertificate they should be added to the signerInfoGen object before it is passed in,
+ * otherwise a standard digest based value will be added.
+ *
+ * @param signerInfoGen the generator for the signer we are using.
+ * @param digestCalculator calculator for to use for digest of certificate.
+ * @param tsaPolicy tasPolicy to send.
+ * @param isIssuerSerialIncluded should issuerSerial be included in the ESSCertIDs, true if yes, by default false.
+ * @throws IllegalArgumentException if calculator is not SHA-1 or there is no associated certificate for the signer,
+ * @throws TSPException if the signer certificate cannot be processed.
+ */
+ public TimeStampTokenGenerator(
+ final SignerInfoGenerator signerInfoGen,
+ DigestCalculator digestCalculator,
+ ASN1ObjectIdentifier tsaPolicy,
+ boolean isIssuerSerialIncluded)
+ throws IllegalArgumentException, TSPException
+ {
this.signerInfoGen = signerInfoGen;
this.tsaPolicyOID = tsaPolicy;
@@ -142,19 +134,22 @@ public class TimeStampTokenGenerator
throw new IllegalArgumentException("SignerInfoGenerator must have an associated certificate");
}
- TSPUtil.validateCertificate(signerInfoGen.getAssociatedCertificate());
+ X509CertificateHolder assocCert = signerInfoGen.getAssociatedCertificate();
+ TSPUtil.validateCertificate(assocCert);
try
{
OutputStream dOut = digestCalculator.getOutputStream();
- dOut.write(signerInfoGen.getAssociatedCertificate().getEncoded());
+ dOut.write(assocCert.getEncoded());
dOut.close();
if (digestCalculator.getAlgorithmIdentifier().getAlgorithm().equals(OIWObjectIdentifiers.idSHA1))
{
- final ESSCertID essCertid = new ESSCertID(digestCalculator.getDigest());
+ final ESSCertID essCertid = new ESSCertID(digestCalculator.getDigest(),
+ isIssuerSerialIncluded ? new IssuerSerial(new GeneralNames(new GeneralName(assocCert.getIssuer())), assocCert.getSerialNumber())
+ : null);
this.signerInfoGen = new SignerInfoGenerator(signerInfoGen, new CMSAttributeTableGenerator()
{
@@ -175,7 +170,9 @@ public class TimeStampTokenGenerator
else
{
AlgorithmIdentifier digAlgID = new AlgorithmIdentifier(digestCalculator.getAlgorithmIdentifier().getAlgorithm());
- final ESSCertIDv2 essCertid = new ESSCertIDv2(digAlgID, digestCalculator.getDigest());
+ final ESSCertIDv2 essCertid = new ESSCertIDv2(digAlgID, digestCalculator.getDigest(),
+ isIssuerSerialIncluded ? new IssuerSerial(new GeneralNames(new GeneralName(assocCert.getIssuer())), new ASN1Integer(assocCert.getSerialNumber()))
+ : null);
this.signerInfoGen = new SignerInfoGenerator(signerInfoGen, new CMSAttributeTableGenerator()
{
@@ -201,185 +198,6 @@ public class TimeStampTokenGenerator
}
/**
- * Basic Constructor - set up a calculator based on signerInfoGen with a ESSCertID calculated from
- * the signer's associated certificate using the sha1DigestCalculator.
- *
- * @param sha1DigestCalculator calculator for SHA-1 of certificate.
- * @param signerInfoGen the generator for the signer we are using.
- * @param tsaPolicy tasPolicy to send.
- * @throws IllegalArgumentException if calculator is not SHA-1 or there is no associated certificate for the signer,
- * @throws TSPException if the signer certificate cannot be processed.
- * @deprecated use constructor taking signerInfoGen first.
- */
- public TimeStampTokenGenerator(
- DigestCalculator sha1DigestCalculator,
- final SignerInfoGenerator signerInfoGen,
- ASN1ObjectIdentifier tsaPolicy)
- throws IllegalArgumentException, TSPException
- {
- this(signerInfoGen, sha1DigestCalculator, tsaPolicy);
- }
-
- /**
- * basic creation - only the default attributes will be included here.
- * @deprecated use SignerInfoGenerator constructor that takes a digest calculator
- */
- public TimeStampTokenGenerator(
- final SignerInfoGenerator signerInfoGen,
- ASN1ObjectIdentifier tsaPolicy)
- throws IllegalArgumentException, TSPException
- {
- this(new DigestCalculator()
- {
- private ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- public AlgorithmIdentifier getAlgorithmIdentifier()
- {
- return new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
- }
-
- public OutputStream getOutputStream()
- {
- return bOut;
- }
-
- public byte[] getDigest()
- {
- try
- {
- return MessageDigest.getInstance("SHA-1").digest(bOut.toByteArray());
- }
- catch (NoSuchAlgorithmException e)
- {
- throw new IllegalStateException("cannot find sha-1: "+ e.getMessage());
- }
- }
- }, signerInfoGen, tsaPolicy);
- }
-
- /**
- * basic creation - only the default attributes will be included here.
- * @deprecated use SignerInfoGenerator constructor that takes a digest calculator.
- */
- public TimeStampTokenGenerator(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- String tsaPolicyOID)
- throws IllegalArgumentException, TSPException
- {
- this(key, cert, digestOID, tsaPolicyOID, null, null);
- }
-
- /**
- * basic creation - only the default attributes will be included here.
- * @deprecated use SignerInfoGenerator constructor that takes a digest calculator.
- */
- public TimeStampTokenGenerator(
- PrivateKey key,
- X509Certificate cert,
- ASN1ObjectIdentifier digestOID,
- String tsaPolicyOID)
- throws IllegalArgumentException, TSPException
- {
- this(key, cert, digestOID.getId(), tsaPolicyOID, null, null);
- }
-
- /**
- * create with a signer with extra signed/unsigned attributes.
- * @deprecated use SignerInfoGenerator constructor that takes a digest calculator.
- */
- public TimeStampTokenGenerator(
- PrivateKey key,
- X509Certificate cert,
- String digestOID,
- String tsaPolicyOID,
- AttributeTable signedAttr,
- AttributeTable unsignedAttr)
- throws IllegalArgumentException, TSPException
- {
- this.key = key;
- this.cert = cert;
- this.digestOID = digestOID;
- this.tsaPolicyOID = new ASN1ObjectIdentifier(tsaPolicyOID);
- this.unsignedAttr = unsignedAttr;
-
- //
- // add the essCertid
- //
- Hashtable signedAttrs = null;
-
- if (signedAttr != null)
- {
- signedAttrs = signedAttr.toHashtable();
- }
- else
- {
- signedAttrs = new Hashtable();
- }
-
-
- TSPUtil.validateCertificate(cert);
-
- try
- {
- ESSCertID essCertid = new ESSCertID(MessageDigest.getInstance("SHA-1").digest(cert.getEncoded()));
- signedAttrs.put(PKCSObjectIdentifiers.id_aa_signingCertificate,
- new Attribute(
- PKCSObjectIdentifiers.id_aa_signingCertificate,
- new DERSet(new SigningCertificate(essCertid))));
- }
- catch (NoSuchAlgorithmException e)
- {
- throw new TSPException("Can't find a SHA-1 implementation.", e);
- }
- catch (CertificateEncodingException e)
- {
- throw new TSPException("Exception processing certificate.", e);
- }
-
- this.signedAttr = new AttributeTable(signedAttrs);
- }
-
- /**
- * @deprecated use addCertificates and addCRLs
- * @param certificates
- * @throws CertStoreException
- * @throws TSPException
- */
- public void setCertificatesAndCRLs(CertStore certificates)
- throws CertStoreException, TSPException
- {
- Collection c1 = certificates.getCertificates(null);
-
- for (Iterator it = c1.iterator(); it.hasNext();)
- {
- try
- {
- certs.add(new JcaX509CertificateHolder((X509Certificate)it.next()));
- }
- catch (CertificateEncodingException e)
- {
- throw new TSPException("cannot encode certificate: " + e.getMessage(), e);
- }
- }
-
- c1 = certificates.getCRLs(null);
-
- for (Iterator it = c1.iterator(); it.hasNext();)
- {
- try
- {
- crls.add(new JcaX509CRLHolder((X509CRL)it.next()));
- }
- catch (CRLException e)
- {
- throw new TSPException("cannot encode CRL: " + e.getMessage(), e);
- }
- }
- }
-
- /**
* Add the store of X509 Certificates to the generator.
*
* @param certStore a Store containing X509CertificateHolder objects
@@ -434,55 +252,22 @@ public class TimeStampTokenGenerator
{
this.tsa = tsa;
}
-
- //------------------------------------------------------------------------------
-
- public TimeStampToken generate(
- TimeStampRequest request,
- BigInteger serialNumber,
- Date genTime,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException, TSPException
- {
- if (signerInfoGen == null)
- {
- try
- {
- JcaSignerInfoGeneratorBuilder sigBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(provider).build());
-
- sigBuilder.setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(signedAttr));
-
- if (unsignedAttr != null)
- {
- sigBuilder.setUnsignedAttributeGenerator(new SimpleAttributeTableGenerator(unsignedAttr));
- }
-
- signerInfoGen = sigBuilder.build(new JcaContentSignerBuilder(getSigAlgorithm(key, digestOID)).setProvider(provider).build(key), cert);
- }
- catch (OperatorCreationException e)
- {
- throw new TSPException("Error generating signing operator", e);
- }
- catch (CertificateEncodingException e)
- {
- throw new TSPException("Error encoding certificate", e);
- }
- }
-
- return generate(request, serialNumber, genTime);
- }
+ /**
+ * Generate a TimeStampToken for the passed in request and serialNumber marking it with the passed in genTime.
+ *
+ * @param request the originating request.
+ * @param serialNumber serial number for the TimeStampToken
+ * @param genTime token generation time.
+ * @return a TimeStampToken
+ * @throws TSPException
+ */
public TimeStampToken generate(
TimeStampRequest request,
BigInteger serialNumber,
Date genTime)
throws TSPException
{
- if (signerInfoGen == null)
- {
- throw new IllegalStateException("can only use this method with SignerInfoGenerator constructor");
- }
-
ASN1ObjectIdentifier digestAlgOID = request.getMessageImprintAlgOID();
AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, DERNull.INSTANCE);
@@ -568,34 +353,4 @@ public class TimeStampTokenGenerator
throw new TSPException("Exception encoding info", e);
}
}
-
- private String getSigAlgorithm(
- PrivateKey key,
- String digestOID)
- {
- String enc = null;
-
- if (key instanceof RSAPrivateKey || "RSA".equalsIgnoreCase(key.getAlgorithm()))
- {
- enc = "RSA";
- }
- else if (key instanceof DSAPrivateKey || "DSA".equalsIgnoreCase(key.getAlgorithm()))
- {
- enc = "DSA";
- }
- else if ("ECDSA".equalsIgnoreCase(key.getAlgorithm()) || "EC".equalsIgnoreCase(key.getAlgorithm()))
- {
- enc = "ECDSA";
- }
- else if (key instanceof GOST3410PrivateKey || "GOST3410".equalsIgnoreCase(key.getAlgorithm()))
- {
- enc = "GOST3410";
- }
- else if ("ECGOST3410".equalsIgnoreCase(key.getAlgorithm()))
- {
- enc = CMSSignedGenerator.ENCRYPTION_ECGOST3410;
- }
-
- return TSPUtil.getDigestAlgName(digestOID) + "with" + enc;
- }
}
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/cms/package.html b/bcpkix/src/main/java/org/bouncycastle/tsp/cms/package.html
deleted file mode 100644
index 2cf1bac..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/cms/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for dealing Syntax for Binding Documents with Time-Stamps - RFC 5544.
-</body>
-</html>
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/package.html b/bcpkix/src/main/java/org/bouncycastle/tsp/package.html
deleted file mode 100644
index 45d0c3c..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for dealing Time Stamp Protocol (TSP) - RFC 3161.
-</body>
-</html>
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/test/AllTests.java b/bcpkix/src/main/java/org/bouncycastle/tsp/test/AllTests.java
index 87d4688..19fc664 100644
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/test/AllTests.java
+++ b/bcpkix/src/main/java/org/bouncycastle/tsp/test/AllTests.java
@@ -22,7 +22,6 @@ public class AllTests
TestSuite suite = new TestSuite("TSP Tests");
suite.addTestSuite(ParseTest.class);
- suite.addTestSuite(TSPTest.class);
suite.addTestSuite(NewTSPTest.class);
suite.addTestSuite(CMSTimeStampedDataTest.class);
suite.addTestSuite(CMSTimeStampedDataParserTest.class);
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/test/CMSTimeStampedDataGeneratorTest.java b/bcpkix/src/main/java/org/bouncycastle/tsp/test/CMSTimeStampedDataGeneratorTest.java
index e274dc0..a9ab7db 100644
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/test/CMSTimeStampedDataGeneratorTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/tsp/test/CMSTimeStampedDataGeneratorTest.java
@@ -81,7 +81,7 @@ public class CMSTimeStampedDataGeneratorTest
throws Exception
{
BcDigestCalculatorProvider calculatorProvider = new BcDigestCalculatorProvider();
- String algOID = "2.16.840.1.101.3.4.2.1"; // SHA-256
+ ASN1ObjectIdentifier algOID = new ASN1ObjectIdentifier("2.16.840.1.101.3.4.2.1"); // SHA-256
DigestCalculator hashCalculator = calculatorProvider.get(new AlgorithmIdentifier(algOID));
cmsTimeStampedDataGenerator.initialiseMessageImprintDigestCalculator(hashCalculator);
@@ -125,7 +125,7 @@ public class CMSTimeStampedDataGeneratorTest
cmsTimeStampedDataGenerator.setMetaData(true, fileInput, "TXT");
BcDigestCalculatorProvider calculatorProvider = new BcDigestCalculatorProvider();
- String algOID = "2.16.840.1.101.3.4.2.1"; // SHA-256
+ ASN1ObjectIdentifier algOID = new ASN1ObjectIdentifier("2.16.840.1.101.3.4.2.1"); // SHA-256
DigestCalculator hashCalculator = calculatorProvider.get(new AlgorithmIdentifier(algOID));
cmsTimeStampedDataGenerator.initialiseMessageImprintDigestCalculator(hashCalculator);
@@ -136,7 +136,7 @@ public class CMSTimeStampedDataGeneratorTest
TimeStampToken timeStampToken = createTimeStampToken(hashCalculator.getDigest(), NISTObjectIdentifiers.id_sha256);
CMSTimeStampedData cmsTimeStampedData = cmsTimeStampedDataGenerator.generate(timeStampToken, baseData);
- for (int i = 0; i < 3; i++)
+ for (int i = 0; i <= 3; i++)
{
byte[] newRequestData = cmsTimeStampedData.calculateNextHash(hashCalculator);
TimeStampToken newTimeStampToken = createTimeStampToken(newRequestData, NISTObjectIdentifiers.id_sha256);
@@ -167,7 +167,7 @@ public class CMSTimeStampedDataGeneratorTest
CMSTimeStampedData cmsTimeStampedData = cmsTimeStampedDataGenerator.generate(timeStampToken, baseData);
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i <= 3; i++) {
switch (i) {
case 0:
algIdentifier = NISTObjectIdentifiers.id_sha224;
@@ -213,7 +213,7 @@ public class CMSTimeStampedDataGeneratorTest
byte[] digest = imprintCalculator.getDigest();
TimeStampToken[] tokens = cmsTspData.getTimeStampTokens();
- assertEquals("TimeStampToken expected and verified are different", 4, tokens.length);
+ assertEquals("TimeStampToken expected and verified are different", 5, tokens.length);
for (int i = 0; i < tokens.length; i++)
{
cmsTspData.validate(newCalculatorProvider, digest, tokens[i]);
@@ -243,7 +243,7 @@ public class CMSTimeStampedDataGeneratorTest
byte[] digest = imprintCalculator.getDigest();
TimeStampToken[] tokens = cmsTspData.getTimeStampTokens();
- assertEquals("TimeStampToken expected and verified are different", 4, tokens.length);
+ assertEquals("TimeStampToken expected and verified are different", 5, tokens.length);
for (int i = 0; i < tokens.length; i++)
{
cmsTspData.validate(newCalculatorProvider, digest, tokens[i]);
@@ -291,7 +291,7 @@ public class CMSTimeStampedDataGeneratorTest
TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- new JcaSimpleSignerInfoGeneratorBuilder().build(algorithmName, privateKey, cert), new ASN1ObjectIdentifier("1.2"));
+ new JcaSimpleSignerInfoGeneratorBuilder().build(algorithmName, privateKey, cert), new SHA1DigestCalculator(), new ASN1ObjectIdentifier("1.2"));
tsTokenGen.addCertificates(certs);
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/test/NewTSPTest.java b/bcpkix/src/main/java/org/bouncycastle/tsp/test/NewTSPTest.java
index 7f69e6e..7bf19be 100644
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/test/NewTSPTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/tsp/test/NewTSPTest.java
@@ -724,7 +724,7 @@ public class NewTSPTest
TimeStampToken tsToken = tsResp.getTimeStampToken();
- tsToken.validate(cert, "BC");
+ tsToken.validate(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert));
//
// check validation
@@ -771,7 +771,7 @@ public class NewTSPTest
{
JcaSignerInfoGeneratorBuilder infoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build());
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(infoGeneratorBuilder.build(new JcaContentSignerBuilder("MD5withRSA").setProvider(BC).build(privateKey), cert), new ASN1ObjectIdentifier("1.2.3"));
+ TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(infoGeneratorBuilder.build(new JcaContentSignerBuilder("MD5withRSA").setProvider(BC).build(privateKey), cert), new SHA1DigestCalculator(), new ASN1ObjectIdentifier("1.2.3"));
tsTokenGen.addCertificates(certs);
@@ -788,7 +788,7 @@ public class NewTSPTest
TimeStampToken tsToken = tsResp.getTimeStampToken();
- tsToken.validate(cert, "BC");
+ tsToken.validate(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert));
//
// check validation
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/test/ParseTest.java b/bcpkix/src/main/java/org/bouncycastle/tsp/test/ParseTest.java
index d94bfb7..557d012 100644
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/test/ParseTest.java
+++ b/bcpkix/src/main/java/org/bouncycastle/tsp/test/ParseTest.java
@@ -299,7 +299,7 @@ public class ParseTest
try
{
- req.validate(TSPAlgorithms.ALLOWED, null, null, "BC");
+ req.validate(TSPAlgorithms.ALLOWED, null, null);
}
catch (Exception e)
{
@@ -327,7 +327,7 @@ public class ParseTest
resp.validate(req);
- resp.getTimeStampToken().validate(cert, "BC");
+ resp.getTimeStampToken().validate(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert));
}
private void unacceptableResponseParse(
diff --git a/bcpkix/src/main/java/org/bouncycastle/tsp/test/TSPTest.java b/bcpkix/src/main/java/org/bouncycastle/tsp/test/TSPTest.java
deleted file mode 100644
index f0d635d..0000000
--- a/bcpkix/src/main/java/org/bouncycastle/tsp/test/TSPTest.java
+++ /dev/null
@@ -1,603 +0,0 @@
-package org.bouncycastle.tsp.test;
-
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.cert.CertStore;
-import java.security.cert.CollectionCertStoreParameters;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-
-import junit.framework.TestCase;
-import org.bouncycastle.asn1.cmp.PKIFailureInfo;
-import org.bouncycastle.asn1.cms.AttributeTable;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.tsp.GenTimeAccuracy;
-import org.bouncycastle.tsp.TSPAlgorithms;
-import org.bouncycastle.tsp.TSPValidationException;
-import org.bouncycastle.tsp.TimeStampRequest;
-import org.bouncycastle.tsp.TimeStampRequestGenerator;
-import org.bouncycastle.tsp.TimeStampResponse;
-import org.bouncycastle.tsp.TimeStampResponseGenerator;
-import org.bouncycastle.tsp.TimeStampToken;
-import org.bouncycastle.tsp.TimeStampTokenGenerator;
-import org.bouncycastle.tsp.TimeStampTokenInfo;
-import org.bouncycastle.util.Arrays;
-
-public class TSPTest
- extends TestCase
-{
- public void testGeneral()
- throws Exception
- {
- String signDN = "O=Bouncy Castle, C=AU";
- KeyPair signKP = TSPTestUtil.makeKeyPair();
- X509Certificate signCert = TSPTestUtil.makeCACertificate(signKP,
- signDN, signKP, signDN);
-
- String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU";
- KeyPair origKP = TSPTestUtil.makeKeyPair();
- X509Certificate origCert = TSPTestUtil.makeCertificate(origKP,
- origDN, signKP, signDN);
-
-
-
- List certList = new ArrayList();
- certList.add(origCert);
- certList.add(signCert);
-
- CertStore certs = CertStore.getInstance("Collection",
- new CollectionCertStoreParameters(certList), "BC");
-
- basicTest(origKP.getPrivate(), origCert, certs);
- responseValidationTest(origKP.getPrivate(), origCert, certs);
- incorrectHashTest(origKP.getPrivate(), origCert, certs);
- badAlgorithmTest(origKP.getPrivate(), origCert, certs);
- timeNotAvailableTest(origKP.getPrivate(), origCert, certs);
- badPolicyTest(origKP.getPrivate(), origCert, certs);
- tokenEncodingTest(origKP.getPrivate(), origCert, certs);
- certReqTest(origKP.getPrivate(), origCert, certs);
- testAccuracyZeroCerts(origKP.getPrivate(), origCert, certs);
- testAccuracyWithCertsAndOrdering(origKP.getPrivate(), origCert, certs);
- testNoNonse(origKP.getPrivate(), origCert, certs);
- }
-
- private void basicTest(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.SHA1, "1.2");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
- TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100));
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- tsToken.validate(cert, "BC");
-
- AttributeTable table = tsToken.getSignedAttributes();
-
- assertNotNull("no signingCertificate attribute found", table.get(PKCSObjectIdentifiers.id_aa_signingCertificate));
- }
-
- private void responseValidationTest(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.MD5, "1.2");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
- TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100));
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- tsToken.validate(cert, "BC");
-
- //
- // check validation
- //
- tsResp.validate(request);
-
- try
- {
- request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(101));
-
- tsResp.validate(request);
-
- fail("response validation failed on invalid nonce.");
- }
- catch (TSPValidationException e)
- {
- // ignore
- }
-
- try
- {
- request = reqGen.generate(TSPAlgorithms.SHA1, new byte[22], BigInteger.valueOf(100));
-
- tsResp.validate(request);
-
- fail("response validation failed on wrong digest.");
- }
- catch (TSPValidationException e)
- {
- // ignore
- }
-
- try
- {
- request = reqGen.generate(TSPAlgorithms.MD5, new byte[20], BigInteger.valueOf(100));
-
- tsResp.validate(request);
-
- fail("response validation failed on wrong digest.");
- }
- catch (TSPValidationException e)
- {
- // ignore
- }
- }
-
- private void incorrectHashTest(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.SHA1, "1.2");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
- TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[16]);
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- if (tsToken != null)
- {
- fail("incorrectHash - token not null.");
- }
-
- PKIFailureInfo failInfo = tsResp.getFailInfo();
-
- if (failInfo == null)
- {
- fail("incorrectHash - failInfo set to null.");
- }
-
- if (failInfo.intValue() != PKIFailureInfo.badDataFormat)
- {
- fail("incorrectHash - wrong failure info returned.");
- }
- }
-
- private void badAlgorithmTest(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.SHA1, "1.2");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
- TimeStampRequest request = reqGen.generate("1.2.3.4.5", new byte[20]);
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- if (tsToken != null)
- {
- fail("badAlgorithm - token not null.");
- }
-
- PKIFailureInfo failInfo = tsResp.getFailInfo();
-
- if (failInfo == null)
- {
- fail("badAlgorithm - failInfo set to null.");
- }
-
- if (failInfo.intValue() != PKIFailureInfo.badAlg)
- {
- fail("badAlgorithm - wrong failure info returned.");
- }
- }
-
- private void timeNotAvailableTest(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.SHA1, "1.2");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
- TimeStampRequest request = reqGen.generate("1.2.3.4.5", new byte[20]);
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), null, "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- if (tsToken != null)
- {
- fail("timeNotAvailable - token not null.");
- }
-
- PKIFailureInfo failInfo = tsResp.getFailInfo();
-
- if (failInfo == null)
- {
- fail("timeNotAvailable - failInfo set to null.");
- }
-
- if (failInfo.intValue() != PKIFailureInfo.timeNotAvailable)
- {
- fail("timeNotAvailable - wrong failure info returned.");
- }
- }
-
- private void badPolicyTest(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.SHA1, "1.2");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
-
- reqGen.setReqPolicy("1.1");
-
- TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20]);
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED, new HashSet());
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- if (tsToken != null)
- {
- fail("badPolicy - token not null.");
- }
-
- PKIFailureInfo failInfo = tsResp.getFailInfo();
-
- if (failInfo == null)
- {
- fail("badPolicy - failInfo set to null.");
- }
-
- if (failInfo.intValue() != PKIFailureInfo.unacceptedPolicy)
- {
- fail("badPolicy - wrong failure info returned.");
- }
- }
-
- private void certReqTest(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.MD5, "1.2");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
-
- //
- // request with certReq false
- //
- reqGen.setCertReq(false);
-
- TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100));
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- assertNull(tsToken.getTimeStampInfo().getGenTimeAccuracy()); // check for abscence of accuracy
-
- assertEquals("1.2", tsToken.getTimeStampInfo().getPolicy().getId());
-
- try
- {
- tsToken.validate(cert, "BC");
- }
- catch (TSPValidationException e)
- {
- fail("certReq(false) verification of token failed.");
- }
-
- CertStore respCerts = tsToken.getCertificatesAndCRLs("Collection", "BC");
-
- Collection certsColl = respCerts.getCertificates(null);
-
- if (!certsColl.isEmpty())
- {
- fail("certReq(false) found certificates in response.");
- }
- }
-
-
- private void tokenEncodingTest(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.SHA1, "1.2.3.4.5.6");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
- TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100));
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampResponse tsResponse = new TimeStampResponse(tsResp.getEncoded());
-
- if (!Arrays.areEqual(tsResponse.getEncoded(), tsResp.getEncoded())
- || !Arrays.areEqual(tsResponse.getTimeStampToken().getEncoded(),
- tsResp.getTimeStampToken().getEncoded()))
- {
- fail();
- }
- }
-
- private void testAccuracyZeroCerts(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.MD5, "1.2");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- tsTokenGen.setAccuracySeconds(1);
- tsTokenGen.setAccuracyMillis(2);
- tsTokenGen.setAccuracyMicros(3);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
- TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100));
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- tsToken.validate(cert, "BC");
-
- //
- // check validation
- //
- tsResp.validate(request);
-
- //
- // check tstInfo
- //
- TimeStampTokenInfo tstInfo = tsToken.getTimeStampInfo();
-
- //
- // check accuracy
- //
- GenTimeAccuracy accuracy = tstInfo.getGenTimeAccuracy();
-
- assertEquals(1, accuracy.getSeconds());
- assertEquals(2, accuracy.getMillis());
- assertEquals(3, accuracy.getMicros());
-
- assertEquals(new BigInteger("23"), tstInfo.getSerialNumber());
-
- assertEquals("1.2", tstInfo.getPolicy().getId());
-
- //
- // test certReq
- //
- CertStore store = tsToken.getCertificatesAndCRLs("Collection", "BC");
-
- Collection certificates = store.getCertificates(null);
-
- assertEquals(0, certificates.size());
- }
-
- private void testAccuracyWithCertsAndOrdering(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.MD5, "1.2.3");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- tsTokenGen.setAccuracySeconds(3);
- tsTokenGen.setAccuracyMillis(1);
- tsTokenGen.setAccuracyMicros(2);
-
- tsTokenGen.setOrdering(true);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
-
- reqGen.setCertReq(true);
-
- TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100));
-
- assertTrue(request.getCertReq());
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- tsToken.validate(cert, "BC");
-
- //
- // check validation
- //
- tsResp.validate(request);
-
- //
- // check tstInfo
- //
- TimeStampTokenInfo tstInfo = tsToken.getTimeStampInfo();
-
- //
- // check accuracy
- //
- GenTimeAccuracy accuracy = tstInfo.getGenTimeAccuracy();
-
- assertEquals(3, accuracy.getSeconds());
- assertEquals(1, accuracy.getMillis());
- assertEquals(2, accuracy.getMicros());
-
- assertEquals(new BigInteger("23"), tstInfo.getSerialNumber());
-
- assertEquals("1.2.3", tstInfo.getPolicy().getId());
-
- assertEquals(true, tstInfo.isOrdered());
-
- assertEquals(tstInfo.getNonce(), BigInteger.valueOf(100));
-
- //
- // test certReq
- //
- CertStore store = tsToken.getCertificatesAndCRLs("Collection", "BC");
-
- Collection certificates = store.getCertificates(null);
-
- assertEquals(2, certificates.size());
- }
-
- private void testNoNonse(
- PrivateKey privateKey,
- X509Certificate cert,
- CertStore certs)
- throws Exception
- {
- TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
- privateKey, cert, TSPAlgorithms.MD5, "1.2.3");
-
- tsTokenGen.setCertificatesAndCRLs(certs);
-
- TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
- TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20]);
-
- assertFalse(request.getCertReq());
-
- TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED);
-
- TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("24"), new Date(), "BC");
-
- tsResp = new TimeStampResponse(tsResp.getEncoded());
-
- TimeStampToken tsToken = tsResp.getTimeStampToken();
-
- tsToken.validate(cert, "BC");
-
- //
- // check validation
- //
- tsResp.validate(request);
-
- //
- // check tstInfo
- //
- TimeStampTokenInfo tstInfo = tsToken.getTimeStampInfo();
-
- //
- // check accuracy
- //
- GenTimeAccuracy accuracy = tstInfo.getGenTimeAccuracy();
-
- assertNull(accuracy);
-
- assertEquals(new BigInteger("24"), tstInfo.getSerialNumber());
-
- assertEquals("1.2.3", tstInfo.getPolicy().getId());
-
- assertEquals(false, tstInfo.isOrdered());
-
- assertNull(tstInfo.getNonce());
-
- //
- // test certReq
- //
- CertStore store = tsToken.getCertificatesAndCRLs("Collection", "BC");
-
- Collection certificates = store.getCertificates(null);
-
- assertEquals(0, certificates.size());
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/LICENSE.java b/bcprov/src/main/java/org/bouncycastle/LICENSE.java
index b97d88b..b02dfbc 100644
--- a/bcprov/src/main/java/org/bouncycastle/LICENSE.java
+++ b/bcprov/src/main/java/org/bouncycastle/LICENSE.java
@@ -3,7 +3,7 @@ package org.bouncycastle;
/**
* The Bouncy Castle License
*
- * Copyright (c) 2000-2012 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
+ * Copyright (c) 2000-2013 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
* <p>
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
@@ -24,7 +24,7 @@ package org.bouncycastle;
public class LICENSE
{
public static String licenseText =
- "Copyright (c) 2000-2012 The Legion Of The Bouncy Castle (http://www.bouncycastle.org) "
+ "Copyright (c) 2000-2013 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) "
+ System.getProperty("line.separator")
+ System.getProperty("line.separator")
+ "Permission is hereby granted, free of charge, to any person obtaining a copy of this software "
diff --git a/bcprov/src/main/java/org/bouncycastle/apache/bzip2/BZip2Constants.java b/bcprov/src/main/java/org/bouncycastle/apache/bzip2/BZip2Constants.java
new file mode 100644
index 0000000..e86bdee
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/apache/bzip2/BZip2Constants.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+package org.bouncycastle.apache.bzip2;
+
+/**
+ * Base class for both the compress and decompress classes.
+ * Holds common arrays, and static data.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+public interface BZip2Constants {
+
+ int baseBlockSize = 100000;
+ int MAX_ALPHA_SIZE = 258;
+ int MAX_CODE_LEN = 23;
+ int RUNA = 0;
+ int RUNB = 1;
+ int N_GROUPS = 6;
+ int G_SIZE = 50;
+ int N_ITERS = 4;
+ int MAX_SELECTORS = (2 + (900000 / G_SIZE));
+ int NUM_OVERSHOOT_BYTES = 20;
+
+ int[] rNums = {
+ 619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
+ 985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
+ 733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
+ 419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
+ 878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
+ 862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
+ 150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
+ 170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
+ 73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
+ 909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
+ 641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
+ 161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
+ 382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
+ 98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
+ 227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
+ 469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
+ 184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
+ 715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
+ 951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
+ 652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
+ 645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
+ 609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
+ 653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
+ 411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
+ 170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
+ 857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
+ 669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
+ 944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
+ 344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
+ 897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
+ 433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
+ 686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
+ 946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
+ 978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
+ 680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
+ 707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
+ 297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
+ 134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
+ 343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
+ 140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
+ 170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
+ 369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
+ 804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
+ 896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
+ 661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
+ 768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
+ 61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
+ 372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
+ 780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
+ 920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
+ 645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
+ 936, 638
+ };
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/apache/bzip2/CBZip2InputStream.java b/bcprov/src/main/java/org/bouncycastle/apache/bzip2/CBZip2InputStream.java
new file mode 100644
index 0000000..08d05e7
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/apache/bzip2/CBZip2InputStream.java
@@ -0,0 +1,848 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+package org.bouncycastle.apache.bzip2;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * An input stream that decompresses from the BZip2 format (with the file
+ * header chars) to be read as any other stream.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ *
+ * <b>NB:</b> note this class has been modified to read the leading BZ from the
+ * start of the BZIP2 stream to make it compatible with other PGP programs.
+ */
+public class CBZip2InputStream extends InputStream implements BZip2Constants {
+ private static void cadvise() {
+ System.out.println("CRC Error");
+ //throw new CCoruptionError();
+ }
+
+// private static void badBGLengths() {
+// cadvise();
+// }
+//
+// private static void bitStreamEOF() {
+// cadvise();
+// }
+
+ private static void compressedStreamEOF() {
+ cadvise();
+ }
+
+ private void makeMaps() {
+ int i;
+ nInUse = 0;
+ for (i = 0; i < 256; i++) {
+ if (inUse[i]) {
+ seqToUnseq[nInUse] = (char) i;
+ unseqToSeq[i] = (char) nInUse;
+ nInUse++;
+ }
+ }
+ }
+
+ /*
+ index of the last char in the block, so
+ the block size == last + 1.
+ */
+ private int last;
+
+ /*
+ index in zptr[] of original string after sorting.
+ */
+ private int origPtr;
+
+ /*
+ always: in the range 0 .. 9.
+ The current block size is 100000 * this number.
+ */
+ private int blockSize100k;
+
+ private boolean blockRandomised;
+
+ private int bsBuff;
+ private int bsLive;
+ private CRC mCrc = new CRC();
+
+ private boolean[] inUse = new boolean[256];
+ private int nInUse;
+
+ private char[] seqToUnseq = new char[256];
+ private char[] unseqToSeq = new char[256];
+
+ private char[] selector = new char[MAX_SELECTORS];
+ private char[] selectorMtf = new char[MAX_SELECTORS];
+
+ private int[] tt;
+ private char[] ll8;
+
+ /*
+ freq table collected to save a pass over the data
+ during decompression.
+ */
+ private int[] unzftab = new int[256];
+
+ private int[][] limit = new int[N_GROUPS][MAX_ALPHA_SIZE];
+ private int[][] base = new int[N_GROUPS][MAX_ALPHA_SIZE];
+ private int[][] perm = new int[N_GROUPS][MAX_ALPHA_SIZE];
+ private int[] minLens = new int[N_GROUPS];
+
+ private InputStream bsStream;
+
+ private boolean streamEnd = false;
+
+ private int currentChar = -1;
+
+ private static final int START_BLOCK_STATE = 1;
+ private static final int RAND_PART_A_STATE = 2;
+ private static final int RAND_PART_B_STATE = 3;
+ private static final int RAND_PART_C_STATE = 4;
+ private static final int NO_RAND_PART_A_STATE = 5;
+ private static final int NO_RAND_PART_B_STATE = 6;
+ private static final int NO_RAND_PART_C_STATE = 7;
+
+ private int currentState = START_BLOCK_STATE;
+
+ private int storedBlockCRC, storedCombinedCRC;
+ private int computedBlockCRC, computedCombinedCRC;
+
+ int i2, count, chPrev, ch2;
+ int i, tPos;
+ int rNToGo = 0;
+ int rTPos = 0;
+ int j2;
+ char z;
+
+ public CBZip2InputStream(InputStream zStream)
+ throws IOException
+ {
+ ll8 = null;
+ tt = null;
+ bsSetStream(zStream);
+ initialize();
+ initBlock();
+ setupBlock();
+ }
+
+ public int read() {
+ if (streamEnd) {
+ return -1;
+ } else {
+ int retChar = currentChar;
+ switch(currentState) {
+ case START_BLOCK_STATE:
+ break;
+ case RAND_PART_A_STATE:
+ break;
+ case RAND_PART_B_STATE:
+ setupRandPartB();
+ break;
+ case RAND_PART_C_STATE:
+ setupRandPartC();
+ break;
+ case NO_RAND_PART_A_STATE:
+ break;
+ case NO_RAND_PART_B_STATE:
+ setupNoRandPartB();
+ break;
+ case NO_RAND_PART_C_STATE:
+ setupNoRandPartC();
+ break;
+ default:
+ break;
+ }
+ return retChar;
+ }
+ }
+
+ private void initialize() throws IOException {
+ char magic3, magic4;
+ magic3 = bsGetUChar();
+ magic4 = bsGetUChar();
+ if (magic3 != 'B' && magic4 != 'Z')
+ {
+ throw new IOException("Not a BZIP2 marked stream");
+ }
+ magic3 = bsGetUChar();
+ magic4 = bsGetUChar();
+ if (magic3 != 'h' || magic4 < '1' || magic4 > '9') {
+ bsFinishedWithStream();
+ streamEnd = true;
+ return;
+ }
+
+ setDecompressStructureSizes(magic4 - '0');
+ computedCombinedCRC = 0;
+ }
+
+ private void initBlock() {
+ char magic1, magic2, magic3, magic4;
+ char magic5, magic6;
+ magic1 = bsGetUChar();
+ magic2 = bsGetUChar();
+ magic3 = bsGetUChar();
+ magic4 = bsGetUChar();
+ magic5 = bsGetUChar();
+ magic6 = bsGetUChar();
+ if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45
+ && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
+ complete();
+ return;
+ }
+
+ if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59
+ || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
+ badBlockHeader();
+ streamEnd = true;
+ return;
+ }
+
+ storedBlockCRC = bsGetInt32();
+
+ if (bsR(1) == 1) {
+ blockRandomised = true;
+ } else {
+ blockRandomised = false;
+ }
+
+ // currBlockNo++;
+ getAndMoveToFrontDecode();
+
+ mCrc.initialiseCRC();
+ currentState = START_BLOCK_STATE;
+ }
+
+ private void endBlock() {
+ computedBlockCRC = mCrc.getFinalCRC();
+ /* A bad CRC is considered a fatal error. */
+ if (storedBlockCRC != computedBlockCRC) {
+ crcError();
+ }
+
+ computedCombinedCRC = (computedCombinedCRC << 1)
+ | (computedCombinedCRC >>> 31);
+ computedCombinedCRC ^= computedBlockCRC;
+ }
+
+ private void complete() {
+ storedCombinedCRC = bsGetInt32();
+ if (storedCombinedCRC != computedCombinedCRC) {
+ crcError();
+ }
+
+ bsFinishedWithStream();
+ streamEnd = true;
+ }
+
+ private static void blockOverrun() {
+ cadvise();
+ }
+
+ private static void badBlockHeader() {
+ cadvise();
+ }
+
+ private static void crcError() {
+ cadvise();
+ }
+
+ private void bsFinishedWithStream() {
+ try {
+ if (this.bsStream != null) {
+ if (this.bsStream != System.in) {
+ this.bsStream.close();
+ this.bsStream = null;
+ }
+ }
+ } catch (IOException ioe) {
+ //ignore
+ }
+ }
+
+ private void bsSetStream(InputStream f) {
+ bsStream = f;
+ bsLive = 0;
+ bsBuff = 0;
+ }
+
+ private int bsR(int n) {
+ int v;
+ while (bsLive < n) {
+ int zzi;
+ char thech = 0;
+ try {
+ thech = (char) bsStream.read();
+ } catch (IOException e) {
+ compressedStreamEOF();
+ }
+ if (thech == -1) {
+ compressedStreamEOF();
+ }
+ zzi = thech;
+ bsBuff = (bsBuff << 8) | (zzi & 0xff);
+ bsLive += 8;
+ }
+
+ v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
+ bsLive -= n;
+ return v;
+ }
+
+ private char bsGetUChar() {
+ return (char) bsR(8);
+ }
+
+ private int bsGetint() {
+ int u = 0;
+ u = (u << 8) | bsR(8);
+ u = (u << 8) | bsR(8);
+ u = (u << 8) | bsR(8);
+ u = (u << 8) | bsR(8);
+ return u;
+ }
+
+ private int bsGetIntVS(int numBits) {
+ return (int) bsR(numBits);
+ }
+
+ private int bsGetInt32() {
+ return (int) bsGetint();
+ }
+
+ private void hbCreateDecodeTables(int[] limit, int[] base,
+ int[] perm, char[] length,
+ int minLen, int maxLen, int alphaSize) {
+ int pp, i, j, vec;
+
+ pp = 0;
+ for (i = minLen; i <= maxLen; i++) {
+ for (j = 0; j < alphaSize; j++) {
+ if (length[j] == i) {
+ perm[pp] = j;
+ pp++;
+ }
+ }
+ }
+
+ for (i = 0; i < MAX_CODE_LEN; i++) {
+ base[i] = 0;
+ }
+ for (i = 0; i < alphaSize; i++) {
+ base[length[i] + 1]++;
+ }
+
+ for (i = 1; i < MAX_CODE_LEN; i++) {
+ base[i] += base[i - 1];
+ }
+
+ for (i = 0; i < MAX_CODE_LEN; i++) {
+ limit[i] = 0;
+ }
+ vec = 0;
+
+ for (i = minLen; i <= maxLen; i++) {
+ vec += (base[i + 1] - base[i]);
+ limit[i] = vec - 1;
+ vec <<= 1;
+ }
+ for (i = minLen + 1; i <= maxLen; i++) {
+ base[i] = ((limit[i - 1] + 1) << 1) - base[i];
+ }
+ }
+
+ private void recvDecodingTables() {
+ char len[][] = new char[N_GROUPS][MAX_ALPHA_SIZE];
+ int i, j, t, nGroups, nSelectors, alphaSize;
+ int minLen, maxLen;
+ boolean[] inUse16 = new boolean[16];
+
+ /* Receive the mapping table */
+ for (i = 0; i < 16; i++) {
+ if (bsR(1) == 1) {
+ inUse16[i] = true;
+ } else {
+ inUse16[i] = false;
+ }
+ }
+
+ for (i = 0; i < 256; i++) {
+ inUse[i] = false;
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (inUse16[i]) {
+ for (j = 0; j < 16; j++) {
+ if (bsR(1) == 1) {
+ inUse[i * 16 + j] = true;
+ }
+ }
+ }
+ }
+
+ makeMaps();
+ alphaSize = nInUse + 2;
+
+ /* Now the selectors */
+ nGroups = bsR(3);
+ nSelectors = bsR(15);
+ for (i = 0; i < nSelectors; i++) {
+ j = 0;
+ while (bsR(1) == 1) {
+ j++;
+ }
+ selectorMtf[i] = (char) j;
+ }
+
+ /* Undo the MTF values for the selectors. */
+ {
+ char[] pos = new char[N_GROUPS];
+ char tmp, v;
+ for (v = 0; v < nGroups; v++) {
+ pos[v] = v;
+ }
+
+ for (i = 0; i < nSelectors; i++) {
+ v = selectorMtf[i];
+ tmp = pos[v];
+ while (v > 0) {
+ pos[v] = pos[v - 1];
+ v--;
+ }
+ pos[0] = tmp;
+ selector[i] = tmp;
+ }
+ }
+
+ /* Now the coding tables */
+ for (t = 0; t < nGroups; t++) {
+ int curr = bsR(5);
+ for (i = 0; i < alphaSize; i++) {
+ while (bsR(1) == 1) {
+ if (bsR(1) == 0) {
+ curr++;
+ } else {
+ curr--;
+ }
+ }
+ len[t][i] = (char) curr;
+ }
+ }
+
+ /* Create the Huffman decoding tables */
+ for (t = 0; t < nGroups; t++) {
+ minLen = 32;
+ maxLen = 0;
+ for (i = 0; i < alphaSize; i++) {
+ if (len[t][i] > maxLen) {
+ maxLen = len[t][i];
+ }
+ if (len[t][i] < minLen) {
+ minLen = len[t][i];
+ }
+ }
+ hbCreateDecodeTables(limit[t], base[t], perm[t], len[t], minLen,
+ maxLen, alphaSize);
+ minLens[t] = minLen;
+ }
+ }
+
+ private void getAndMoveToFrontDecode() {
+ char[] yy = new char[256];
+ int i, j, nextSym, limitLast;
+ int EOB, groupNo, groupPos;
+
+ limitLast = baseBlockSize * blockSize100k;
+ origPtr = bsGetIntVS(24);
+
+ recvDecodingTables();
+ EOB = nInUse + 1;
+ groupNo = -1;
+ groupPos = 0;
+
+ /*
+ Setting up the unzftab entries here is not strictly
+ necessary, but it does save having to do it later
+ in a separate pass, and so saves a block's worth of
+ cache misses.
+ */
+ for (i = 0; i <= 255; i++) {
+ unzftab[i] = 0;
+ }
+
+ for (i = 0; i <= 255; i++) {
+ yy[i] = (char) i;
+ }
+
+ last = -1;
+
+ {
+ int zt, zn, zvec, zj;
+ if (groupPos == 0) {
+ groupNo++;
+ groupPos = G_SIZE;
+ }
+ groupPos--;
+ zt = selector[groupNo];
+ zn = minLens[zt];
+ zvec = bsR(zn);
+ while (zvec > limit[zt][zn]) {
+ zn++;
+ {
+ {
+ while (bsLive < 1) {
+ int zzi;
+ char thech = 0;
+ try {
+ thech = (char) bsStream.read();
+ } catch (IOException e) {
+ compressedStreamEOF();
+ }
+ if (thech == -1) {
+ compressedStreamEOF();
+ }
+ zzi = thech;
+ bsBuff = (bsBuff << 8) | (zzi & 0xff);
+ bsLive += 8;
+ }
+ }
+ zj = (bsBuff >> (bsLive - 1)) & 1;
+ bsLive--;
+ }
+ zvec = (zvec << 1) | zj;
+ }
+ nextSym = perm[zt][zvec - base[zt][zn]];
+ }
+
+ while (true) {
+
+ if (nextSym == EOB) {
+ break;
+ }
+
+ if (nextSym == RUNA || nextSym == RUNB) {
+ char ch;
+ int s = -1;
+ int N = 1;
+ do {
+ if (nextSym == RUNA) {
+ s = s + (0 + 1) * N;
+ } else if (nextSym == RUNB) {
+ s = s + (1 + 1) * N;
+ }
+ N = N * 2;
+ {
+ int zt, zn, zvec, zj;
+ if (groupPos == 0) {
+ groupNo++;
+ groupPos = G_SIZE;
+ }
+ groupPos--;
+ zt = selector[groupNo];
+ zn = minLens[zt];
+ zvec = bsR(zn);
+ while (zvec > limit[zt][zn]) {
+ zn++;
+ {
+ {
+ while (bsLive < 1) {
+ int zzi;
+ char thech = 0;
+ try {
+ thech = (char) bsStream.read();
+ } catch (IOException e) {
+ compressedStreamEOF();
+ }
+ if (thech == -1) {
+ compressedStreamEOF();
+ }
+ zzi = thech;
+ bsBuff = (bsBuff << 8) | (zzi & 0xff);
+ bsLive += 8;
+ }
+ }
+ zj = (bsBuff >> (bsLive - 1)) & 1;
+ bsLive--;
+ }
+ zvec = (zvec << 1) | zj;
+ }
+ nextSym = perm[zt][zvec - base[zt][zn]];
+ }
+ } while (nextSym == RUNA || nextSym == RUNB);
+
+ s++;
+ ch = seqToUnseq[yy[0]];
+ unzftab[ch] += s;
+
+ while (s > 0) {
+ last++;
+ ll8[last] = ch;
+ s--;
+ }
+
+ if (last >= limitLast) {
+ blockOverrun();
+ }
+ continue;
+ } else {
+ char tmp;
+ last++;
+ if (last >= limitLast) {
+ blockOverrun();
+ }
+
+ tmp = yy[nextSym - 1];
+ unzftab[seqToUnseq[tmp]]++;
+ ll8[last] = seqToUnseq[tmp];
+
+ /*
+ This loop is hammered during decompression,
+ hence the unrolling.
+
+ for (j = nextSym-1; j > 0; j--) yy[j] = yy[j-1];
+ */
+
+ j = nextSym - 1;
+ for (; j > 3; j -= 4) {
+ yy[j] = yy[j - 1];
+ yy[j - 1] = yy[j - 2];
+ yy[j - 2] = yy[j - 3];
+ yy[j - 3] = yy[j - 4];
+ }
+ for (; j > 0; j--) {
+ yy[j] = yy[j - 1];
+ }
+
+ yy[0] = tmp;
+ {
+ int zt, zn, zvec, zj;
+ if (groupPos == 0) {
+ groupNo++;
+ groupPos = G_SIZE;
+ }
+ groupPos--;
+ zt = selector[groupNo];
+ zn = minLens[zt];
+ zvec = bsR(zn);
+ while (zvec > limit[zt][zn]) {
+ zn++;
+ {
+ {
+ while (bsLive < 1) {
+ int zzi;
+ char thech = 0;
+ try {
+ thech = (char) bsStream.read();
+ } catch (IOException e) {
+ compressedStreamEOF();
+ }
+ zzi = thech;
+ bsBuff = (bsBuff << 8) | (zzi & 0xff);
+ bsLive += 8;
+ }
+ }
+ zj = (bsBuff >> (bsLive - 1)) & 1;
+ bsLive--;
+ }
+ zvec = (zvec << 1) | zj;
+ }
+ nextSym = perm[zt][zvec - base[zt][zn]];
+ }
+ continue;
+ }
+ }
+ }
+
+ private void setupBlock() {
+ int[] cftab = new int[257];
+ char ch;
+
+ cftab[0] = 0;
+ for (i = 1; i <= 256; i++) {
+ cftab[i] = unzftab[i - 1];
+ }
+ for (i = 1; i <= 256; i++) {
+ cftab[i] += cftab[i - 1];
+ }
+
+ for (i = 0; i <= last; i++) {
+ ch = (char) ll8[i];
+ tt[cftab[ch]] = i;
+ cftab[ch]++;
+ }
+ cftab = null;
+
+ tPos = tt[origPtr];
+
+ count = 0;
+ i2 = 0;
+ ch2 = 256; /* not a char and not EOF */
+
+ if (blockRandomised) {
+ rNToGo = 0;
+ rTPos = 0;
+ setupRandPartA();
+ } else {
+ setupNoRandPartA();
+ }
+ }
+
+ private void setupRandPartA() {
+ if (i2 <= last) {
+ chPrev = ch2;
+ ch2 = ll8[tPos];
+ tPos = tt[tPos];
+ if (rNToGo == 0) {
+ rNToGo = rNums[rTPos];
+ rTPos++;
+ if (rTPos == 512) {
+ rTPos = 0;
+ }
+ }
+ rNToGo--;
+ ch2 ^= (int) ((rNToGo == 1) ? 1 : 0);
+ i2++;
+
+ currentChar = ch2;
+ currentState = RAND_PART_B_STATE;
+ mCrc.updateCRC(ch2);
+ } else {
+ endBlock();
+ initBlock();
+ setupBlock();
+ }
+ }
+
+ private void setupNoRandPartA() {
+ if (i2 <= last) {
+ chPrev = ch2;
+ ch2 = ll8[tPos];
+ tPos = tt[tPos];
+ i2++;
+
+ currentChar = ch2;
+ currentState = NO_RAND_PART_B_STATE;
+ mCrc.updateCRC(ch2);
+ } else {
+ endBlock();
+ initBlock();
+ setupBlock();
+ }
+ }
+
+ private void setupRandPartB() {
+ if (ch2 != chPrev) {
+ currentState = RAND_PART_A_STATE;
+ count = 1;
+ setupRandPartA();
+ } else {
+ count++;
+ if (count >= 4) {
+ z = ll8[tPos];
+ tPos = tt[tPos];
+ if (rNToGo == 0) {
+ rNToGo = rNums[rTPos];
+ rTPos++;
+ if (rTPos == 512) {
+ rTPos = 0;
+ }
+ }
+ rNToGo--;
+ z ^= ((rNToGo == 1) ? 1 : 0);
+ j2 = 0;
+ currentState = RAND_PART_C_STATE;
+ setupRandPartC();
+ } else {
+ currentState = RAND_PART_A_STATE;
+ setupRandPartA();
+ }
+ }
+ }
+
+ private void setupRandPartC() {
+ if (j2 < (int) z) {
+ currentChar = ch2;
+ mCrc.updateCRC(ch2);
+ j2++;
+ } else {
+ currentState = RAND_PART_A_STATE;
+ i2++;
+ count = 0;
+ setupRandPartA();
+ }
+ }
+
+ private void setupNoRandPartB() {
+ if (ch2 != chPrev) {
+ currentState = NO_RAND_PART_A_STATE;
+ count = 1;
+ setupNoRandPartA();
+ } else {
+ count++;
+ if (count >= 4) {
+ z = ll8[tPos];
+ tPos = tt[tPos];
+ currentState = NO_RAND_PART_C_STATE;
+ j2 = 0;
+ setupNoRandPartC();
+ } else {
+ currentState = NO_RAND_PART_A_STATE;
+ setupNoRandPartA();
+ }
+ }
+ }
+
+ private void setupNoRandPartC() {
+ if (j2 < (int) z) {
+ currentChar = ch2;
+ mCrc.updateCRC(ch2);
+ j2++;
+ } else {
+ currentState = NO_RAND_PART_A_STATE;
+ i2++;
+ count = 0;
+ setupNoRandPartA();
+ }
+ }
+
+ private void setDecompressStructureSizes(int newSize100k) {
+ if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k
+ && blockSize100k <= 9)) {
+ // throw new IOException("Invalid block size");
+ }
+
+ blockSize100k = newSize100k;
+
+ if (newSize100k == 0) {
+ return;
+ }
+
+ int n = baseBlockSize * newSize100k;
+ ll8 = new char[n];
+ tt = new int[n];
+ }
+}
+
diff --git a/bcprov/src/main/java/org/bouncycastle/apache/bzip2/CBZip2OutputStream.java b/bcprov/src/main/java/org/bouncycastle/apache/bzip2/CBZip2OutputStream.java
new file mode 100644
index 0000000..0503583
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/apache/bzip2/CBZip2OutputStream.java
@@ -0,0 +1,1651 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+package org.bouncycastle.apache.bzip2;
+
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * An output stream that compresses into the BZip2 format (with the file
+ * header chars) into another stream.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ *
+ * TODO: Update to BZip2 1.0.1
+ * <b>NB:</b> note this class has been modified to add a leading BZ to the
+ * start of the BZIP2 stream to make it compatible with other PGP programs.
+ */
+public class CBZip2OutputStream extends OutputStream implements BZip2Constants {
+ protected static final int SETMASK = (1 << 21);
+ protected static final int CLEARMASK = (~SETMASK);
+ protected static final int GREATER_ICOST = 15;
+ protected static final int LESSER_ICOST = 0;
+ protected static final int SMALL_THRESH = 20;
+ protected static final int DEPTH_THRESH = 10;
+
+ /*
+ If you are ever unlucky/improbable enough
+ to get a stack overflow whilst sorting,
+ increase the following constant and try
+ again. In practice I have never seen the
+ stack go above 27 elems, so the following
+ limit seems very generous.
+ */
+ protected static final int QSORT_STACK_SIZE = 1000;
+ private boolean finished;
+
+ private static void panic() {
+ System.out.println("panic");
+ //throw new CError();
+ }
+
+ private void makeMaps() {
+ int i;
+ nInUse = 0;
+ for (i = 0; i < 256; i++) {
+ if (inUse[i]) {
+ seqToUnseq[nInUse] = (char) i;
+ unseqToSeq[i] = (char) nInUse;
+ nInUse++;
+ }
+ }
+ }
+
+ protected static void hbMakeCodeLengths(char[] len, int[] freq,
+ int alphaSize, int maxLen) {
+ /*
+ Nodes and heap entries run from 1. Entry 0
+ for both the heap and nodes is a sentinel.
+ */
+ int nNodes, nHeap, n1, n2, i, j, k;
+ boolean tooLong;
+
+ int[] heap = new int[MAX_ALPHA_SIZE + 2];
+ int[] weight = new int[MAX_ALPHA_SIZE * 2];
+ int[] parent = new int[MAX_ALPHA_SIZE * 2];
+
+ for (i = 0; i < alphaSize; i++) {
+ weight[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
+ }
+
+ while (true) {
+ nNodes = alphaSize;
+ nHeap = 0;
+
+ heap[0] = 0;
+ weight[0] = 0;
+ parent[0] = -2;
+
+ for (i = 1; i <= alphaSize; i++) {
+ parent[i] = -1;
+ nHeap++;
+ heap[nHeap] = i;
+ {
+ int zz, tmp;
+ zz = nHeap;
+ tmp = heap[zz];
+ while (weight[tmp] < weight[heap[zz >> 1]]) {
+ heap[zz] = heap[zz >> 1];
+ zz >>= 1;
+ }
+ heap[zz] = tmp;
+ }
+ }
+ if (!(nHeap < (MAX_ALPHA_SIZE + 2))) {
+ panic();
+ }
+
+ while (nHeap > 1) {
+ n1 = heap[1];
+ heap[1] = heap[nHeap];
+ nHeap--;
+ {
+ int zz = 0, yy = 0, tmp = 0;
+ zz = 1;
+ tmp = heap[zz];
+ while (true) {
+ yy = zz << 1;
+ if (yy > nHeap) {
+ break;
+ }
+ if (yy < nHeap
+ && weight[heap[yy + 1]] < weight[heap[yy]]) {
+ yy++;
+ }
+ if (weight[tmp] < weight[heap[yy]]) {
+ break;
+ }
+ heap[zz] = heap[yy];
+ zz = yy;
+ }
+ heap[zz] = tmp;
+ }
+ n2 = heap[1];
+ heap[1] = heap[nHeap];
+ nHeap--;
+ {
+ int zz = 0, yy = 0, tmp = 0;
+ zz = 1;
+ tmp = heap[zz];
+ while (true) {
+ yy = zz << 1;
+ if (yy > nHeap) {
+ break;
+ }
+ if (yy < nHeap
+ && weight[heap[yy + 1]] < weight[heap[yy]]) {
+ yy++;
+ }
+ if (weight[tmp] < weight[heap[yy]]) {
+ break;
+ }
+ heap[zz] = heap[yy];
+ zz = yy;
+ }
+ heap[zz] = tmp;
+ }
+ nNodes++;
+ parent[n1] = parent[n2] = nNodes;
+
+ weight[nNodes] = ((weight[n1] & 0xffffff00)
+ + (weight[n2] & 0xffffff00))
+ | (1 + (((weight[n1] & 0x000000ff) >
+ (weight[n2] & 0x000000ff)) ?
+ (weight[n1] & 0x000000ff) :
+ (weight[n2] & 0x000000ff)));
+
+ parent[nNodes] = -1;
+ nHeap++;
+ heap[nHeap] = nNodes;
+ {
+ int zz = 0, tmp = 0;
+ zz = nHeap;
+ tmp = heap[zz];
+ while (weight[tmp] < weight[heap[zz >> 1]]) {
+ heap[zz] = heap[zz >> 1];
+ zz >>= 1;
+ }
+ heap[zz] = tmp;
+ }
+ }
+ if (!(nNodes < (MAX_ALPHA_SIZE * 2))) {
+ panic();
+ }
+
+ tooLong = false;
+ for (i = 1; i <= alphaSize; i++) {
+ j = 0;
+ k = i;
+ while (parent[k] >= 0) {
+ k = parent[k];
+ j++;
+ }
+ len[i - 1] = (char) j;
+ if (j > maxLen) {
+ tooLong = true;
+ }
+ }
+
+ if (!tooLong) {
+ break;
+ }
+
+ for (i = 1; i < alphaSize; i++) {
+ j = weight[i] >> 8;
+ j = 1 + (j / 2);
+ weight[i] = j << 8;
+ }
+ }
+ }
+
+ /*
+ index of the last char in the block, so
+ the block size == last + 1.
+ */
+ int last;
+
+ /*
+ index in zptr[] of original string after sorting.
+ */
+ int origPtr;
+
+ /*
+ always: in the range 0 .. 9.
+ The current block size is 100000 * this number.
+ */
+ int blockSize100k;
+
+ boolean blockRandomised;
+
+ int bytesOut;
+ int bsBuff;
+ int bsLive;
+ CRC mCrc = new CRC();
+
+ private boolean[] inUse = new boolean[256];
+ private int nInUse;
+
+ private char[] seqToUnseq = new char[256];
+ private char[] unseqToSeq = new char[256];
+
+ private char[] selector = new char[MAX_SELECTORS];
+ private char[] selectorMtf = new char[MAX_SELECTORS];
+
+ private char[] block;
+ private int[] quadrant;
+ private int[] zptr;
+ private short[] szptr;
+ private int[] ftab;
+
+ private int nMTF;
+
+ private int[] mtfFreq = new int[MAX_ALPHA_SIZE];
+
+ /*
+ * Used when sorting. If too many long comparisons
+ * happen, we stop sorting, randomise the block
+ * slightly, and try again.
+ */
+ private int workFactor;
+ private int workDone;
+ private int workLimit;
+ private boolean firstAttempt;
+ private int nBlocksRandomised;
+
+ private int currentChar = -1;
+ private int runLength = 0;
+
+ public CBZip2OutputStream(OutputStream inStream) throws IOException {
+ this(inStream, 9);
+ }
+
+ public CBZip2OutputStream(OutputStream inStream, int inBlockSize)
+ throws IOException {
+ block = null;
+ quadrant = null;
+ zptr = null;
+ ftab = null;
+
+ inStream.write('B');
+ inStream.write('Z');
+
+ bsSetStream(inStream);
+
+ workFactor = 50;
+ if (inBlockSize > 9) {
+ inBlockSize = 9;
+ }
+ if (inBlockSize < 1) {
+ inBlockSize = 1;
+ }
+ blockSize100k = inBlockSize;
+ allocateCompressStructures();
+ initialize();
+ initBlock();
+ }
+
+ /**
+ *
+ * modified by Oliver Merkel, 010128
+ *
+ */
+ public void write(int bv) throws IOException {
+ int b = (256 + bv) % 256;
+ if (currentChar != -1) {
+ if (currentChar == b) {
+ runLength++;
+ if (runLength > 254) {
+ writeRun();
+ currentChar = -1;
+ runLength = 0;
+ }
+ } else {
+ writeRun();
+ runLength = 1;
+ currentChar = b;
+ }
+ } else {
+ currentChar = b;
+ runLength++;
+ }
+ }
+
+ private void writeRun() throws IOException {
+ if (last < allowableBlockSize) {
+ inUse[currentChar] = true;
+ for (int i = 0; i < runLength; i++) {
+ mCrc.updateCRC((char) currentChar);
+ }
+ switch (runLength) {
+ case 1:
+ last++;
+ block[last + 1] = (char) currentChar;
+ break;
+ case 2:
+ last++;
+ block[last + 1] = (char) currentChar;
+ last++;
+ block[last + 1] = (char) currentChar;
+ break;
+ case 3:
+ last++;
+ block[last + 1] = (char) currentChar;
+ last++;
+ block[last + 1] = (char) currentChar;
+ last++;
+ block[last + 1] = (char) currentChar;
+ break;
+ default:
+ inUse[runLength - 4] = true;
+ last++;
+ block[last + 1] = (char) currentChar;
+ last++;
+ block[last + 1] = (char) currentChar;
+ last++;
+ block[last + 1] = (char) currentChar;
+ last++;
+ block[last + 1] = (char) currentChar;
+ last++;
+ block[last + 1] = (char) (runLength - 4);
+ break;
+ }
+ } else {
+ endBlock();
+ initBlock();
+ writeRun();
+ }
+ }
+
+ boolean closed = false;
+
+ protected void finalize() throws Throwable {
+ close();
+ super.finalize();
+ }
+
+ public void close() throws IOException {
+ if (closed) {
+ return;
+ }
+
+ finish();
+
+ closed = true;
+ super.close();
+ bsStream.close();
+ }
+
+ public void finish() throws IOException {
+ if (finished) {
+ return;
+ }
+
+ if (runLength > 0) {
+ writeRun();
+ }
+ currentChar = -1;
+ endBlock();
+ endCompression();
+ finished = true;
+ flush();
+ }
+
+ public void flush() throws IOException {
+ super.flush();
+ bsStream.flush();
+ }
+
+ private int blockCRC, combinedCRC;
+
+ private void initialize() throws IOException {
+ bytesOut = 0;
+ nBlocksRandomised = 0;
+
+ /* Write `magic' bytes h indicating file-format == huffmanised,
+ followed by a digit indicating blockSize100k.
+ */
+ bsPutUChar('h');
+ bsPutUChar('0' + blockSize100k);
+
+ combinedCRC = 0;
+ }
+
+ private int allowableBlockSize;
+
+ private void initBlock() {
+ // blockNo++;
+ mCrc.initialiseCRC();
+ last = -1;
+ // ch = 0;
+
+ for (int i = 0; i < 256; i++) {
+ inUse[i] = false;
+ }
+
+ /* 20 is just a paranoia constant */
+ allowableBlockSize = baseBlockSize * blockSize100k - 20;
+ }
+
+ private void endBlock() throws IOException {
+ blockCRC = mCrc.getFinalCRC();
+ combinedCRC = (combinedCRC << 1) | (combinedCRC >>> 31);
+ combinedCRC ^= blockCRC;
+
+ /* sort the block and establish posn of original string */
+ doReversibleTransformation();
+
+ /*
+ A 6-byte block header, the value chosen arbitrarily
+ as 0x314159265359 :-). A 32 bit value does not really
+ give a strong enough guarantee that the value will not
+ appear by chance in the compressed datastream. Worst-case
+ probability of this event, for a 900k block, is about
+ 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits.
+ For a compressed file of size 100Gb -- about 100000 blocks --
+ only a 48-bit marker will do. NB: normal compression/
+ decompression do *not* rely on these statistical properties.
+ They are only important when trying to recover blocks from
+ damaged files.
+ */
+ bsPutUChar(0x31);
+ bsPutUChar(0x41);
+ bsPutUChar(0x59);
+ bsPutUChar(0x26);
+ bsPutUChar(0x53);
+ bsPutUChar(0x59);
+
+ /* Now the block's CRC, so it is in a known place. */
+ bsPutint(blockCRC);
+
+ /* Now a single bit indicating randomisation. */
+ if (blockRandomised) {
+ bsW(1, 1);
+ nBlocksRandomised++;
+ } else {
+ bsW(1, 0);
+ }
+
+ /* Finally, block's contents proper. */
+ moveToFrontCodeAndSend();
+ }
+
+ private void endCompression() throws IOException {
+ /*
+ Now another magic 48-bit number, 0x177245385090, to
+ indicate the end of the last block. (sqrt(pi), if
+ you want to know. I did want to use e, but it contains
+ too much repetition -- 27 18 28 18 28 46 -- for me
+ to feel statistically comfortable. Call me paranoid.)
+ */
+ bsPutUChar(0x17);
+ bsPutUChar(0x72);
+ bsPutUChar(0x45);
+ bsPutUChar(0x38);
+ bsPutUChar(0x50);
+ bsPutUChar(0x90);
+
+ bsPutint(combinedCRC);
+
+ bsFinishedWithStream();
+ }
+
+ private void hbAssignCodes (int[] code, char[] length, int minLen,
+ int maxLen, int alphaSize) {
+ int n, vec, i;
+
+ vec = 0;
+ for (n = minLen; n <= maxLen; n++) {
+ for (i = 0; i < alphaSize; i++) {
+ if (length[i] == n) {
+ code[i] = vec;
+ vec++;
+ }
+ }
+ vec <<= 1;
+ }
+ }
+
+ private void bsSetStream(OutputStream f) {
+ bsStream = f;
+ bsLive = 0;
+ bsBuff = 0;
+ bytesOut = 0;
+ }
+
+ private void bsFinishedWithStream() throws IOException {
+ while (bsLive > 0) {
+ int ch = (bsBuff >> 24);
+ try {
+ bsStream.write(ch); // write 8-bit
+ } catch (IOException e) {
+ throw e;
+ }
+ bsBuff <<= 8;
+ bsLive -= 8;
+ bytesOut++;
+ }
+ }
+
+ private void bsW(int n, int v) throws IOException {
+ while (bsLive >= 8) {
+ int ch = (bsBuff >> 24);
+ try {
+ bsStream.write(ch); // write 8-bit
+ } catch (IOException e) {
+ throw e;
+ }
+ bsBuff <<= 8;
+ bsLive -= 8;
+ bytesOut++;
+ }
+ bsBuff |= (v << (32 - bsLive - n));
+ bsLive += n;
+ }
+
+ private void bsPutUChar(int c) throws IOException {
+ bsW(8, c);
+ }
+
+ private void bsPutint(int u) throws IOException {
+ bsW(8, (u >> 24) & 0xff);
+ bsW(8, (u >> 16) & 0xff);
+ bsW(8, (u >> 8) & 0xff);
+ bsW(8, u & 0xff);
+ }
+
+ private void bsPutIntVS(int numBits, int c) throws IOException {
+ bsW(numBits, c);
+ }
+
+ private void sendMTFValues() throws IOException {
+ char len[][] = new char[N_GROUPS][MAX_ALPHA_SIZE];
+
+ int v, t, i, j, gs, ge, totc, bt, bc, iter;
+ int nSelectors = 0, alphaSize, minLen, maxLen, selCtr;
+ int nGroups;//, nBytes;
+
+ alphaSize = nInUse + 2;
+ for (t = 0; t < N_GROUPS; t++) {
+ for (v = 0; v < alphaSize; v++) {
+ len[t][v] = (char) GREATER_ICOST;
+ }
+ }
+
+ /* Decide how many coding tables to use */
+ if (nMTF <= 0) {
+ panic();
+ }
+
+ if (nMTF < 200) {
+ nGroups = 2;
+ } else if (nMTF < 600) {
+ nGroups = 3;
+ } else if (nMTF < 1200) {
+ nGroups = 4;
+ } else if (nMTF < 2400) {
+ nGroups = 5;
+ } else {
+ nGroups = 6;
+ }
+
+ /* Generate an initial set of coding tables */ {
+ int nPart, remF, tFreq, aFreq;
+
+ nPart = nGroups;
+ remF = nMTF;
+ gs = 0;
+ while (nPart > 0) {
+ tFreq = remF / nPart;
+ ge = gs - 1;
+ aFreq = 0;
+ while (aFreq < tFreq && ge < alphaSize - 1) {
+ ge++;
+ aFreq += mtfFreq[ge];
+ }
+
+ if (ge > gs && nPart != nGroups && nPart != 1
+ && ((nGroups - nPart) % 2 == 1)) {
+ aFreq -= mtfFreq[ge];
+ ge--;
+ }
+
+ for (v = 0; v < alphaSize; v++) {
+ if (v >= gs && v <= ge) {
+ len[nPart - 1][v] = (char) LESSER_ICOST;
+ } else {
+ len[nPart - 1][v] = (char) GREATER_ICOST;
+ }
+ }
+
+ nPart--;
+ gs = ge + 1;
+ remF -= aFreq;
+ }
+ }
+
+ int[][] rfreq = new int[N_GROUPS][MAX_ALPHA_SIZE];
+ int[] fave = new int[N_GROUPS];
+ short[] cost = new short[N_GROUPS];
+ /*
+ Iterate up to N_ITERS times to improve the tables.
+ */
+ for (iter = 0; iter < N_ITERS; iter++) {
+ for (t = 0; t < nGroups; t++) {
+ fave[t] = 0;
+ }
+
+ for (t = 0; t < nGroups; t++) {
+ for (v = 0; v < alphaSize; v++) {
+ rfreq[t][v] = 0;
+ }
+ }
+
+ nSelectors = 0;
+ totc = 0;
+ gs = 0;
+ while (true) {
+
+ /* Set group start & end marks. */
+ if (gs >= nMTF) {
+ break;
+ }
+ ge = gs + G_SIZE - 1;
+ if (ge >= nMTF) {
+ ge = nMTF - 1;
+ }
+
+ /*
+ Calculate the cost of this group as coded
+ by each of the coding tables.
+ */
+ for (t = 0; t < nGroups; t++) {
+ cost[t] = 0;
+ }
+
+ if (nGroups == 6) {
+ short cost0, cost1, cost2, cost3, cost4, cost5;
+ cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0;
+ for (i = gs; i <= ge; i++) {
+ short icv = szptr[i];
+ cost0 += len[0][icv];
+ cost1 += len[1][icv];
+ cost2 += len[2][icv];
+ cost3 += len[3][icv];
+ cost4 += len[4][icv];
+ cost5 += len[5][icv];
+ }
+ cost[0] = cost0;
+ cost[1] = cost1;
+ cost[2] = cost2;
+ cost[3] = cost3;
+ cost[4] = cost4;
+ cost[5] = cost5;
+ } else {
+ for (i = gs; i <= ge; i++) {
+ short icv = szptr[i];
+ for (t = 0; t < nGroups; t++) {
+ cost[t] += len[t][icv];
+ }
+ }
+ }
+
+ /*
+ Find the coding table which is best for this group,
+ and record its identity in the selector table.
+ */
+ bc = 999999999;
+ bt = -1;
+ for (t = 0; t < nGroups; t++) {
+ if (cost[t] < bc) {
+ bc = cost[t];
+ bt = t;
+ }
+ }
+ totc += bc;
+ fave[bt]++;
+ selector[nSelectors] = (char) bt;
+ nSelectors++;
+
+ /*
+ Increment the symbol frequencies for the selected table.
+ */
+ for (i = gs; i <= ge; i++) {
+ rfreq[bt][szptr[i]]++;
+ }
+
+ gs = ge + 1;
+ }
+
+ /*
+ Recompute the tables based on the accumulated frequencies.
+ */
+ for (t = 0; t < nGroups; t++) {
+ hbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20);
+ }
+ }
+
+ rfreq = null;
+ fave = null;
+ cost = null;
+
+ if (!(nGroups < 8)) {
+ panic();
+ }
+ if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / G_SIZE)))) {
+ panic();
+ }
+
+
+ /* Compute MTF values for the selectors. */
+ {
+ char[] pos = new char[N_GROUPS];
+ char ll_i, tmp2, tmp;
+ for (i = 0; i < nGroups; i++) {
+ pos[i] = (char) i;
+ }
+ for (i = 0; i < nSelectors; i++) {
+ ll_i = selector[i];
+ j = 0;
+ tmp = pos[j];
+ while (ll_i != tmp) {
+ j++;
+ tmp2 = tmp;
+ tmp = pos[j];
+ pos[j] = tmp2;
+ }
+ pos[0] = tmp;
+ selectorMtf[i] = (char) j;
+ }
+ }
+
+ int[][] code = new int[N_GROUPS][MAX_ALPHA_SIZE];
+
+ /* Assign actual codes for the tables. */
+ for (t = 0; t < nGroups; t++) {
+ minLen = 32;
+ maxLen = 0;
+ for (i = 0; i < alphaSize; i++) {
+ if (len[t][i] > maxLen) {
+ maxLen = len[t][i];
+ }
+ if (len[t][i] < minLen) {
+ minLen = len[t][i];
+ }
+ }
+ if (maxLen > 20) {
+ panic();
+ }
+ if (minLen < 1) {
+ panic();
+ }
+ hbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize);
+ }
+
+ /* Transmit the mapping table. */
+ {
+ boolean[] inUse16 = new boolean[16];
+ for (i = 0; i < 16; i++) {
+ inUse16[i] = false;
+ for (j = 0; j < 16; j++) {
+ if (inUse[i * 16 + j]) {
+ inUse16[i] = true;
+ }
+ }
+ }
+
+// nBytes = bytesOut;
+ for (i = 0; i < 16; i++) {
+ if (inUse16[i]) {
+ bsW(1, 1);
+ } else {
+ bsW(1, 0);
+ }
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (inUse16[i]) {
+ for (j = 0; j < 16; j++) {
+ if (inUse[i * 16 + j]) {
+ bsW(1, 1);
+ } else {
+ bsW(1, 0);
+ }
+ }
+ }
+ }
+
+ }
+
+ /* Now the selectors. */
+// nBytes = bytesOut;
+ bsW (3, nGroups);
+ bsW (15, nSelectors);
+ for (i = 0; i < nSelectors; i++) {
+ for (j = 0; j < selectorMtf[i]; j++) {
+ bsW(1, 1);
+ }
+ bsW(1, 0);
+ }
+
+ /* Now the coding tables. */
+// nBytes = bytesOut;
+
+ for (t = 0; t < nGroups; t++) {
+ int curr = len[t][0];
+ bsW(5, curr);
+ for (i = 0; i < alphaSize; i++) {
+ while (curr < len[t][i]) {
+ bsW(2, 2);
+ curr++; /* 10 */
+ }
+ while (curr > len[t][i]) {
+ bsW(2, 3);
+ curr--; /* 11 */
+ }
+ bsW (1, 0);
+ }
+ }
+
+ /* And finally, the block data proper */
+// nBytes = bytesOut;
+ selCtr = 0;
+ gs = 0;
+ while (true) {
+ if (gs >= nMTF) {
+ break;
+ }
+ ge = gs + G_SIZE - 1;
+ if (ge >= nMTF) {
+ ge = nMTF - 1;
+ }
+ for (i = gs; i <= ge; i++) {
+ bsW(len[selector[selCtr]][szptr[i]],
+ code[selector[selCtr]][szptr[i]]);
+ }
+
+ gs = ge + 1;
+ selCtr++;
+ }
+ if (!(selCtr == nSelectors)) {
+ panic();
+ }
+ }
+
+ private void moveToFrontCodeAndSend () throws IOException {
+ bsPutIntVS(24, origPtr);
+ generateMTFValues();
+ sendMTFValues();
+ }
+
+ private OutputStream bsStream;
+
+ private void simpleSort(int lo, int hi, int d) {
+ int i, j, h, bigN, hp;
+ int v;
+
+ bigN = hi - lo + 1;
+ if (bigN < 2) {
+ return;
+ }
+
+ hp = 0;
+ while (incs[hp] < bigN) {
+ hp++;
+ }
+ hp--;
+
+ for (; hp >= 0; hp--) {
+ h = incs[hp];
+
+ i = lo + h;
+ while (true) {
+ /* copy 1 */
+ if (i > hi) {
+ break;
+ }
+ v = zptr[i];
+ j = i;
+ while (fullGtU(zptr[j - h] + d, v + d)) {
+ zptr[j] = zptr[j - h];
+ j = j - h;
+ if (j <= (lo + h - 1)) {
+ break;
+ }
+ }
+ zptr[j] = v;
+ i++;
+
+ /* copy 2 */
+ if (i > hi) {
+ break;
+ }
+ v = zptr[i];
+ j = i;
+ while (fullGtU(zptr[j - h] + d, v + d)) {
+ zptr[j] = zptr[j - h];
+ j = j - h;
+ if (j <= (lo + h - 1)) {
+ break;
+ }
+ }
+ zptr[j] = v;
+ i++;
+
+ /* copy 3 */
+ if (i > hi) {
+ break;
+ }
+ v = zptr[i];
+ j = i;
+ while (fullGtU(zptr[j - h] + d, v + d)) {
+ zptr[j] = zptr[j - h];
+ j = j - h;
+ if (j <= (lo + h - 1)) {
+ break;
+ }
+ }
+ zptr[j] = v;
+ i++;
+
+ if (workDone > workLimit && firstAttempt) {
+ return;
+ }
+ }
+ }
+ }
+
+ private void vswap(int p1, int p2, int n) {
+ int temp = 0;
+ while (n > 0) {
+ temp = zptr[p1];
+ zptr[p1] = zptr[p2];
+ zptr[p2] = temp;
+ p1++;
+ p2++;
+ n--;
+ }
+ }
+
+ private char med3(char a, char b, char c) {
+ char t;
+ if (a > b) {
+ t = a;
+ a = b;
+ b = t;
+ }
+ if (b > c) {
+ t = b;
+ b = c;
+ c = t;
+ }
+ if (a > b) {
+ b = a;
+ }
+ return b;
+ }
+
+ private static class StackElem {
+ int ll;
+ int hh;
+ int dd;
+ }
+
+ private void qSort3(int loSt, int hiSt, int dSt) {
+ int unLo, unHi, ltLo, gtHi, med, n, m;
+ int sp, lo, hi, d;
+ StackElem[] stack = new StackElem[QSORT_STACK_SIZE];
+ for (int count = 0; count < QSORT_STACK_SIZE; count++) {
+ stack[count] = new StackElem();
+ }
+
+ sp = 0;
+
+ stack[sp].ll = loSt;
+ stack[sp].hh = hiSt;
+ stack[sp].dd = dSt;
+ sp++;
+
+ while (sp > 0) {
+ if (sp >= QSORT_STACK_SIZE) {
+ panic();
+ }
+
+ sp--;
+ lo = stack[sp].ll;
+ hi = stack[sp].hh;
+ d = stack[sp].dd;
+
+ if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) {
+ simpleSort(lo, hi, d);
+ if (workDone > workLimit && firstAttempt) {
+ return;
+ }
+ continue;
+ }
+
+ med = med3(block[zptr[lo] + d + 1],
+ block[zptr[hi ] + d + 1],
+ block[zptr[(lo + hi) >> 1] + d + 1]);
+
+ unLo = ltLo = lo;
+ unHi = gtHi = hi;
+
+ while (true) {
+ while (true) {
+ if (unLo > unHi) {
+ break;
+ }
+ n = ((int) block[zptr[unLo] + d + 1]) - med;
+ if (n == 0) {
+ int temp = 0;
+ temp = zptr[unLo];
+ zptr[unLo] = zptr[ltLo];
+ zptr[ltLo] = temp;
+ ltLo++;
+ unLo++;
+ continue;
+ }
+ if (n > 0) {
+ break;
+ }
+ unLo++;
+ }
+ while (true) {
+ if (unLo > unHi) {
+ break;
+ }
+ n = ((int) block[zptr[unHi] + d + 1]) - med;
+ if (n == 0) {
+ int temp = 0;
+ temp = zptr[unHi];
+ zptr[unHi] = zptr[gtHi];
+ zptr[gtHi] = temp;
+ gtHi--;
+ unHi--;
+ continue;
+ }
+ if (n < 0) {
+ break;
+ }
+ unHi--;
+ }
+ if (unLo > unHi) {
+ break;
+ }
+ int temp = 0;
+ temp = zptr[unLo];
+ zptr[unLo] = zptr[unHi];
+ zptr[unHi] = temp;
+ unLo++;
+ unHi--;
+ }
+
+ if (gtHi < ltLo) {
+ stack[sp].ll = lo;
+ stack[sp].hh = hi;
+ stack[sp].dd = d + 1;
+ sp++;
+ continue;
+ }
+
+ n = ((ltLo - lo) < (unLo - ltLo)) ? (ltLo - lo) : (unLo - ltLo);
+ vswap(lo, unLo - n, n);
+ m = ((hi - gtHi) < (gtHi - unHi)) ? (hi - gtHi) : (gtHi - unHi);
+ vswap(unLo, hi - m + 1, m);
+
+ n = lo + unLo - ltLo - 1;
+ m = hi - (gtHi - unHi) + 1;
+
+ stack[sp].ll = lo;
+ stack[sp].hh = n;
+ stack[sp].dd = d;
+ sp++;
+
+ stack[sp].ll = n + 1;
+ stack[sp].hh = m - 1;
+ stack[sp].dd = d + 1;
+ sp++;
+
+ stack[sp].ll = m;
+ stack[sp].hh = hi;
+ stack[sp].dd = d;
+ sp++;
+ }
+ }
+
+ private void mainSort() {
+ int i, j, ss, sb;
+ int[] runningOrder = new int[256];
+ int[] copy = new int[256];
+ boolean[] bigDone = new boolean[256];
+ int c1, c2;
+ int numQSorted;
+
+ /*
+ In the various block-sized structures, live data runs
+ from 0 to last+NUM_OVERSHOOT_BYTES inclusive. First,
+ set up the overshoot area for block.
+ */
+
+ // if (verbosity >= 4) fprintf ( stderr, " sort initialise ...\n" );
+ for (i = 0; i < NUM_OVERSHOOT_BYTES; i++) {
+ block[last + i + 2] = block[(i % (last + 1)) + 1];
+ }
+ for (i = 0; i <= last + NUM_OVERSHOOT_BYTES; i++) {
+ quadrant[i] = 0;
+ }
+
+ block[0] = (char) (block[last + 1]);
+
+ if (last < 4000) {
+ /*
+ Use simpleSort(), since the full sorting mechanism
+ has quite a large constant overhead.
+ */
+ for (i = 0; i <= last; i++) {
+ zptr[i] = i;
+ }
+ firstAttempt = false;
+ workDone = workLimit = 0;
+ simpleSort(0, last, 0);
+ } else {
+ numQSorted = 0;
+ for (i = 0; i <= 255; i++) {
+ bigDone[i] = false;
+ }
+
+ for (i = 0; i <= 65536; i++) {
+ ftab[i] = 0;
+ }
+
+ c1 = block[0];
+ for (i = 0; i <= last; i++) {
+ c2 = block[i + 1];
+ ftab[(c1 << 8) + c2]++;
+ c1 = c2;
+ }
+
+ for (i = 1; i <= 65536; i++) {
+ ftab[i] += ftab[i - 1];
+ }
+
+ c1 = block[1];
+ for (i = 0; i < last; i++) {
+ c2 = block[i + 2];
+ j = (c1 << 8) + c2;
+ c1 = c2;
+ ftab[j]--;
+ zptr[ftab[j]] = i;
+ }
+
+ j = ((block[last + 1]) << 8) + (block[1]);
+ ftab[j]--;
+ zptr[ftab[j]] = last;
+
+ /*
+ Now ftab contains the first loc of every small bucket.
+ Calculate the running order, from smallest to largest
+ big bucket.
+ */
+
+ for (i = 0; i <= 255; i++) {
+ runningOrder[i] = i;
+ }
+
+ {
+ int vv;
+ int h = 1;
+ do {
+ h = 3 * h + 1;
+ }
+ while (h <= 256);
+ do {
+ h = h / 3;
+ for (i = h; i <= 255; i++) {
+ vv = runningOrder[i];
+ j = i;
+ while ((ftab[((runningOrder[j - h]) + 1) << 8]
+ - ftab[(runningOrder[j - h]) << 8]) >
+ (ftab[((vv) + 1) << 8] - ftab[(vv) << 8])) {
+ runningOrder[j] = runningOrder[j - h];
+ j = j - h;
+ if (j <= (h - 1)) {
+ break;
+ }
+ }
+ runningOrder[j] = vv;
+ }
+ } while (h != 1);
+ }
+
+ /*
+ The main sorting loop.
+ */
+ for (i = 0; i <= 255; i++) {
+
+ /*
+ Process big buckets, starting with the least full.
+ */
+ ss = runningOrder[i];
+
+ /*
+ Complete the big bucket [ss] by quicksorting
+ any unsorted small buckets [ss, j]. Hopefully
+ previous pointer-scanning phases have already
+ completed many of the small buckets [ss, j], so
+ we don't have to sort them at all.
+ */
+ for (j = 0; j <= 255; j++) {
+ sb = (ss << 8) + j;
+ if (!((ftab[sb] & SETMASK) == SETMASK)) {
+ int lo = ftab[sb] & CLEARMASK;
+ int hi = (ftab[sb + 1] & CLEARMASK) - 1;
+ if (hi > lo) {
+ qSort3(lo, hi, 2);
+ numQSorted += (hi - lo + 1);
+ if (workDone > workLimit && firstAttempt) {
+ return;
+ }
+ }
+ ftab[sb] |= SETMASK;
+ }
+ }
+
+ /*
+ The ss big bucket is now done. Record this fact,
+ and update the quadrant descriptors. Remember to
+ update quadrants in the overshoot area too, if
+ necessary. The "if (i < 255)" test merely skips
+ this updating for the last bucket processed, since
+ updating for the last bucket is pointless.
+ */
+ bigDone[ss] = true;
+
+ if (i < 255) {
+ int bbStart = ftab[ss << 8] & CLEARMASK;
+ int bbSize = (ftab[(ss + 1) << 8] & CLEARMASK) - bbStart;
+ int shifts = 0;
+
+ while ((bbSize >> shifts) > 65534) {
+ shifts++;
+ }
+
+ for (j = 0; j < bbSize; j++) {
+ int a2update = zptr[bbStart + j];
+ int qVal = (j >> shifts);
+ quadrant[a2update] = qVal;
+ if (a2update < NUM_OVERSHOOT_BYTES) {
+ quadrant[a2update + last + 1] = qVal;
+ }
+ }
+
+ if (!(((bbSize - 1) >> shifts) <= 65535)) {
+ panic();
+ }
+ }
+
+ /*
+ Now scan this big bucket so as to synthesise the
+ sorted order for small buckets [t, ss] for all t != ss.
+ */
+ for (j = 0; j <= 255; j++) {
+ copy[j] = ftab[(j << 8) + ss] & CLEARMASK;
+ }
+
+ for (j = ftab[ss << 8] & CLEARMASK;
+ j < (ftab[(ss + 1) << 8] & CLEARMASK); j++) {
+ c1 = block[zptr[j]];
+ if (!bigDone[c1]) {
+ zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1;
+ copy[c1]++;
+ }
+ }
+
+ for (j = 0; j <= 255; j++) {
+ ftab[(j << 8) + ss] |= SETMASK;
+ }
+ }
+ }
+ }
+
+ private void randomiseBlock() {
+ int i;
+ int rNToGo = 0;
+ int rTPos = 0;
+ for (i = 0; i < 256; i++) {
+ inUse[i] = false;
+ }
+
+ for (i = 0; i <= last; i++) {
+ if (rNToGo == 0) {
+ rNToGo = (char) rNums[rTPos];
+ rTPos++;
+ if (rTPos == 512) {
+ rTPos = 0;
+ }
+ }
+ rNToGo--;
+ block[i + 1] ^= ((rNToGo == 1) ? 1 : 0);
+ // handle 16 bit signed numbers
+ block[i + 1] &= 0xFF;
+
+ inUse[block[i + 1]] = true;
+ }
+ }
+
+ private void doReversibleTransformation() {
+ int i;
+
+ workLimit = workFactor * last;
+ workDone = 0;
+ blockRandomised = false;
+ firstAttempt = true;
+
+ mainSort();
+
+ if (workDone > workLimit && firstAttempt) {
+ randomiseBlock();
+ workLimit = workDone = 0;
+ blockRandomised = true;
+ firstAttempt = false;
+ mainSort();
+ }
+
+ origPtr = -1;
+ for (i = 0; i <= last; i++) {
+ if (zptr[i] == 0) {
+ origPtr = i;
+ break;
+ }
+ }
+
+ if (origPtr == -1) {
+ panic();
+ }
+ }
+
+ private boolean fullGtU(int i1, int i2) {
+ int k;
+ char c1, c2;
+ int s1, s2;
+
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ i1++;
+ i2++;
+
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ i1++;
+ i2++;
+
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ i1++;
+ i2++;
+
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ i1++;
+ i2++;
+
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ i1++;
+ i2++;
+
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ i1++;
+ i2++;
+
+ k = last + 1;
+
+ do {
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ s1 = quadrant[i1];
+ s2 = quadrant[i2];
+ if (s1 != s2) {
+ return (s1 > s2);
+ }
+ i1++;
+ i2++;
+
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ s1 = quadrant[i1];
+ s2 = quadrant[i2];
+ if (s1 != s2) {
+ return (s1 > s2);
+ }
+ i1++;
+ i2++;
+
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ s1 = quadrant[i1];
+ s2 = quadrant[i2];
+ if (s1 != s2) {
+ return (s1 > s2);
+ }
+ i1++;
+ i2++;
+
+ c1 = block[i1 + 1];
+ c2 = block[i2 + 1];
+ if (c1 != c2) {
+ return (c1 > c2);
+ }
+ s1 = quadrant[i1];
+ s2 = quadrant[i2];
+ if (s1 != s2) {
+ return (s1 > s2);
+ }
+ i1++;
+ i2++;
+
+ if (i1 > last) {
+ i1 -= last;
+ i1--;
+ }
+ if (i2 > last) {
+ i2 -= last;
+ i2--;
+ }
+
+ k -= 4;
+ workDone++;
+ } while (k >= 0);
+
+ return false;
+ }
+
+ /*
+ Knuth's increments seem to work better
+ than Incerpi-Sedgewick here. Possibly
+ because the number of elems to sort is
+ usually small, typically <= 20.
+ */
+ private int[] incs = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+ 9841, 29524, 88573, 265720,
+ 797161, 2391484 };
+
+ private void allocateCompressStructures () {
+ int n = baseBlockSize * blockSize100k;
+ block = new char[(n + 1 + NUM_OVERSHOOT_BYTES)];
+ quadrant = new int[(n + NUM_OVERSHOOT_BYTES)];
+ zptr = new int[n];
+ ftab = new int[65537];
+
+ if (block == null || quadrant == null || zptr == null
+ || ftab == null) {
+ //int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n + NUM_OVERSHOOT_BYTES) + n + 65537;
+ //compressOutOfMemory ( totalDraw, n );
+ }
+
+ /*
+ The back end needs a place to store the MTF values
+ whilst it calculates the coding tables. We could
+ put them in the zptr array. However, these values
+ will fit in a short, so we overlay szptr at the
+ start of zptr, in the hope of reducing the number
+ of cache misses induced by the multiple traversals
+ of the MTF values when calculating coding tables.
+ Seems to improve compression speed by about 1%.
+ */
+ // szptr = zptr;
+
+
+ szptr = new short[2 * n];
+ }
+
+ private void generateMTFValues() {
+ char[] yy = new char[256];
+ int i, j;
+ char tmp;
+ char tmp2;
+ int zPend;
+ int wr;
+ int EOB;
+
+ makeMaps();
+ EOB = nInUse + 1;
+
+ for (i = 0; i <= EOB; i++) {
+ mtfFreq[i] = 0;
+ }
+
+ wr = 0;
+ zPend = 0;
+ for (i = 0; i < nInUse; i++) {
+ yy[i] = (char) i;
+ }
+
+
+ for (i = 0; i <= last; i++) {
+ char ll_i;
+
+ ll_i = unseqToSeq[block[zptr[i]]];
+
+ j = 0;
+ tmp = yy[j];
+ while (ll_i != tmp) {
+ j++;
+ tmp2 = tmp;
+ tmp = yy[j];
+ yy[j] = tmp2;
+ }
+ yy[0] = tmp;
+
+ if (j == 0) {
+ zPend++;
+ } else {
+ if (zPend > 0) {
+ zPend--;
+ while (true) {
+ switch (zPend % 2) {
+ case 0:
+ szptr[wr] = (short) RUNA;
+ wr++;
+ mtfFreq[RUNA]++;
+ break;
+ case 1:
+ szptr[wr] = (short) RUNB;
+ wr++;
+ mtfFreq[RUNB]++;
+ break;
+ }
+ if (zPend < 2) {
+ break;
+ }
+ zPend = (zPend - 2) / 2;
+ }
+ zPend = 0;
+ }
+ szptr[wr] = (short) (j + 1);
+ wr++;
+ mtfFreq[j + 1]++;
+ }
+ }
+
+ if (zPend > 0) {
+ zPend--;
+ while (true) {
+ switch (zPend % 2) {
+ case 0:
+ szptr[wr] = (short) RUNA;
+ wr++;
+ mtfFreq[RUNA]++;
+ break;
+ case 1:
+ szptr[wr] = (short) RUNB;
+ wr++;
+ mtfFreq[RUNB]++;
+ break;
+ }
+ if (zPend < 2) {
+ break;
+ }
+ zPend = (zPend - 2) / 2;
+ }
+ }
+
+ szptr[wr] = (short) EOB;
+ wr++;
+ mtfFreq[EOB]++;
+
+ nMTF = wr;
+ }
+}
+
+
diff --git a/bcprov/src/main/java/org/bouncycastle/apache/bzip2/CRC.java b/bcprov/src/main/java/org/bouncycastle/apache/bzip2/CRC.java
new file mode 100644
index 0000000..ce03d28
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/apache/bzip2/CRC.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+package org.bouncycastle.apache.bzip2;
+
+/**
+ * A simple class the hold and calculate the CRC for sanity checking
+ * of the data.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+class CRC {
+ public static int crc32Table[] = {
+ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+ 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+ 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+ 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
+ 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
+ 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
+ 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
+ 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
+ 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
+ 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+ 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
+ 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
+ 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+ 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
+ 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
+ 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
+ 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
+ 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
+ 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
+ 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+ 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
+ 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
+ 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+ 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
+ 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
+ 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
+ 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
+ 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
+ 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
+ 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+ 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
+ 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
+ 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+ 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
+ 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
+ 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
+ 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
+ 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
+ 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
+ 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+ 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
+ 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
+ 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+ };
+
+ public CRC() {
+ initialiseCRC();
+ }
+
+ void initialiseCRC() {
+ globalCrc = 0xffffffff;
+ }
+
+ int getFinalCRC() {
+ return ~globalCrc;
+ }
+
+ int getGlobalCRC() {
+ return globalCrc;
+ }
+
+ void setGlobalCRC(int newCrc) {
+ globalCrc = newCrc;
+ }
+
+ void updateCRC(int inCh) {
+ int temp = (globalCrc >> 24) ^ inCh;
+ if (temp < 0) {
+ temp = 256 + temp;
+ }
+ globalCrc = (globalCrc << 8) ^ CRC.crc32Table[temp];
+ }
+
+ int globalCrc;
+}
+
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java
index 7281a6a..98ab0d6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERTags.java
@@ -11,9 +11,9 @@ public interface BERTags
public static final int EXTERNAL = 0x08;
public static final int ENUMERATED = 0x0a;
public static final int SEQUENCE = 0x10;
- public static final int SEQUENCE_OF = 0x10; // for completeness
+ 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_OF = 0x11; // for completeness
+ 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;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java
index 063e525..8b8d226 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBoolean.java
@@ -160,7 +160,7 @@ public class DERBoolean
{
if (value.length != 1)
{
- throw new IllegalArgumentException("byte value should have 1 byte in it");
+ throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it");
}
if (value[0] == 0)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java b/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
index 2f299ee..9b1ef55 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DEREnumerated.java
@@ -5,6 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.util.Arrays;
+/**
+ * Use ASN1Enumerated instead of this.
+ */
public class DEREnumerated
extends ASN1Primitive
{
@@ -52,7 +55,7 @@ public class DEREnumerated
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
*/
- public static DEREnumerated getInstance(
+ public static ASN1Enumerated getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
@@ -68,18 +71,27 @@ public class DEREnumerated
}
}
+ /**
+ * @deprecated use ASN1Enumerated
+ */
public DEREnumerated(
int value)
{
bytes = BigInteger.valueOf(value).toByteArray();
}
+ /**
+ * @deprecated use ASN1Enumerated
+ */
public DEREnumerated(
BigInteger value)
{
bytes = value.toByteArray();
}
+ /**
+ * @deprecated use ASN1Enumerated
+ */
public DEREnumerated(
byte[] bytes)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java
index 3804450..57cc84a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERInteger.java
@@ -5,6 +5,9 @@ import java.math.BigInteger;
import org.bouncycastle.util.Arrays;
+/**
+ * Use ASN1Integer instead of this,
+ */
public class DERInteger
extends ASN1Primitive
{
@@ -67,18 +70,27 @@ public class DERInteger
}
}
+ /**
+ * @deprecated use ASN1Integer constructor
+ */
public DERInteger(
long value)
{
bytes = BigInteger.valueOf(value).toByteArray();
}
+ /**
+ * @deprecated use ASN1Integer constructor
+ */
public DERInteger(
BigInteger value)
{
bytes = value.toByteArray();
}
+ /**
+ * @deprecated use ASN1Integer constructor
+ */
public DERInteger(
byte[] bytes)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
index e1de22a..3d4d04c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
@@ -6,6 +6,9 @@ import java.math.BigInteger;
import org.bouncycastle.util.Arrays;
+/**
+ * Use ASN1ObjectIdentifier instead of this,
+ */
public class DERObjectIdentifier
extends ASN1Primitive
{
@@ -38,7 +41,22 @@ public class DERObjectIdentifier
if (obj instanceof byte[])
{
- return ASN1ObjectIdentifier.fromOctetString((byte[])obj);
+ byte[] enc = (byte[])obj;
+ if (enc[0] == BERTags.OBJECT_IDENTIFIER)
+ {
+ try
+ {
+ return (ASN1ObjectIdentifier)fromByteArray(enc);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
+ }
+ }
+ else
+ { // TODO: this really shouldn't be supported here...
+ return ASN1ObjectIdentifier.fromOctetString((byte[])obj);
+ }
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
@@ -148,6 +166,9 @@ public class DERObjectIdentifier
this.body = Arrays.clone(bytes);
}
+ /**
+ * @deprecated use ASN1ObjectIdentifier constructor.
+ */
public DERObjectIdentifier(
String identifier)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java
index bb8ec4e..b5cc59a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLSequence.java
@@ -3,20 +3,23 @@ package org.bouncycastle.asn1;
import java.io.IOException;
import java.util.Enumeration;
+/**
+ * The DLSequence encodes a SEQUENCE using definite length form.
+ */
public class DLSequence
extends ASN1Sequence
{
private int bodyLength = -1;
/**
- * create an empty sequence
+ * Create an empty sequence
*/
public DLSequence()
{
}
/**
- * create a sequence containing one object
+ * Create a sequence containing one object
*/
public DLSequence(
ASN1Encodable obj)
@@ -25,7 +28,7 @@ public class DLSequence
}
/**
- * create a sequence containing a vector of objects.
+ * Create a sequence containing a vector of objects.
*/
public DLSequence(
ASN1EncodableVector v)
@@ -34,7 +37,7 @@ public class DLSequence
}
/**
- * create a sequence containing an array of objects.
+ * Create a sequence containing an array of objects.
*/
public DLSequence(
ASN1Encodable[] array)
@@ -51,7 +54,7 @@ public class DLSequence
for (Enumeration e = this.getObjects(); e.hasMoreElements();)
{
- Object obj = e.nextElement();
+ Object obj = e.nextElement();
length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
}
@@ -65,12 +68,12 @@ public class DLSequence
int encodedLength()
throws IOException
{
- int length = getBodyLength();
+ int length = getBodyLength();
return 1 + StreamUtil.calculateBodyLength(length) + length;
}
- /*
+ /**
* A note on the implementation:
* <p>
* As DL requires the constructed, definite-length model to
@@ -82,17 +85,17 @@ public class DLSequence
ASN1OutputStream out)
throws IOException
{
- ASN1OutputStream dOut = out.getDLSubStream();
- int length = getBodyLength();
+ ASN1OutputStream dOut = out.getDLSubStream();
+ int length = getBodyLength();
out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
out.writeLength(length);
for (Enumeration e = this.getObjects(); e.hasMoreElements();)
{
- Object obj = e.nextElement();
+ Object obj = e.nextElement();
dOut.writeObject((ASN1Encodable)obj);
}
}
-}
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java
index 755754b..91e83fa 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLSet.java
@@ -4,7 +4,52 @@ import java.io.IOException;
import java.util.Enumeration;
/**
- * A DER encoded set object
+ * The DLSet encodes ASN.1 SET value without element ordering,
+ * and always using definite length form.
+ * <hr>
+ * <h2>X.690</h2>
+ * <h3>8: Basic encoding rules</h3>
+ * <h4>8.11 Encoding of a set value </h4>
+ * <b>8.11.1</b> The encoding of a set value shall be constructed
+ * <p/>
+ * <b>8.11.2</b> The contents octets shall consist of the complete
+ * encoding of a data value from each of the types listed in the
+ * ASN.1 definition of the set type, in an order chosen by the sender,
+ * unless the type was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * <p/>
+ * <b>8.11.3</b> The encoding of a data value may, but need not,
+ * be present for a type which was referenced with the keyword
+ * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
+ * <blockquote>
+ * NOTE &mdash; The order of data values in a set value is not significant,
+ * and places no constraints on the order during transfer
+ * </blockquote>
+ * <h3>9: Canonical encoding rules</h3>
+ * <h4>9.3 Set components</h4>
+ * The encodings of the component values of a set value shall
+ * appear in an order determined by their tags as specified
+ * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
+ * Additionally, for the purposes of determining the order in which
+ * components are encoded when one or more component is an untagged
+ * choice type, each untagged choice type is ordered as though it
+ * has a tag equal to that of the smallest tag in that choice type
+ * or any untagged choice types nested within.
+ * <h3>10: Distinguished encoding rules</h3>
+ * <h4>10.3 Set components</h4>
+ * The encodings of the component values of a set value shall appear
+ * in an order determined by their tags as specified
+ * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
+ * <blockquote>
+ * NOTE &mdash; Where a component of the set is an untagged choice type,
+ * the location of that component in the ordering will depend on
+ * the tag of the choice component being encoded.
+ * </blockquote>
+ * <h3>11: Restrictions on BER employed by both CER and DER</h3>
+ * <h4>11.5 Set and sequence components with default value </h4>
+ * The encoding of a set value or sequence value shall not include
+ * an encoding for any component value which is equal to
+ * its default value.
*/
public class DLSet
extends ASN1Set
@@ -54,7 +99,7 @@ public class DLSet
for (Enumeration e = this.getObjects(); e.hasMoreElements();)
{
- Object obj = e.nextElement();
+ Object obj = e.nextElement();
length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
}
@@ -68,12 +113,12 @@ public class DLSet
int encodedLength()
throws IOException
{
- int length = getBodyLength();
+ int length = getBodyLength();
return 1 + StreamUtil.calculateBodyLength(length) + length;
}
- /*
+ /**
* A note on the implementation:
* <p>
* As DL requires the constructed, definite-length model to
@@ -85,17 +130,17 @@ public class DLSet
ASN1OutputStream out)
throws IOException
{
- ASN1OutputStream dOut = out.getDLSubStream();
- int length = getBodyLength();
+ ASN1OutputStream dOut = out.getDLSubStream();
+ int length = getBodyLength();
out.write(BERTags.SET | BERTags.CONSTRUCTED);
out.writeLength(length);
for (Enumeration e = this.getObjects(); e.hasMoreElements();)
{
- Object obj = e.nextElement();
+ Object obj = e.nextElement();
dOut.writeObject((ASN1Encodable)obj);
}
}
-}
+} \ No newline at end of file
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 18fc66c..16a6768 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
@@ -2,50 +2,70 @@ package org.bouncycastle.asn1.bc;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle
+ * <p>
+ * 1.3.6.1.4.1.22554
+ */
public interface BCObjectIdentifiers
{
/**
* iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle
- *
+ *<p>
* 1.3.6.1.4.1.22554
*/
public static final ASN1ObjectIdentifier bc = new ASN1ObjectIdentifier("1.3.6.1.4.1.22554");
/**
* pbe(1) algorithms
+ * <p>
+ * 1.3.6.1.4.1.22554.1
*/
- public static final ASN1ObjectIdentifier bc_pbe = new ASN1ObjectIdentifier(bc.getId() + ".1");
+ public static final ASN1ObjectIdentifier bc_pbe = bc.branch("1");
/**
* SHA-1(1)
+ * <p>
+ * 1.3.6.1.4.1.22554.1.1
*/
- public static final ASN1ObjectIdentifier bc_pbe_sha1 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".1");
+ public static final ASN1ObjectIdentifier bc_pbe_sha1 = bc_pbe.branch("1");
- /**
- * SHA-2(2) . (SHA-256(1)|SHA-384(2)|SHA-512(3)|SHA-224(4))
- */
- public static final ASN1ObjectIdentifier bc_pbe_sha256 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.1");
- public static final ASN1ObjectIdentifier bc_pbe_sha384 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.2");
- public static final ASN1ObjectIdentifier bc_pbe_sha512 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.3");
- public static final ASN1ObjectIdentifier bc_pbe_sha224 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.4");
+ /** SHA-2.SHA-256; 1.3.6.1.4.1.22554.1.2.1 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256 = bc_pbe.branch("2.1");
+ /** SHA-2.SHA-384; 1.3.6.1.4.1.22554.1.2.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha384 = bc_pbe.branch("2.2");
+ /** SHA-2.SHA-512; 1.3.6.1.4.1.22554.1.2.3 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha512 = bc_pbe.branch("2.3");
+ /** SHA-2.SHA-224; 1.3.6.1.4.1.22554.1.2.4 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha224 = bc_pbe.branch("2.4");
/**
* PKCS-5(1)|PKCS-12(2)
*/
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs5 = new ASN1ObjectIdentifier(bc_pbe_sha1.getId() + ".1");
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12 = new ASN1ObjectIdentifier(bc_pbe_sha1.getId() + ".2");
+ /** SHA-1.PKCS5; 1.3.6.1.4.1.22554.1.1.1 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs5 = bc_pbe_sha1.branch("1");
+ /** SHA-1.PKCS12; 1.3.6.1.4.1.22554.1.1.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12 = bc_pbe_sha1.branch("2");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs5 = new ASN1ObjectIdentifier(bc_pbe_sha256.getId() + ".1");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12 = new ASN1ObjectIdentifier(bc_pbe_sha256.getId() + ".2");
+ /** SHA-256.PKCS12; 1.3.6.1.4.1.22554.1.2.1.1 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs5 = bc_pbe_sha256.branch("1");
+ /** SHA-256.PKCS12; 1.3.6.1.4.1.22554.1.2.1.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12 = bc_pbe_sha256.branch("2");
/**
* AES(1) . (CBC-128(2)|CBC-192(22)|CBC-256(42))
*/
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes128_cbc = new ASN1ObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.2");
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes192_cbc = new ASN1ObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.22");
- public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes256_cbc = new ASN1ObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.42");
+ /** 1.3.6.1.4.1.22554.1.1.2.1.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes128_cbc = bc_pbe_sha1_pkcs12.branch("1.2");
+ /** 1.3.6.1.4.1.22554.1.1.2.1.22 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes192_cbc = bc_pbe_sha1_pkcs12.branch("1.22");
+ /** 1.3.6.1.4.1.22554.1.1.2.1.42 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes256_cbc = bc_pbe_sha1_pkcs12.branch("1.42");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes128_cbc = new ASN1ObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.2");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = new ASN1ObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.22");
- public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = new ASN1ObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.42");
+ /** 1.3.6.1.4.1.22554.1.1.2.2.2 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes128_cbc = bc_pbe_sha256_pkcs12.branch("1.2");
+ /** 1.3.6.1.4.1.22554.1.1.2.2.22 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = bc_pbe_sha256_pkcs12.branch("1.22");
+ /** 1.3.6.1.4.1.22554.1.1.2.2.42 */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = bc_pbe_sha256_pkcs12.branch("1.42");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java
index c43afe6..51aba65 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java
@@ -6,10 +6,10 @@ public interface CMPObjectIdentifiers
{
// RFC 4210
- // id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13}
+ /** id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13} */
static final ASN1ObjectIdentifier passwordBasedMac = new ASN1ObjectIdentifier("1.2.840.113533.7.66.13");
- // id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30}
+ /** id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30} */
static final ASN1ObjectIdentifier dhBasedMac = new ASN1ObjectIdentifier("1.2.840.113533.7.66.30");
// Example InfoTypeAndValue contents include, but are not limited
@@ -52,19 +52,36 @@ public interface CMPObjectIdentifiers
// dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
// and
// id-it OBJECT IDENTIFIER ::= {id-pkix 4}
+
+ /** RFC 4120: it-id: PKIX.4 = 1.3.6.1.5.5.7.4 */
+
+ /** RFC 4120: 1.3.6.1.5.5.7.4.1 */
static final ASN1ObjectIdentifier it_caProtEncCert = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.1");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.2 */
static final ASN1ObjectIdentifier it_signKeyPairTypes = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.2");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.3 */
static final ASN1ObjectIdentifier it_encKeyPairTypes = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.3");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.4 */
static final ASN1ObjectIdentifier it_preferredSymAlg = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.4");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.5 */
static final ASN1ObjectIdentifier it_caKeyUpdateInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.5");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.6 */
static final ASN1ObjectIdentifier it_currentCRL = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.6");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.7 */
static final ASN1ObjectIdentifier it_unsupportedOIDs = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.7");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.10 */
static final ASN1ObjectIdentifier it_keyPairParamReq = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.10");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.11 */
static final ASN1ObjectIdentifier it_keyPairParamRep = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.11");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.12 */
static final ASN1ObjectIdentifier it_revPassphrase = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.12");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.13 */
static final ASN1ObjectIdentifier it_implicitConfirm = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.13");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.14 */
static final ASN1ObjectIdentifier it_confirmWaitTime = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.14");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.15 */
static final ASN1ObjectIdentifier it_origPKIMessage = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.15");
+ /** RFC 4120: 1.3.6.1.5.5.7.4.16 */
static final ASN1ObjectIdentifier it_suppLangTags = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.16");
// RFC 4211
@@ -81,26 +98,44 @@ public interface CMPObjectIdentifiers
// arc for Registration Info in CRMF
// id-regInfo OBJECT IDENTIFIER ::= { id-pkip id-regInfo(2) }
+ /** RFC 4211: it-pkip: PKIX.5 = 1.3.6.1.5.5.7.5 */
+ static final ASN1ObjectIdentifier id_pkip = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5");
+
+ /** RFC 4211: it-regCtrl: 1.3.6.1.5.5.7.5.1 */
+ static final ASN1ObjectIdentifier id_regCtrl = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1");
+ /** RFC 4211: it-regInfo: 1.3.6.1.5.5.7.5.2 */
+ static final ASN1ObjectIdentifier id_regInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.2");
+
+
+ /** 1.3.6.1.5.5.7.5.1.1 */
static final ASN1ObjectIdentifier regCtrl_regToken = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.1");
+ /** 1.3.6.1.5.5.7.5.1.2 */
static final ASN1ObjectIdentifier regCtrl_authenticator = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.2");
+ /** 1.3.6.1.5.5.7.5.1.3 */
static final ASN1ObjectIdentifier regCtrl_pkiPublicationInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.3");
+ /** 1.3.6.1.5.5.7.5.1.4 */
static final ASN1ObjectIdentifier regCtrl_pkiArchiveOptions = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.4");
+ /** 1.3.6.1.5.5.7.5.1.5 */
static final ASN1ObjectIdentifier regCtrl_oldCertID = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.5");
+ /** 1.3.6.1.5.5.7.5.1.6 */
static final ASN1ObjectIdentifier regCtrl_protocolEncrKey = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.6");
- // From RFC4210:
- // id-regCtrl-altCertTemplate OBJECT IDENTIFIER ::= {id-regCtrl 7}
+ /** From RFC4210:
+ * id-regCtrl-altCertTemplate OBJECT IDENTIFIER ::= {id-regCtrl 7}; 1.3.6.1.5.5.7.1.7 */
static final ASN1ObjectIdentifier regCtrl_altCertTemplate = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.7");
+ /** RFC 4211: it-regInfo-utf8Pairs: 1.3.6.1.5.5.7.5.2.1 */
static final ASN1ObjectIdentifier regInfo_utf8Pairs = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.2.1");
+ /** RFC 4211: it-regInfo-certReq: 1.3.6.1.5.5.7.5.2.1 */
static final ASN1ObjectIdentifier regInfo_certReq = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.2.2");
- // id-smime OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) rsadsi(113549) pkcs(1) pkcs9(9) 16 }
- //
- // id-ct OBJECT IDENTIFIER ::= { id-smime 1 } -- content types
- //
- // id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+ /**
+ * 1.2.840.113549.1.9.16.1.21
+ * <p>
+ * id-ct OBJECT IDENTIFIER ::= { id-smime 1 } -- content types
+ * <p>
+ * id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+ */
static final ASN1ObjectIdentifier ct_encKeyWithID = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.1.21");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cmp/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/cmp/package.html
deleted file mode 100644
index eb713c9..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cmp/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting PKIX-CMP as described RFC 2510.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
index b5a2f34..066cf69 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attribute.java
@@ -10,6 +10,27 @@ import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#page-14">RFC 5652</a>:
+ * Attribute is a pair of OID (as type identifier) + set of values.
+ * <p>
+ * <pre>
+ * Attribute ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue
+ * }
+ *
+ * AttributeValue ::= ANY
+ * </pre>
+ * <p>
+ * General rule on values is that same AttributeValue must not be included
+ * multiple times into the set. That is, if the value is a SET OF INTEGERs,
+ * then having same value repeated is wrong: (1, 1), but different values is OK: (1, 2).
+ * Normally the AttributeValue syntaxes are more complicated than that.
+ * <p>
+ * General rule of Attribute usage is that the {@link Attributes} containers
+ * must not have multiple Attribute:s with same attrType (OID) there.
+ */
public class Attribute
extends ASN1Object
{
@@ -17,7 +38,14 @@ public class Attribute
private ASN1Set attrValues;
/**
- * return an Attribute object from the given object.
+ * Return an Attribute object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link Attribute} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with Attribute structure inside
+ * </ul>
*
* @param o the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -81,12 +109,6 @@ public class Attribute
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Attribute ::= SEQUENCE {
- * attrType OBJECT IDENTIFIER,
- * attrValues SET OF AttributeValue
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
index f114623..02b6cc1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AttributeTable.java
@@ -11,6 +11,9 @@ import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSet;
+/**
+ * This is helper tool to construct {@link Attributes} sets.
+ */
public class AttributeTable
{
private Hashtable attributes = new Hashtable();
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 614e224..e21c8a7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Attributes.java
@@ -6,6 +6,21 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DLSet;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652">RFC 5652</a> defines
+ * 5 "SET OF Attribute" entities with 5 different names.
+ * This is common implementation for them all:
+ * <pre>
+ * SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * Attributes ::=
+ * SET SIZE(1..MAX) OF Attribute
+ * </pre>
+ */
public class Attributes
extends ASN1Object
{
@@ -21,6 +36,19 @@ public class Attributes
attributes = new DLSet(v);
}
+ /**
+ * Return an Attribute set object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link Attributes} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Set#getInstance(java.lang.Object) ASN1Set} input formats with Attributes structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static Attributes getInstance(Object obj)
{
if (obj instanceof Attributes)
@@ -47,12 +75,8 @@ public class Attributes
return rv;
}
- /**
- * <pre>
- * Attributes ::=
- * SET SIZE(1..MAX) OF Attribute -- according to RFC 5652
- * </pre>
- * @return
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java
index 5152dc9..034753f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedData.java
@@ -11,6 +11,27 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5083">RFC 5083</a>:
+ *
+ * CMS AuthEnveloped Data object.
+ * <p>
+ * ASN.1:
+ * <pre>
+ * id-ct-authEnvelopedData OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)
+ * smime(16) ct(1) 23 }
+ *
+ * AuthEnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * authEncryptedContentInfo EncryptedContentInfo,
+ * authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+ * </pre>
+ */
public class AuthEnvelopedData
extends ASN1Object
{
@@ -51,6 +72,12 @@ public class AuthEnvelopedData
this.unauthAttrs = unauthAttrs;
}
+ /**
+ * Constructs AuthEnvelopedData by parsing supplied ASN1Sequence
+ * <p>
+ * @param seq An ASN1Sequence with AuthEnvelopedData
+ * @deprecated use getInstance().
+ */
public AuthEnvelopedData(
ASN1Sequence seq)
{
@@ -98,8 +125,14 @@ public class AuthEnvelopedData
}
/**
- * return an AuthEnvelopedData object from a tagged object.
+ * Return an AuthEnvelopedData object from a tagged object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats
+ * </ul>
*
+
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
@@ -114,10 +147,17 @@ public class AuthEnvelopedData
}
/**
- * return an AuthEnvelopedData object from the given object.
+ * Return an AuthEnvelopedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link AuthEnvelopedData} object
+ * <li> {@link ASN1Sequence org.bouncycastle.asn1.ASN1Sequence} input formats with AuthEnvelopedData structure inside
+ * </ul>
*
- * @param obj the object we want converted.
- * @throws IllegalArgumentException if the object cannot be converted.
+ * @param obj The object we want converted.
+ * @throws IllegalArgumentException if the object cannot be converted, or was null.
*/
public static AuthEnvelopedData getInstance(
Object obj)
@@ -172,16 +212,6 @@ public class AuthEnvelopedData
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * AuthEnvelopedData ::= SEQUENCE {
- * version CMSVersion,
- * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
- * recipientInfos RecipientInfos,
- * authEncryptedContentInfo EncryptedContentInfo,
- * authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
- * mac MessageAuthenticationCode,
- * unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java
index 55569a7..8460c33 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java
@@ -11,7 +11,7 @@ import org.bouncycastle.asn1.ASN1TaggedObjectParser;
import org.bouncycastle.asn1.BERTags;
/**
- * Produce an object suitable for an ASN1OutputStream.
+ * Parse {@link AuthEnvelopedData} input stream.
*
* <pre>
* AuthEnvelopedData ::= SEQUENCE {
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java
index bbf98f1..c0945f3 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedData.java
@@ -14,6 +14,30 @@ import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-9.1">RFC 5652</a> section 9.1:
+ * The AuthenticatedData carries AuthAttributes and other data
+ * which define what really is being signed.
+ * <p>
+ * <pre>
+ * AuthenticatedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * macAlgorithm MessageAuthenticationCodeAlgorithm,
+ * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+ * encapContentInfo EncapsulatedContentInfo,
+ * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+ *
+ * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * MessageAuthenticationCode ::= OCTET STRING
+ * </pre>
+ */
public class AuthenticatedData
extends ASN1Object
{
@@ -57,6 +81,9 @@ public class AuthenticatedData
this.unauthAttrs = unauthAttrs;
}
+ /**
+ * @deprecated use getInstance()
+ */
public AuthenticatedData(
ASN1Sequence seq)
{
@@ -102,7 +129,7 @@ public class AuthenticatedData
}
/**
- * return an AuthenticatedData object from a tagged object.
+ * Return an AuthenticatedData object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -118,7 +145,14 @@ public class AuthenticatedData
}
/**
- * return an AuthenticatedData object from the given object.
+ * Return an AuthenticatedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link AuthenticatedData} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with AuthenticatedData structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @throws IllegalArgumentException if the object cannot be converted.
@@ -186,24 +220,6 @@ public class AuthenticatedData
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * AuthenticatedData ::= SEQUENCE {
- * version CMSVersion,
- * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
- * recipientInfos RecipientInfos,
- * macAlgorithm MessageAuthenticationCodeAlgorithm,
- * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
- * encapContentInfo EncapsulatedContentInfo,
- * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
- * mac MessageAuthenticationCode,
- * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
- *
- * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
- *
- * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
- *
- * MessageAuthenticationCode ::= OCTET STRING
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java
index fd867e2..ce9aa4f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java
@@ -13,7 +13,7 @@ import org.bouncycastle.asn1.BERTags;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
/**
- * Produce an object suitable for an ASN1OutputStream.
+ * Parse {@link AuthenticatedData} stream.
* <pre>
* AuthenticatedData ::= SEQUENCE {
* version CMSVersion,
@@ -127,9 +127,18 @@ public class AuthenticatedDataParser
return null;
}
+ /**
+ * @deprecated use getEncapsulatedContentInfo()
+ */
public ContentInfoParser getEnapsulatedContentInfo()
throws IOException
{
+ return getEncapsulatedContentInfo();
+ }
+
+ public ContentInfoParser getEncapsulatedContentInfo()
+ throws IOException
+ {
if (nextObject == null)
{
nextObject = seq.readObject();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java
new file mode 100644
index 0000000..3277bb2
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CCMParameters.java
@@ -0,0 +1,102 @@
+package org.bouncycastle.asn1.cms;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1Object;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * <a href="http://tools.ietf.org/html/rfc5084">RFC 5084</a>: CCMParameters object.
+ * <p>
+ * <pre>
+ CCMParameters ::= SEQUENCE {
+ aes-nonce OCTET STRING, -- recommended size is 12 octets
+ aes-ICVlen AES-CCM-ICVlen DEFAULT 12 }
+ * </pre>
+ */
+public class CCMParameters
+ extends ASN1Object
+{
+ private byte[] nonce;
+ private int icvLen;
+
+ /**
+ * Return an CCMParameters object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link org.bouncycastle.asn1.cms.CCMParameters} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(Object) ASN1Sequence} input formats with CCMParameters structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static CCMParameters getInstance(
+ Object obj)
+ {
+ if (obj instanceof CCMParameters)
+ {
+ return (CCMParameters)obj;
+ }
+ else if (obj != null)
+ {
+ return new CCMParameters(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CCMParameters(
+ ASN1Sequence seq)
+ {
+ this.nonce = ASN1OctetString.getInstance(seq.getObjectAt(0)).getOctets();
+
+ if (seq.size() == 2)
+ {
+ this.icvLen = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue().intValue();
+ }
+ else
+ {
+ this.icvLen = 12;
+ }
+ }
+
+ public CCMParameters(
+ byte[] nonce,
+ int icvLen)
+ {
+ this.nonce = Arrays.clone(nonce);
+ this.icvLen = icvLen;
+ }
+
+ public byte[] getNonce()
+ {
+ return Arrays.clone(nonce);
+ }
+
+ public int getIcvLen()
+ {
+ return icvLen;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new DEROctetString(nonce));
+
+ if (icvLen != 12)
+ {
+ v.add(new ASN1Integer(icvLen));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
index 5e97324..d2fc7d1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSAttributes.java
@@ -3,11 +3,28 @@ 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.
+ * <pre>
+ * contentType ::= 1.2.840.113549.1.9.3
+ * messageDigest ::= 1.2.840.113549.1.9.4
+ * signingTime ::= 1.2.840.113549.1.9.5
+ * counterSignature ::= 1.2.840.113549.1.9.6
+ *
+ * contentHint ::= 1.2.840.113549.1.9.16.2.4
+ * </pre>
+ */
+
public interface CMSAttributes
{
+ /** PKCS#9: 1.2.840.113549.1.9.3 */
public static final 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;
+ /** PKCS#9: 1.2.840.113549.1.9.5 */
public static final 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;
+ /** 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;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
index 6294d97..b88bf6e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
@@ -5,24 +5,39 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
public interface CMSObjectIdentifiers
{
+ /** PKCS#7: 1.2.840.113549.1.7.1 */
static final ASN1ObjectIdentifier data = PKCSObjectIdentifiers.data;
+ /** PKCS#7: 1.2.840.113549.1.7.2 */
static final ASN1ObjectIdentifier signedData = PKCSObjectIdentifiers.signedData;
+ /** PKCS#7: 1.2.840.113549.1.7.3 */
static final ASN1ObjectIdentifier envelopedData = PKCSObjectIdentifiers.envelopedData;
+ /** PKCS#7: 1.2.840.113549.1.7.4 */
static final ASN1ObjectIdentifier signedAndEnvelopedData = PKCSObjectIdentifiers.signedAndEnvelopedData;
+ /** PKCS#7: 1.2.840.113549.1.7.5 */
static final ASN1ObjectIdentifier digestedData = PKCSObjectIdentifiers.digestedData;
+ /** PKCS#7: 1.2.840.113549.1.7.6 */
static final ASN1ObjectIdentifier encryptedData = PKCSObjectIdentifiers.encryptedData;
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.2 -- smime ct authData */
static final ASN1ObjectIdentifier authenticatedData = PKCSObjectIdentifiers.id_ct_authData;
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.9 -- smime ct compressedData */
static final ASN1ObjectIdentifier compressedData = PKCSObjectIdentifiers.id_ct_compressedData;
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.23 -- smime ct authEnvelopedData */
static final ASN1ObjectIdentifier authEnvelopedData = PKCSObjectIdentifiers.id_ct_authEnvelopedData;
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.31 -- smime ct timestampedData*/
static final ASN1ObjectIdentifier timestampedData = PKCSObjectIdentifiers.id_ct_timestampedData;
/**
* The other Revocation Info arc
+ * <p>
+ * <pre>
* id-ri OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
- * dod(6) internet(1) security(5) mechanisms(5) pkix(7) ri(16) }
+ * dod(6) internet(1) security(5) mechanisms(5) pkix(7) ri(16) }
+ * </pre>
*/
static final ASN1ObjectIdentifier id_ri = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.16");
+ /** 1.3.6.1.5.5.7.16.2 */
static final ASN1ObjectIdentifier id_ri_ocsp_response = id_ri.branch("2");
+ /** 1.3.6.1.5.5.7.16.4 */
static final ASN1ObjectIdentifier id_ri_scvp = id_ri.branch("4");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java
index e9d9f67..e546470 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedData.java
@@ -10,12 +10,13 @@ import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
/**
- * RFC 3274 - CMS Compressed Data.
+ * <a href="http://tools.ietf.org/html/rfc3274">RFC 3274</a>: CMS Compressed Data.
+ *
* <pre>
* CompressedData ::= SEQUENCE {
- * version CMSVersion,
- * compressionAlgorithm CompressionAlgorithmIdentifier,
- * encapContentInfo EncapsulatedContentInfo
+ * version CMSVersion,
+ * compressionAlgorithm CompressionAlgorithmIdentifier,
+ * encapContentInfo EncapsulatedContentInfo
* }
* </pre>
*/
@@ -41,27 +42,33 @@ public class CompressedData
this.version = (ASN1Integer)seq.getObjectAt(0);
this.compressionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
this.encapContentInfo = ContentInfo.getInstance(seq.getObjectAt(2));
-
}
/**
- * return a CompressedData object from a tagged object.
+ * Return a CompressedData object from a tagged object.
*
- * @param _ato the tagged object holding the object we want.
- * @param _explicit true if the object is meant to be explicitly
+ * @param ato the tagged object holding the object we want.
+ * @param isExplicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static CompressedData getInstance(
- ASN1TaggedObject _ato,
- boolean _explicit)
+ ASN1TaggedObject ato,
+ boolean isExplicit)
{
- return getInstance(ASN1Sequence.getInstance(_ato, _explicit));
+ return getInstance(ASN1Sequence.getInstance(ato, isExplicit));
}
/**
- * return a CompressedData object from the given object.
+ * Return a CompressedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link CompressedData} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with CompressedData structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java
index 035e19d..41895ce 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/CompressedDataParser.java
@@ -7,12 +7,13 @@ import org.bouncycastle.asn1.ASN1SequenceParser;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
/**
- * RFC 3274 - CMS Compressed Data.
+ * Parser of <a href="http://tools.ietf.org/html/rfc3274">RFC 3274</a> {@link CompressedData} object.
+ * <p>
* <pre>
* CompressedData ::= SEQUENCE {
- * version CMSVersion,
- * compressionAlgorithm CompressionAlgorithmIdentifier,
- * encapContentInfo EncapsulatedContentInfo
+ * version CMSVersion,
+ * compressionAlgorithm CompressionAlgorithmIdentifier,
+ * encapContentInfo EncapsulatedContentInfo
* }
* </pre>
*/
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java
index 345cf2c..2e8e039 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfo.java
@@ -10,6 +10,22 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.BERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-3">RFC 5652</a> ContentInfo, and
+ * <a href="http://tools.ietf.org/html/rfc5652#section-5.2">RFC 5652</a> EncapsulatedContentInfo objects.
+ *
+ * <pre>
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
+ * }
+ *
+ * EncapsulatedContentInfo ::= SEQUENCE {
+ * eContentType ContentType,
+ * eContent [0] EXPLICIT OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ */
public class ContentInfo
extends ASN1Object
implements CMSObjectIdentifiers
@@ -17,6 +33,19 @@ public class ContentInfo
private ASN1ObjectIdentifier contentType;
private ASN1Encodable content;
+ /**
+ * Return an ContentInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link ContentInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with ContentInfo structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static ContentInfo getInstance(
Object obj)
{
@@ -84,12 +113,6 @@ public class ContentInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * ContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * content
- * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java
index bbc3176..19f0ec8 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ContentInfoParser.java
@@ -8,12 +8,12 @@ import org.bouncycastle.asn1.ASN1SequenceParser;
import org.bouncycastle.asn1.ASN1TaggedObjectParser;
/**
- * Produce an object suitable for an ASN1OutputStream.
+ * <a href="http://tools.ietf.org/html/rfc5652#section-3">RFC 5652</a> {@link ContentInfo} object parser.
+ *
* <pre>
* ContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * content
- * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ * contentType ContentType,
+ * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
* </pre>
*/
public class ContentInfoParser
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java
index 32b7e40..0f3b906 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/DigestedData.java
@@ -12,13 +12,13 @@ import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
/**
- * RFC 3274 - CMS Digest Data.
+ * <a href="http://tools.ietf.org/html/rfc5652#section-7">RFC 5652</a> DigestedData object.
* <pre>
* DigestedData ::= SEQUENCE {
- * version CMSVersion,
- * digestAlgorithm DigestAlgorithmIdentifier,
- * encapContentInfo EncapsulatedContentInfo,
- * digest Digest }
+ * version CMSVersion,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * encapContentInfo EncapsulatedContentInfo,
+ * digest Digest }
* </pre>
*/
public class DigestedData
@@ -50,23 +50,30 @@ public class DigestedData
}
/**
- * return a CompressedData object from a tagged object.
+ * Return a DigestedData object from a tagged object.
*
- * @param _ato the tagged object holding the object we want.
- * @param _explicit true if the object is meant to be explicitly
+ * @param ato the tagged object holding the object we want.
+ * @param isExplicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException if the object held by the
* tagged object cannot be converted.
*/
public static DigestedData getInstance(
- ASN1TaggedObject _ato,
- boolean _explicit)
+ ASN1TaggedObject ato,
+ boolean isExplicit)
{
- return getInstance(ASN1Sequence.getInstance(_ato, _explicit));
+ return getInstance(ASN1Sequence.getInstance(ato, isExplicit));
}
/**
- * return a CompressedData object from the given object.
+ * Return a DigestedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link DigestedData} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java
index 14265e5..64d887d 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfo.java
@@ -11,6 +11,17 @@ import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.BERTaggedObject;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.1">RFC 5652</a> EncryptedContentInfo object.
+ *
+ * <pre>
+ * EncryptedContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+ * }
+ * </pre>
+ */
public class EncryptedContentInfo
extends ASN1Object
{
@@ -47,7 +58,14 @@ public class EncryptedContentInfo
}
/**
- * return an EncryptedContentInfo object from the given object.
+ * Return an EncryptedContentInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link EncryptedContentInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -84,13 +102,6 @@ public class EncryptedContentInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * EncryptedContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
- * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java
index 1e6f040..77fb0bb 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java
@@ -9,6 +9,8 @@ import org.bouncycastle.asn1.ASN1TaggedObjectParser;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
/**
+ * Parser for <a href="http://tools.ietf.org/html/rfc5652#section-6.1">RFC 5652</a> EncryptedContentInfo object.
+ * <p>
* <pre>
* EncryptedContentInfo ::= SEQUENCE {
* contentType ContentType,
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java
index 9d61b33..2c83958 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EncryptedData.java
@@ -9,6 +9,16 @@ import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.BERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-8">RFC 5652</a> EncryptedData object.
+ * <p>
+ * <pre>
+ * EncryptedData ::= SEQUENCE {
+ * version CMSVersion,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+ * </pre>
+ */
public class EncryptedData
extends ASN1Object
{
@@ -16,6 +26,19 @@ public class EncryptedData
private EncryptedContentInfo encryptedContentInfo;
private ASN1Set unprotectedAttrs;
+ /**
+ * Return an EncryptedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link EncryptedData} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats
+ * </ul>
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static EncryptedData getInstance(Object o)
{
if (o instanceof EncryptedData)
@@ -70,12 +93,6 @@ public class EncryptedData
}
/**
- * <pre>
- * EncryptedData ::= SEQUENCE {
- * version CMSVersion,
- * encryptedContentInfo EncryptedContentInfo,
- * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
- * </pre>
* @return a basic ASN.1 object representation.
*/
public ASN1Primitive toASN1Primitive()
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java
index 6d8b484..994575a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedData.java
@@ -12,6 +12,18 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.1">RFC 5652</a> EnvelopedData object.
+ * <pre>
+ * EnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+ * }
+ * </pre>
+ */
public class EnvelopedData
extends ASN1Object
{
@@ -78,7 +90,7 @@ public class EnvelopedData
}
/**
- * return an EnvelopedData object from a tagged object.
+ * Return an EnvelopedData object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -94,7 +106,14 @@ public class EnvelopedData
}
/**
- * return an EnvelopedData object from the given object.
+ * Return an EnvelopedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link EnvelopedData} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with EnvelopedData structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -142,15 +161,6 @@ public class EnvelopedData
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * EnvelopedData ::= SEQUENCE {
- * version CMSVersion,
- * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
- * recipientInfos RecipientInfos,
- * encryptedContentInfo EncryptedContentInfo,
- * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java
index 73529fd..774813a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/EnvelopedDataParser.java
@@ -10,6 +10,8 @@ import org.bouncycastle.asn1.ASN1TaggedObjectParser;
import org.bouncycastle.asn1.BERTags;
/**
+ * Parser of <a href="http://tools.ietf.org/html/rfc5652#section-6.1">RFC 5652</a> {@link EnvelopedData} object.
+ * <p>
* <pre>
* EnvelopedData ::= SEQUENCE {
* version CMSVersion,
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Evidence.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Evidence.java
index c68ec9a..4dcbfde 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Evidence.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Evidence.java
@@ -6,6 +6,18 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>:
+ * Binding Documents with Time-Stamps; Evidence object.
+ * <p>
+ * <pre>
+ * Evidence ::= CHOICE {
+ * tstEvidence [0] TimeStampTokenEvidence, -- see RFC 3161
+ * ersEvidence [1] EvidenceRecord, -- see RFC 4998
+ * otherEvidence [2] OtherEvidence
+ * }
+ * </pre>
+ */
public class Evidence
extends ASN1Object
implements ASN1Choice
@@ -25,6 +37,18 @@ public class Evidence
}
}
+ /**
+ * Return an Evidence object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> {@link Evidence} object
+ * <li> {@link org.bouncycastle.asn1.ASN1TaggedObject#getInstance(java.lang.Object) ASN1TaggedObject} input formats with Evidence data inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static Evidence getInstance(Object obj)
{
if (obj == null || obj instanceof Evidence)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java
new file mode 100644
index 0000000..0f03c87
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/GCMParameters.java
@@ -0,0 +1,102 @@
+package org.bouncycastle.asn1.cms;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1Object;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * <a href="http://tools.ietf.org/html/rfc5084">RFC 5084</a>: GCMParameters object.
+ * <p>
+ * <pre>
+ GCMParameters ::= SEQUENCE {
+ aes-nonce OCTET STRING, -- recommended size is 12 octets
+ aes-ICVlen AES-GCM-ICVlen DEFAULT 12 }
+ * </pre>
+ */
+public class GCMParameters
+ extends ASN1Object
+{
+ private byte[] nonce;
+ private int icvLen;
+
+ /**
+ * Return an GCMParameters object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link org.bouncycastle.asn1.cms.GCMParameters} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(Object) ASN1Sequence} input formats with GCMParameters structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static GCMParameters getInstance(
+ Object obj)
+ {
+ if (obj instanceof GCMParameters)
+ {
+ return (GCMParameters)obj;
+ }
+ else if (obj != null)
+ {
+ return new GCMParameters(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private GCMParameters(
+ ASN1Sequence seq)
+ {
+ this.nonce = ASN1OctetString.getInstance(seq.getObjectAt(0)).getOctets();
+
+ if (seq.size() == 2)
+ {
+ this.icvLen = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue().intValue();
+ }
+ else
+ {
+ this.icvLen = 12;
+ }
+ }
+
+ public GCMParameters(
+ byte[] nonce,
+ int icvLen)
+ {
+ this.nonce = Arrays.clone(nonce);
+ this.icvLen = icvLen;
+ }
+
+ public byte[] getNonce()
+ {
+ return Arrays.clone(nonce);
+ }
+
+ public int getIcvLen()
+ {
+ return icvLen;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new DEROctetString(nonce));
+
+ if (icvLen != 12)
+ {
+ v.add(new ASN1Integer(icvLen));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java
index ad0dbb1..d46cbfb 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java
@@ -13,12 +13,37 @@ import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.X509CertificateStructure;
import org.bouncycastle.asn1.x509.X509Name;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-10.2.4">RFC 5652</a>: IssuerAndSerialNumber object.
+ * <p>
+ * <pre>
+ * IssuerAndSerialNumber ::= SEQUENCE {
+ * issuer Name,
+ * serialNumber CertificateSerialNumber
+ * }
+ *
+ * CertificateSerialNumber ::= INTEGER -- See RFC 5280
+ * </pre>
+ */
public class IssuerAndSerialNumber
extends ASN1Object
{
private X500Name name;
private ASN1Integer serialNumber;
+ /**
+ * Return an IssuerAndSerialNumber object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link IssuerAndSerialNumber} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with IssuerAndSerialNumber structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static IssuerAndSerialNumber getInstance(
Object obj)
{
@@ -36,7 +61,6 @@ public class IssuerAndSerialNumber
/**
* @deprecated use getInstance() method.
- * @param seq
*/
public IssuerAndSerialNumber(
ASN1Sequence seq)
@@ -52,6 +76,9 @@ public class IssuerAndSerialNumber
this.serialNumber = certificate.getSerialNumber();
}
+ /**
+ * @deprecated use constructor taking Certificate
+ */
public IssuerAndSerialNumber(
X509CertificateStructure certificate)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java
index 67c68ab..0361e9f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKIdentifier.java
@@ -10,6 +10,18 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.3">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <p>
+ * <pre>
+ * KEKIdentifier ::= SEQUENCE {
+ * keyIdentifier OCTET STRING,
+ * date GeneralizedTime OPTIONAL,
+ * other OtherKeyAttribute OPTIONAL
+ * }
+ * </pre>
+ */
public class KEKIdentifier
extends ASN1Object
{
@@ -56,7 +68,7 @@ public class KEKIdentifier
}
/**
- * return a KEKIdentifier object from a tagged object.
+ * Return a KEKIdentifier object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -72,7 +84,14 @@ public class KEKIdentifier
}
/**
- * return a KEKIdentifier object from the given object.
+ * Return a KEKIdentifier object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link KEKIdentifier} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with KEKIdentifier structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -110,13 +129,6 @@ public class KEKIdentifier
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * KEKIdentifier ::= SEQUENCE {
- * keyIdentifier OCTET STRING,
- * date GeneralizedTime OPTIONAL,
- * other OtherKeyAttribute OPTIONAL
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java
index 6c67772..2d0cfa6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KEKRecipientInfo.java
@@ -10,6 +10,19 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.3">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <p>
+ * <pre>
+ * KEKRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- always set to 4
+ * kekid KEKIdentifier,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey
+ * }
+ * </pre>
+ */
public class KEKRecipientInfo
extends ASN1Object
{
@@ -39,7 +52,7 @@ public class KEKRecipientInfo
}
/**
- * return a KEKRecipientInfo object from a tagged object.
+ * Return a KEKRecipientInfo object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -55,7 +68,14 @@ public class KEKRecipientInfo
}
/**
- * return a KEKRecipientInfo object from the given object.
+ * Return a KEKRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link KEKRecipientInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with KEKRecipientInfo structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -63,17 +83,17 @@ public class KEKRecipientInfo
public static KEKRecipientInfo getInstance(
Object obj)
{
- if (obj == null || obj instanceof KEKRecipientInfo)
+ if (obj instanceof KEKRecipientInfo)
{
return (KEKRecipientInfo)obj;
}
- if(obj instanceof ASN1Sequence)
+ if (obj != null)
{
- return new KEKRecipientInfo((ASN1Sequence)obj);
+ return new KEKRecipientInfo(ASN1Sequence.getInstance(obj));
}
- throw new IllegalArgumentException("Invalid KEKRecipientInfo: " + obj.getClass().getName());
+ return null;
}
public ASN1Integer getVersion()
@@ -98,14 +118,6 @@ public class KEKRecipientInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * KEKRecipientInfo ::= SEQUENCE {
- * version CMSVersion, -- always set to 4
- * kekid KEKIdentifier,
- * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
- * encryptedKey EncryptedKey
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java
index 29f455a..6580cd4 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java
@@ -7,6 +7,16 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <p>
+ * <pre>
+ * KeyAgreeRecipientIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * rKeyId [0] IMPLICIT RecipientKeyIdentifier }
+ * </pre>
+ */
public class KeyAgreeRecipientIdentifier
extends ASN1Object
implements ASN1Choice
@@ -15,7 +25,7 @@ public class KeyAgreeRecipientIdentifier
private RecipientKeyIdentifier rKeyID;
/**
- * return an KeyAgreeRecipientIdentifier object from a tagged object.
+ * Return an KeyAgreeRecipientIdentifier object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -31,7 +41,16 @@ public class KeyAgreeRecipientIdentifier
}
/**
- * return an KeyAgreeRecipientIdentifier object from the given object.
+ * Return an KeyAgreeRecipientIdentifier object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> {@link KeyAgreeRecipientIdentifier} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with IssuerAndSerialNumber structure inside
+ * <li> {@link org.bouncycastle.asn1.ASN1TaggedObject#getInstance(java.lang.Object) ASN1TaggedObject} with tag value 0: a KeyAgreeRecipientIdentifier data structure
+ * </ul>
+ * <p>
+ * Note: no byte[] input!
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -84,12 +103,6 @@ public class KeyAgreeRecipientIdentifier
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * KeyAgreeRecipientIdentifier ::= CHOICE {
- * issuerAndSerialNumber IssuerAndSerialNumber,
- * rKeyId [0] IMPLICIT RecipientKeyIdentifier
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java
index c6e5744..224932a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java
@@ -11,6 +11,22 @@ import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <p>
+ * <pre>
+ * KeyAgreeRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- always set to 3
+ * originator [0] EXPLICIT OriginatorIdentifierOrKey,
+ * ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * recipientEncryptedKeys RecipientEncryptedKeys
+ * }
+ *
+ * UserKeyingMaterial ::= OCTET STRING
+ * </pre>
+ */
public class KeyAgreeRecipientInfo
extends ASN1Object
{
@@ -32,7 +48,10 @@ public class KeyAgreeRecipientInfo
this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
this.recipientEncryptedKeys = recipientEncryptedKeys;
}
-
+
+ /**
+ * @deprecated use getInstance()
+ */
public KeyAgreeRecipientInfo(
ASN1Sequence seq)
{
@@ -55,7 +74,7 @@ public class KeyAgreeRecipientInfo
}
/**
- * return a KeyAgreeRecipientInfo object from a tagged object.
+ * Return a KeyAgreeRecipientInfo object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -71,7 +90,14 @@ public class KeyAgreeRecipientInfo
}
/**
- * return a KeyAgreeRecipientInfo object from the given object.
+ * Return a KeyAgreeRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link KeyAgreeRecipientInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with KeyAgreeRecipientInfo structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -79,19 +105,17 @@ public class KeyAgreeRecipientInfo
public static KeyAgreeRecipientInfo getInstance(
Object obj)
{
- if (obj == null || obj instanceof KeyAgreeRecipientInfo)
+ if (obj instanceof KeyAgreeRecipientInfo)
{
return (KeyAgreeRecipientInfo)obj;
}
- if (obj instanceof ASN1Sequence)
+ if (obj != null)
{
- return new KeyAgreeRecipientInfo((ASN1Sequence)obj);
+ return new KeyAgreeRecipientInfo(ASN1Sequence.getInstance(obj));
}
- throw new IllegalArgumentException(
- "Illegal object in KeyAgreeRecipientInfo: " + obj.getClass().getName());
-
+ return null;
}
public ASN1Integer getVersion()
@@ -121,17 +145,6 @@ public class KeyAgreeRecipientInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * KeyAgreeRecipientInfo ::= SEQUENCE {
- * version CMSVersion, -- always set to 3
- * originator [0] EXPLICIT OriginatorIdentifierOrKey,
- * ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
- * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
- * recipientEncryptedKeys RecipientEncryptedKeys
- * }
- *
- * UserKeyingMaterial ::= OCTET STRING
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java
index 8b0a545..7d31111 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java
@@ -10,6 +10,18 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.1">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <pre>
+ * KeyTransRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- always set to 0 or 2
+ * rid RecipientIdentifier,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey
+ * }
+ * </pre>
+ */
public class KeyTransRecipientInfo
extends ASN1Object
{
@@ -36,7 +48,10 @@ public class KeyTransRecipientInfo
this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
this.encryptedKey = encryptedKey;
}
-
+
+ /**
+ * @deprecated use getInstance()
+ */
public KeyTransRecipientInfo(
ASN1Sequence seq)
{
@@ -47,7 +62,14 @@ public class KeyTransRecipientInfo
}
/**
- * return a KeyTransRecipientInfo object from the given object.
+ * Return a KeyTransRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link KeyTransRecipientInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with KeyTransRecipientInfo structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -55,18 +77,17 @@ public class KeyTransRecipientInfo
public static KeyTransRecipientInfo getInstance(
Object obj)
{
- if (obj == null || obj instanceof KeyTransRecipientInfo)
+ if (obj instanceof KeyTransRecipientInfo)
{
return (KeyTransRecipientInfo)obj;
}
- if(obj instanceof ASN1Sequence)
+ if(obj != null)
{
- return new KeyTransRecipientInfo((ASN1Sequence)obj);
+ return new KeyTransRecipientInfo(ASN1Sequence.getInstance(obj));
}
- throw new IllegalArgumentException(
- "Illegal object in KeyTransRecipientInfo: " + obj.getClass().getName());
+ return null;
}
public ASN1Integer getVersion()
@@ -91,14 +112,6 @@ public class KeyTransRecipientInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * KeyTransRecipientInfo ::= SEQUENCE {
- * version CMSVersion, -- always set to 0 or 2
- * rid RecipientIdentifier,
- * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
- * encryptedKey EncryptedKey
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/MetaData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/MetaData.java
index 73db22e..667187b 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/MetaData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/MetaData.java
@@ -9,6 +9,19 @@ import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERUTF8String;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>:
+ * Binding Documents with Time-Stamps; MetaData object.
+ * <p>
+ * <pre>
+ * MetaData ::= SEQUENCE {
+ * hashProtected BOOLEAN,
+ * fileName UTF8String OPTIONAL,
+ * mediaType IA5String OPTIONAL,
+ * otherMetaData Attributes OPTIONAL
+ * }
+ * </pre>
+ */
public class MetaData
extends ASN1Object
{
@@ -49,6 +62,19 @@ public class MetaData
}
}
+ /**
+ * Return a MetaData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link MetaData} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with MetaData structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static MetaData getInstance(Object obj)
{
if (obj instanceof MetaData)
@@ -63,17 +89,6 @@ public class MetaData
return null;
}
- /**
- * <pre>
- * MetaData ::= SEQUENCE {
- * hashProtected BOOLEAN,
- * fileName UTF8String OPTIONAL,
- * mediaType IA5String OPTIONAL,
- * otherMetaData Attributes OPTIONAL
- * }
- * </pre>
- * @return
- */
public ASN1Primitive toASN1Primitive()
{
ASN1EncodableVector v = new ASN1EncodableVector();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java
index c7c3ecb..2096be2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java
@@ -9,6 +9,19 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <pre>
+ * OriginatorIdentifierOrKey ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier,
+ * originatorKey [1] OriginatorPublicKey
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
public class OriginatorIdentifierOrKey
extends ASN1Object
implements ASN1Choice
@@ -52,7 +65,7 @@ public class OriginatorIdentifierOrKey
}
/**
- * return an OriginatorIdentifierOrKey object from a tagged object.
+ * Return an OriginatorIdentifierOrKey object from a tagged object.
*
* @param o the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -74,7 +87,17 @@ public class OriginatorIdentifierOrKey
}
/**
- * return an OriginatorIdentifierOrKey object from the given object.
+ * Return an OriginatorIdentifierOrKey object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link OriginatorIdentifierOrKey} object
+ * <li> {@link IssuerAndSerialNumber} object
+ * <li> {@link SubjectKeyIdentifier} object
+ * <li> {@link OriginatorPublicKey} object
+ * <li> {@link org.bouncycastle.asn1.ASN1TaggedObject#getInstance(java.lang.Object) ASN1TaggedObject} input formats with IssuerAndSerialNumber structure inside
+ * </ul>
*
* @param o the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -148,15 +171,6 @@ public class OriginatorIdentifierOrKey
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * OriginatorIdentifierOrKey ::= CHOICE {
- * issuerAndSerialNumber IssuerAndSerialNumber,
- * subjectKeyIdentifier [0] SubjectKeyIdentifier,
- * originatorKey [1] OriginatorPublicKey
- * }
- *
- * SubjectKeyIdentifier ::= OCTET STRING
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java
index d87054b..96abf7d 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorInfo.java
@@ -9,6 +9,36 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.1">RFC 5652</a>: OriginatorInfo object.
+ * <pre>
+ * RFC 3369:
+ *
+ * OriginatorInfo ::= SEQUENCE {
+ * certs [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
+ * }
+ * CertificateRevocationLists ::= SET OF CertificateList (from X.509)
+ *
+ * RFC 3582 / 5652:
+ *
+ * OriginatorInfo ::= SEQUENCE {
+ * certs [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT RevocationInfoChoices OPTIONAL
+ * }
+ * RevocationInfoChoices ::= SET OF RevocationInfoChoice
+ * RevocationInfoChoice ::= CHOICE {
+ * crl CertificateList,
+ * other [1] IMPLICIT OtherRevocationInfoFormat }
+ *
+ * OtherRevocationInfoFormat ::= SEQUENCE {
+ * otherRevInfoFormat OBJECT IDENTIFIER,
+ * otherRevInfo ANY DEFINED BY otherRevInfoFormat }
+ * </pre>
+ * <p>
+ * TODO: RevocationInfoChoices / RevocationInfoChoice.
+ * Constructor using CertificateSet, CertificationInfoChoices
+ */
public class OriginatorInfo
extends ASN1Object
{
@@ -54,7 +84,7 @@ public class OriginatorInfo
}
/**
- * return an OriginatorInfo object from a tagged object.
+ * Return an OriginatorInfo object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -70,7 +100,14 @@ public class OriginatorInfo
}
/**
- * return an OriginatorInfo object from the given object.
+ * Return an OriginatorInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link OriginatorInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OriginatorInfo structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -86,7 +123,7 @@ public class OriginatorInfo
{
return new OriginatorInfo(ASN1Sequence.getInstance(obj));
}
-
+
return null;
}
@@ -102,12 +139,6 @@ public class OriginatorInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * OriginatorInfo ::= SEQUENCE {
- * certs [0] IMPLICIT CertificateSet OPTIONAL,
- * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java
index 5d95d13..b9bc52f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OriginatorPublicKey.java
@@ -9,7 +9,17 @@ import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <p>
+ * <pre>
+ * OriginatorPublicKey ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * publicKey BIT STRING
+ * }
+ * </pre>
+ */
public class OriginatorPublicKey
extends ASN1Object
{
@@ -23,7 +33,10 @@ public class OriginatorPublicKey
this.algorithm = algorithm;
this.publicKey = new DERBitString(publicKey);
}
-
+
+ /**
+ * @deprecated use getInstance()
+ */
public OriginatorPublicKey(
ASN1Sequence seq)
{
@@ -32,7 +45,7 @@ public class OriginatorPublicKey
}
/**
- * return an OriginatorPublicKey object from a tagged object.
+ * Return an OriginatorPublicKey object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -48,7 +61,14 @@ public class OriginatorPublicKey
}
/**
- * return an OriginatorPublicKey object from the given object.
+ * Return an OriginatorPublicKey object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link OriginatorPublicKey} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OriginatorPublicKey structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -56,17 +76,17 @@ public class OriginatorPublicKey
public static OriginatorPublicKey getInstance(
Object obj)
{
- if (obj == null || obj instanceof OriginatorPublicKey)
+ if (obj instanceof OriginatorPublicKey)
{
return (OriginatorPublicKey)obj;
}
- if (obj instanceof ASN1Sequence)
+ if (obj != null)
{
- return new OriginatorPublicKey((ASN1Sequence)obj);
+ return new OriginatorPublicKey(ASN1Sequence.getInstance(obj));
}
-
- throw new IllegalArgumentException("Invalid OriginatorPublicKey: " + obj.getClass().getName());
+
+ return null;
}
public AlgorithmIdentifier getAlgorithm()
@@ -81,12 +101,6 @@ public class OriginatorPublicKey
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * OriginatorPublicKey ::= SEQUENCE {
- * algorithm AlgorithmIdentifier,
- * publicKey BIT STRING
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java
index 1336bb6..7363c81 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherKeyAttribute.java
@@ -8,6 +8,16 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequence;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-10.2.7">RFC 5652</a>: OtherKeyAttribute object.
+ * <p>
+ * <pre>
+ * OtherKeyAttribute ::= SEQUENCE {
+ * keyAttrId OBJECT IDENTIFIER,
+ * keyAttr ANY DEFINED BY keyAttrId OPTIONAL
+ * }
+ * </pre>
+ */
public class OtherKeyAttribute
extends ASN1Object
{
@@ -15,7 +25,14 @@ public class OtherKeyAttribute
private ASN1Encodable keyAttr;
/**
- * return an OtherKeyAttribute object from the given object.
+ * Return an OtherKeyAttribute object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link OtherKeyAttribute} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OtherKeyAttribute structure inside
+ * </ul>
*
* @param o the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -23,19 +40,22 @@ public class OtherKeyAttribute
public static OtherKeyAttribute getInstance(
Object o)
{
- if (o == null || o instanceof OtherKeyAttribute)
+ if (o instanceof OtherKeyAttribute)
{
return (OtherKeyAttribute)o;
}
- if (o instanceof ASN1Sequence)
+ if (o != null)
{
- return new OtherKeyAttribute((ASN1Sequence)o);
+ return new OtherKeyAttribute(ASN1Sequence.getInstance(o));
}
- throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ return null;
}
-
+
+ /**
+ * @deprecated use getInstance()
+ */
public OtherKeyAttribute(
ASN1Sequence seq)
{
@@ -63,12 +83,6 @@ public class OtherKeyAttribute
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * OtherKeyAttribute ::= SEQUENCE {
- * keyAttrId OBJECT IDENTIFIER,
- * keyAttr ANY DEFINED BY keyAttrId OPTIONAL
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java
index 692c96c..b77b150 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRecipientInfo.java
@@ -9,6 +9,15 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.5">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <pre>
+ * OtherRecipientInfo ::= SEQUENCE {
+ * oriType OBJECT IDENTIFIER,
+ * oriValue ANY DEFINED BY oriType }
+ * </pre>
+ */
public class OtherRecipientInfo
extends ASN1Object
{
@@ -25,7 +34,6 @@ public class OtherRecipientInfo
/**
* @deprecated use getInstance().
- * @param seq
*/
public OtherRecipientInfo(
ASN1Sequence seq)
@@ -35,7 +43,7 @@ public class OtherRecipientInfo
}
/**
- * return a OtherRecipientInfo object from a tagged object.
+ * Return a OtherRecipientInfo object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -51,7 +59,14 @@ public class OtherRecipientInfo
}
/**
- * return a OtherRecipientInfo object from the given object.
+ * Return a OtherRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link PasswordRecipientInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OtherRecipientInfo structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -84,11 +99,6 @@ public class OtherRecipientInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * OtherRecipientInfo ::= SEQUENCE {
- * oriType OBJECT IDENTIFIER,
- * oriValue ANY DEFINED BY oriType }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java
index ae6518a..a8348ff 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/OtherRevocationInfoFormat.java
@@ -9,6 +9,15 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-10.2.1">RFC 5652</a>: OtherRevocationInfoFormat object.
+ * <p>
+ * <pre>
+ * OtherRevocationInfoFormat ::= SEQUENCE {
+ * otherRevInfoFormat OBJECT IDENTIFIER,
+ * otherRevInfo ANY DEFINED BY otherRevInfoFormat }
+ * </pre>
+ */
public class OtherRevocationInfoFormat
extends ASN1Object
{
@@ -31,7 +40,7 @@ public class OtherRevocationInfoFormat
}
/**
- * return a OtherRevocationInfoFormat object from a tagged object.
+ * Return a OtherRevocationInfoFormat object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -47,7 +56,14 @@ public class OtherRevocationInfoFormat
}
/**
- * return a OtherRevocationInfoFormat object from the given object.
+ * Return a OtherRevocationInfoFormat object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link OtherRevocationInfoFormat} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with OtherRevocationInfoFormat structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -80,11 +96,6 @@ public class OtherRevocationInfoFormat
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * OtherRevocationInfoFormat ::= SEQUENCE {
- * otherRevInfoFormat OBJECT IDENTIFIER,
- * otherRevInfo ANY DEFINED BY otherRevInfoFormat }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java
index f325fcd..7ed16cf 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java
@@ -11,6 +11,18 @@ import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-10.2.7">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <pre>
+ * PasswordRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- Always set to 0
+ * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier
+ * OPTIONAL,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey }
+ * </pre>
+ */
public class PasswordRecipientInfo
extends ASN1Object
{
@@ -38,7 +50,10 @@ public class PasswordRecipientInfo
this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
this.encryptedKey = encryptedKey;
}
-
+
+ /**
+ * @deprecated use getInstance() method.
+ */
public PasswordRecipientInfo(
ASN1Sequence seq)
{
@@ -57,7 +72,7 @@ public class PasswordRecipientInfo
}
/**
- * return a PasswordRecipientInfo object from a tagged object.
+ * Return a PasswordRecipientInfo object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -73,7 +88,14 @@ public class PasswordRecipientInfo
}
/**
- * return a PasswordRecipientInfo object from the given object.
+ * Return a PasswordRecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link PasswordRecipientInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with PasswordRecipientInfo structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -81,17 +103,17 @@ public class PasswordRecipientInfo
public static PasswordRecipientInfo getInstance(
Object obj)
{
- if (obj == null || obj instanceof PasswordRecipientInfo)
+ if (obj instanceof PasswordRecipientInfo)
{
return (PasswordRecipientInfo)obj;
}
- if(obj instanceof ASN1Sequence)
+ if (obj != null)
{
- return new PasswordRecipientInfo((ASN1Sequence)obj);
+ return new PasswordRecipientInfo(ASN1Sequence.getInstance(obj));
}
- throw new IllegalArgumentException("Invalid PasswordRecipientInfo: " + obj.getClass().getName());
+ return null;
}
public ASN1Integer getVersion()
@@ -116,14 +138,6 @@ public class PasswordRecipientInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * PasswordRecipientInfo ::= SEQUENCE {
- * version CMSVersion, -- Always set to 0
- * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier
- * OPTIONAL,
- * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
- * encryptedKey EncryptedKey }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java
index 2f2a173..5062c10 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java
@@ -8,7 +8,16 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
-
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <pre>
+ * RecipientEncryptedKey ::= SEQUENCE {
+ * rid KeyAgreeRecipientIdentifier,
+ * encryptedKey EncryptedKey
+ * }
+ * </pre>
+ */
public class RecipientEncryptedKey
extends ASN1Object
{
@@ -23,7 +32,7 @@ public class RecipientEncryptedKey
}
/**
- * return an RecipientEncryptedKey object from a tagged object.
+ * Return an RecipientEncryptedKey object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -39,7 +48,14 @@ public class RecipientEncryptedKey
}
/**
- * return a RecipientEncryptedKey object from the given object.
+ * Return a RecipientEncryptedKey object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link RecipientEncryptedKey} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with RecipientEncryptedKey structure inside
+ * </ul>
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -47,17 +63,17 @@ public class RecipientEncryptedKey
public static RecipientEncryptedKey getInstance(
Object obj)
{
- if (obj == null || obj instanceof RecipientEncryptedKey)
+ if (obj instanceof RecipientEncryptedKey)
{
return (RecipientEncryptedKey)obj;
}
- if (obj instanceof ASN1Sequence)
+ if (obj != null)
{
- return new RecipientEncryptedKey((ASN1Sequence)obj);
+ return new RecipientEncryptedKey(ASN1Sequence.getInstance(obj));
}
- throw new IllegalArgumentException("Invalid RecipientEncryptedKey: " + obj.getClass().getName());
+ return null;
}
public RecipientEncryptedKey(
@@ -80,12 +96,6 @@ public class RecipientEncryptedKey
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * RecipientEncryptedKey ::= SEQUENCE {
- * rid KeyAgreeRecipientIdentifier,
- * encryptedKey EncryptedKey
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java
index 8aa992d..66b154a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientIdentifier.java
@@ -8,6 +8,18 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.1">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <pre>
+ * RecipientIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
public class RecipientIdentifier
extends ASN1Object
implements ASN1Choice
@@ -33,7 +45,16 @@ public class RecipientIdentifier
}
/**
- * return a RecipientIdentifier object from the given object.
+ * Return a RecipientIdentifier object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link RecipientIdentifier} object
+ * <li> {@link IssuerAndSerialNumber} object
+ * <li> {@link org.bouncycastle.asn1.ASN1OctetString#getInstance(java.lang.Object) ASN1OctetString} input formats (OctetString, byte[]) with value of KeyIdentifier in DER form
+ * <li> {@link org.bouncycastle.asn1.ASN1Primitive ASN1Primitive} for RecipientIdentifier constructor
+ * </ul>
*
* @param o the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -82,14 +103,6 @@ public class RecipientIdentifier
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * RecipientIdentifier ::= CHOICE {
- * issuerAndSerialNumber IssuerAndSerialNumber,
- * subjectKeyIdentifier [0] SubjectKeyIdentifier
- * }
- *
- * SubjectKeyIdentifier ::= OCTET STRING
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java
index 7593a7a..39a7bb2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientInfo.java
@@ -9,6 +9,19 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <p>
+ * <pre>
+ * RecipientInfo ::= CHOICE {
+ * ktri KeyTransRecipientInfo,
+ * kari [1] KeyAgreeRecipientInfo,
+ * kekri [2] KEKRecipientInfo,
+ * pwri [3] PasswordRecipientInfo,
+ * ori [4] OtherRecipientInfo }
+ * </pre>
+ */
public class RecipientInfo
extends ASN1Object
implements ASN1Choice
@@ -51,6 +64,20 @@ public class RecipientInfo
this.info = info;
}
+ /**
+ * Return a RecipientInfo object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link RecipientInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with RecipientInfo structure inside
+ * <li> {@link org.bouncycastle.asn1.ASN1TaggedObject#getInstance(java.lang.Object) ASN1TaggedObject} input formats with RecipientInfo structure inside
+ * </ul>
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static RecipientInfo getInstance(
Object o)
{
@@ -138,14 +165,6 @@ public class RecipientInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * RecipientInfo ::= CHOICE {
- * ktri KeyTransRecipientInfo,
- * kari [1] KeyAgreeRecipientInfo,
- * kekri [2] KEKRecipientInfo,
- * pwri [3] PasswordRecipientInfo,
- * ori [4] OtherRecipientInfo }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java
index 076761b..f0eae59 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java
@@ -10,6 +10,20 @@ import org.bouncycastle.asn1.DERGeneralizedTime;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-6.2.2">RFC 5652</a>:
+ * Content encryption key delivery mechanisms.
+ * <p>
+ * <pre>
+ * RecipientKeyIdentifier ::= SEQUENCE {
+ * subjectKeyIdentifier SubjectKeyIdentifier,
+ * date GeneralizedTime OPTIONAL,
+ * other OtherKeyAttribute OPTIONAL
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
public class RecipientKeyIdentifier
extends ASN1Object
{
@@ -43,6 +57,9 @@ public class RecipientKeyIdentifier
this(subjectKeyIdentifier, null, null);
}
+ /**
+ * @deprecated use getInstance()
+ */
public RecipientKeyIdentifier(
ASN1Sequence seq)
{
@@ -73,38 +90,45 @@ public class RecipientKeyIdentifier
}
/**
- * return a RecipientKeyIdentifier object from a tagged object.
+ * Return a RecipientKeyIdentifier object from a tagged object.
*
- * @param _ato the tagged object holding the object we want.
- * @param _explicit true if the object is meant to be explicitly
+ * @param ato the tagged object holding the object we want.
+ * @param isExplicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException if the object held by the
* tagged object cannot be converted.
*/
- public static RecipientKeyIdentifier getInstance(ASN1TaggedObject _ato, boolean _explicit)
+ public static RecipientKeyIdentifier getInstance(ASN1TaggedObject ato, boolean isExplicit)
{
- return getInstance(ASN1Sequence.getInstance(_ato, _explicit));
+ return getInstance(ASN1Sequence.getInstance(ato, isExplicit));
}
/**
- * return a RecipientKeyIdentifier object from the given object.
+ * Return a RecipientKeyIdentifier object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link RecipientKeyIdentifier} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with RecipientKeyIdentifier structure inside
+ * </ul>
*
- * @param _obj the object we want converted.
+ * @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
*/
- public static RecipientKeyIdentifier getInstance(Object _obj)
+ public static RecipientKeyIdentifier getInstance(Object obj)
{
- if(_obj == null || _obj instanceof RecipientKeyIdentifier)
+ if (obj instanceof RecipientKeyIdentifier)
{
- return (RecipientKeyIdentifier)_obj;
+ return (RecipientKeyIdentifier)obj;
}
- if(_obj instanceof ASN1Sequence)
+ if(obj != null)
{
- return new RecipientKeyIdentifier((ASN1Sequence)_obj);
+ return new RecipientKeyIdentifier(ASN1Sequence.getInstance(obj));
}
- throw new IllegalArgumentException("Invalid RecipientKeyIdentifier: " + _obj.getClass().getName());
+ return null;
}
public ASN1OctetString getSubjectKeyIdentifier()
@@ -125,15 +149,6 @@ public class RecipientKeyIdentifier
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * RecipientKeyIdentifier ::= SEQUENCE {
- * subjectKeyIdentifier SubjectKeyIdentifier,
- * date GeneralizedTime OPTIONAL,
- * other OtherKeyAttribute OPTIONAL
- * }
- *
- * SubjectKeyIdentifier ::= OCTET STRING
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java
index e9b91eb..52279c3 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SCVPReqRes.java
@@ -8,12 +8,35 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5940">RFC 5940</a>:
+ * Additional Cryptographic Message Syntax (CMS) Revocation Information Choices.
+ * <p>
+ * <pre>
+ * SCVPReqRes ::= SEQUENCE {
+ * request [0] EXPLICIT ContentInfo OPTIONAL,
+ * response ContentInfo }
+ * </pre>
+ */
public class SCVPReqRes
extends ASN1Object
{
private final ContentInfo request;
private final ContentInfo response;
+ /**
+ * Return a SCVPReqRes object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link SCVPReqRes} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with SCVPReqRes structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static SCVPReqRes getInstance(
Object obj)
{
@@ -67,11 +90,6 @@ public class SCVPReqRes
}
/**
- * <pre>
- * SCVPReqRes ::= SEQUENCE {
- * request [0] EXPLICIT ContentInfo OPTIONAL,
- * response ContentInfo }
- * </pre>
* @return the ASN.1 primitive representation.
*/
public ASN1Primitive toASN1Primitive()
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java
index fd2718a..8c7fcc2 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedData.java
@@ -16,7 +16,45 @@ import org.bouncycastle.asn1.BERTaggedObject;
import org.bouncycastle.asn1.DERTaggedObject;
/**
- * a signed data object.
+ * <a href="http://tools.ietf.org/html/rfc5652#section-5.1">RFC 5652</a>:
+ * <p>
+ * A signed data object containing multitude of {@link SignerInfo}s.
+ * <pre>
+ * SignedData ::= SEQUENCE {
+ * version CMSVersion,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * encapContentInfo EncapsulatedContentInfo,
+ * certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos
+ * }
+ *
+ * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
+ *
+ * SignerInfos ::= SET OF SignerInfo
+ * </pre>
+ * <p>
+ * The version calculation uses following ruleset from RFC 3852 section 5.1:
+ * <pre>
+ * IF ((certificates is present) AND
+ * (any certificates with a type of other are present)) OR
+ * ((crls is present) AND
+ * (any crls with a type of other are present))
+ * THEN version MUST be 5
+ * ELSE
+ * IF (certificates is present) AND
+ * (any version 2 attribute certificates are present)
+ * THEN version MUST be 4
+ * ELSE
+ * IF ((certificates is present) AND
+ * (any version 1 attribute certificates are present)) OR
+ * (any SignerInfo structures are version 3) OR
+ * (encapContentInfo eContentType is other than id-data)
+ * THEN version MUST be 3
+ * ELSE version MUST be 1
+ * </pre>
+ * <p>
+ * @todo Check possible update for this to RFC 5652 level
*/
public class SignedData
extends ASN1Object
@@ -35,6 +73,19 @@ public class SignedData
private boolean certsBer;
private boolean crlsBer;
+ /**
+ * Return a SignedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link SignedData} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with SignedData structure inside
+ * </ul>
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static SignedData getInstance(
Object o)
{
@@ -68,24 +119,6 @@ public class SignedData
}
- // RFC3852, section 5.1:
- // IF ((certificates is present) AND
- // (any certificates with a type of other are present)) OR
- // ((crls is present) AND
- // (any crls with a type of other are present))
- // THEN version MUST be 5
- // ELSE
- // IF (certificates is present) AND
- // (any version 2 attribute certificates are present)
- // THEN version MUST be 4
- // ELSE
- // IF ((certificates is present) AND
- // (any version 1 attribute certificates are present)) OR
- // (any SignerInfo structures are version 3) OR
- // (encapContentInfo eContentType is other than id-data)
- // THEN version MUST be 3
- // ELSE version MUST be 1
- //
private ASN1Integer calculateVersion(
ASN1ObjectIdentifier contentOid,
ASN1Set certs,
@@ -257,16 +290,6 @@ public class SignedData
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SignedData ::= SEQUENCE {
- * version CMSVersion,
- * digestAlgorithms DigestAlgorithmIdentifiers,
- * encapContentInfo EncapsulatedContentInfo,
- * certificates [0] IMPLICIT CertificateSet OPTIONAL,
- * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
- * signerInfos SignerInfos
- * }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java
index 6e23b29..df22b8e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignedDataParser.java
@@ -11,6 +11,8 @@ import org.bouncycastle.asn1.ASN1TaggedObjectParser;
import org.bouncycastle.asn1.BERTags;
/**
+ * Parser for <a href="http://tools.ietf.org/html/rfc5652#section-5.1">RFC 5652</a>: {@link SignedData} object.
+ * <p>
* <pre>
* SignedData ::= SEQUENCE {
* version CMSVersion,
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java
index 37b6b31..2543eb1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerIdentifier.java
@@ -8,6 +8,21 @@ import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERTaggedObject;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-5.3">RFC 5652</a>:
+ * Identify who signed the containing {@link SignerInfo} object.
+ * <p>
+ * The certificates referred to by this are at containing {@link SignedData} structure.
+ * <p>
+ * <pre>
+ * SignerIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
public class SignerIdentifier
extends ASN1Object
implements ASN1Choice
@@ -33,7 +48,16 @@ public class SignerIdentifier
}
/**
- * return a SignerIdentifier object from the given object.
+ * Return a SignerIdentifier object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link SignerIdentifier} object
+ * <li> {@link IssuerAndSerialNumber} object
+ * <li> {@link org.bouncycastle.asn1.ASN1OctetString#getInstance(java.lang.Object) ASN1OctetString} input formats with SignerIdentifier structure inside
+ * <li> {@link org.bouncycastle.asn1.ASN1Primitive ASN1Primitive} for SignerIdentifier constructor.
+ * </ul>
*
* @param o the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
@@ -82,14 +106,6 @@ public class SignerIdentifier
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SignerIdentifier ::= CHOICE {
- * issuerAndSerialNumber IssuerAndSerialNumber,
- * subjectKeyIdentifier [0] SubjectKeyIdentifier
- * }
- *
- * SubjectKeyIdentifier ::= OCTET STRING
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java
index 8aafd67..4209045 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/SignerInfo.java
@@ -15,6 +15,63 @@ import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-5.3">RFC 5652</a>:
+ * Signature container per Signer, see {@link SignerIdentifier}.
+ * <pre>
+ * PKCS#7:
+ *
+ * SignerInfo ::= SEQUENCE {
+ * version Version,
+ * sid SignerIdentifier,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+ * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ * encryptedDigest EncryptedDigest,
+ * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+ * }
+ *
+ * EncryptedDigest ::= OCTET STRING
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * -----------------------------------------
+ *
+ * RFC 5256:
+ *
+ * SignerInfo ::= SEQUENCE {
+ * version CMSVersion,
+ * sid SignerIdentifier,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
+ * signatureAlgorithm SignatureAlgorithmIdentifier,
+ * signature SignatureValue,
+ * unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL
+ * }
+ *
+ * -- {@link SignerIdentifier} referenced certificates are at containing
+ * -- {@link SignedData} certificates element.
+ *
+ * SignerIdentifier ::= CHOICE {
+ * issuerAndSerialNumber {@link IssuerAndSerialNumber},
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier }
+ *
+ * -- See {@link Attributes} for generalized SET OF {@link Attribute}
+ *
+ * SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * {@link Attribute} ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue }
+ *
+ * AttributeValue ::= ANY
+ *
+ * SignatureValue ::= OCTET STRING
+ * </pre>
+ */
public class SignerInfo
extends ASN1Object
{
@@ -26,22 +83,44 @@ public class SignerInfo
private ASN1OctetString encryptedDigest;
private ASN1Set unauthenticatedAttributes;
+ /**
+ * Return a SignerInfo object from the given input
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link SignerInfo} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with SignerInfo structure inside
+ * </ul>
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static SignerInfo getInstance(
Object o)
throws IllegalArgumentException
{
- if (o == null || o instanceof SignerInfo)
+ if (o instanceof SignerInfo)
{
return (SignerInfo)o;
}
- else if (o instanceof ASN1Sequence)
+ else if (o != null)
{
- return new SignerInfo((ASN1Sequence)o);
+ return new SignerInfo(ASN1Sequence.getInstance(o));
}
- throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ return null;
}
+ /**
+ *
+ * @param sid
+ * @param digAlgorithm CMS knows as 'digestAlgorithm'
+ * @param authenticatedAttributes CMS knows as 'signedAttrs'
+ * @param digEncryptionAlgorithm CMS knows as 'signatureAlgorithm'
+ * @param encryptedDigest CMS knows as 'signature'
+ * @param unauthenticatedAttributes CMS knows as 'unsignedAttrs'
+ */
public SignerInfo(
SignerIdentifier sid,
AlgorithmIdentifier digAlgorithm,
@@ -67,6 +146,15 @@ public class SignerInfo
this.unauthenticatedAttributes = unauthenticatedAttributes;
}
+ /**
+ *
+ * @param sid
+ * @param digAlgorithm CMS knows as 'digestAlgorithm'
+ * @param authenticatedAttributes CMS knows as 'signedAttrs'
+ * @param digEncryptionAlgorithm CMS knows as 'signatureAlgorithm'
+ * @param encryptedDigest CMS knows as 'signature'
+ * @param unauthenticatedAttributes CMS knows as 'unsignedAttrs'
+ */
public SignerInfo(
SignerIdentifier sid,
AlgorithmIdentifier digAlgorithm,
@@ -167,23 +255,6 @@ public class SignerInfo
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * SignerInfo ::= SEQUENCE {
- * version Version,
- * SignerIdentifier sid,
- * digestAlgorithm DigestAlgorithmIdentifier,
- * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
- * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
- * encryptedDigest EncryptedDigest,
- * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
- * }
- *
- * EncryptedDigest ::= OCTET STRING
- *
- * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java
index 2087248..977fce6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/Time.java
@@ -12,6 +12,22 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERGeneralizedTime;
import org.bouncycastle.asn1.DERUTCTime;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5652#section-11.3">RFC 5652</a>:
+ * Dual-mode timestamp format producing either UTCTIme or GeneralizedTime.
+ * <p>
+ * <pre>
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * </pre>
+ * <p>
+ * This has a constructor using java.util.Date for input which generates
+ * a {@link org.bouncycastle.asn1.DERUTCTime DERUTCTime} object if the
+ * supplied datetime is in range 1950-01-01-00:00:00 UTC until 2049-12-31-23:59:60 UTC.
+ * If the datetime value is outside that range, the generated object will be
+ * {@link org.bouncycastle.asn1.DERGeneralizedTime DERGeneralizedTime}.
+ */
public class Time
extends ASN1Object
implements ASN1Choice
@@ -25,6 +41,9 @@ public class Time
return getInstance(obj.getObject());
}
+ /**
+ * @deprecated use getInstance()
+ */
public Time(
ASN1Primitive time)
{
@@ -38,7 +57,7 @@ public class Time
}
/**
- * creates a time object from a given date - if the date is between 1950
+ * Create a time object from a given date - if the year is in between 1950
* and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
* is used.
*/
@@ -63,6 +82,20 @@ public class Time
}
}
+ /**
+ * Return a Time object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link Time} object
+ * <li> {@link org.bouncycastle.asn1.DERUTCTime DERUTCTime} object
+ * <li> {@link org.bouncycastle.asn1.DERGeneralizedTime DERGeneralizedTime} object
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static Time getInstance(
Object obj)
{
@@ -82,6 +115,9 @@ public class Time
throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
}
+ /**
+ * Get the date+tine as a String in full form century format.
+ */
public String getTime()
{
if (time instanceof DERUTCTime)
@@ -94,6 +130,9 @@ public class Time
}
}
+ /**
+ * Get java.util.Date version of date+time.
+ */
public Date getDate()
{
try
@@ -115,11 +154,6 @@ public class Time
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * Time ::= CHOICE {
- * utcTime UTCTime,
- * generalTime GeneralizedTime }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java
index ee1044f..f6d8d5a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampAndCRL.java
@@ -7,6 +7,16 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.CertificateList;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>
+ * Binding Documents with Time-Stamps; TimeStampAndCRL object.
+ * <pre>
+ * TimeStampAndCRL ::= SEQUENCE {
+ * timeStamp TimeStampToken, -- according to RFC 3161
+ * crl CertificateList OPTIONAL -- according to RFC 5280
+ * }
+ * </pre>
+ */
public class TimeStampAndCRL
extends ASN1Object
{
@@ -27,6 +37,19 @@ public class TimeStampAndCRL
}
}
+ /**
+ * Return a TimeStampAndCRL object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link TimeStampAndCRL} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with TimeStampAndCRL structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static TimeStampAndCRL getInstance(Object obj)
{
if (obj instanceof TimeStampAndCRL)
@@ -57,15 +80,6 @@ public class TimeStampAndCRL
return this.crl;
}
- /**
- * <pre>
- * TimeStampAndCRL ::= SEQUENCE {
- * timeStamp TimeStampToken, -- according to RFC 3161
- * crl CertificateList OPTIONAL -- according to RFC 5280
- * }
- * </pre>
- * @return
- */
public ASN1Primitive toASN1Primitive()
{
ASN1EncodableVector v = new ASN1EncodableVector();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java
index 6adefbb..5461147 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java
@@ -9,6 +9,14 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>
+ * Binding Documents with Time-Stamps; TimeStampTokenEvidence object.
+ * <pre>
+ * TimeStampTokenEvidence ::=
+ * SEQUENCE SIZE(1..MAX) OF TimeStampAndCRL
+ * </pre>
+ */
public class TimeStampTokenEvidence
extends ASN1Object
{
@@ -43,6 +51,19 @@ public class TimeStampTokenEvidence
return getInstance(ASN1Sequence.getInstance(tagged, explicit));
}
+ /**
+ * Return a TimeStampTokenEvidence object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link TimeStampTokenEvidence} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with TimeStampTokenEvidence structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static TimeStampTokenEvidence getInstance(Object obj)
{
if (obj instanceof TimeStampTokenEvidence)
@@ -62,13 +83,6 @@ public class TimeStampTokenEvidence
return timeStampAndCRLs;
}
- /**
- * <pre>
- * TimeStampTokenEvidence ::=
- * SEQUENCE SIZE(1..MAX) OF TimeStampAndCRL
- * </pre>
- * @return
- */
public ASN1Primitive toASN1Primitive()
{
ASN1EncodableVector v = new ASN1EncodableVector();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java
index ca8b696..f19061e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedData.java
@@ -9,6 +9,20 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.DERIA5String;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>:
+ * Binding Documents with Time-Stamps; TimeStampedData object.
+ * <p>
+ * <pre>
+ * TimeStampedData ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * dataUri IA5String OPTIONAL,
+ * metaData MetaData OPTIONAL,
+ * content OCTET STRING OPTIONAL,
+ * temporalEvidence Evidence
+ * }
+ * </pre>
+ */
public class TimeStampedData
extends ASN1Object
{
@@ -47,18 +61,26 @@ public class TimeStampedData
this.temporalEvidence = Evidence.getInstance(seq.getObjectAt(index));
}
+ /**
+ * Return a TimeStampedData object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link RecipientKeyIdentifier} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with TimeStampedData structure inside
+ * </ul>
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
public static TimeStampedData getInstance(Object obj)
{
- if (obj instanceof TimeStampedData)
+ if (obj == null || obj instanceof TimeStampedData)
{
return (TimeStampedData)obj;
}
- else if (obj != null)
- {
- return new TimeStampedData(ASN1Sequence.getInstance(obj));
- }
-
- return null;
+ return new TimeStampedData(ASN1Sequence.getInstance(obj));
}
public DERIA5String getDataUri()
@@ -81,18 +103,6 @@ public class TimeStampedData
return temporalEvidence;
}
- /**
- * <pre>
- * TimeStampedData ::= SEQUENCE {
- * version INTEGER { v1(1) },
- * dataUri IA5String OPTIONAL,
- * metaData MetaData OPTIONAL,
- * content OCTET STRING OPTIONAL,
- * temporalEvidence Evidence
- * }
- * </pre>
- * @return
- */
public ASN1Primitive toASN1Primitive()
{
ASN1EncodableVector v = new ASN1EncodableVector();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java
index 0d050eb..f53e00f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/TimeStampedDataParser.java
@@ -12,6 +12,20 @@ import org.bouncycastle.asn1.ASN1SequenceParser;
import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.DERIA5String;
+/**
+ * Parser for <a href="http://tools.ietf.org/html/rfc5544">RFC 5544</a>:
+ * {@link TimeStampedData} object.
+ * <p>
+ * <pre>
+ * TimeStampedData ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * dataUri IA5String OPTIONAL,
+ * metaData MetaData OPTIONAL,
+ * content OCTET STRING OPTIONAL,
+ * temporalEvidence Evidence
+ * }
+ * </pre>
+ */
public class TimeStampedDataParser
{
private ASN1Integer version;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java
index 7beb6a4..bd7267b 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java
@@ -10,6 +10,14 @@ import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.cms.OriginatorPublicKey;
+/**
+ * <a href="http://tools.ietf.org/html/rfc5753">RFC 5753/3278</a>: MQVuserKeyingMaterial object.
+ * <pre>
+ * MQVuserKeyingMaterial ::= SEQUENCE {
+ * ephemeralPublicKey OriginatorPublicKey,
+ * addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL }
+ * </pre>
+ */
public class MQVuserKeyingMaterial
extends ASN1Object
{
@@ -42,7 +50,7 @@ public class MQVuserKeyingMaterial
}
/**
- * return an MQVuserKeyingMaterial object from a tagged object.
+ * Return an MQVuserKeyingMaterial object from a tagged object.
*
* @param obj the tagged object holding the object we want.
* @param explicit true if the object is meant to be explicitly
@@ -58,7 +66,14 @@ public class MQVuserKeyingMaterial
}
/**
- * return an MQVuserKeyingMaterial object from the given object.
+ * Return an MQVuserKeyingMaterial object from the given object.
+ * <p>
+ * Accepted inputs:
+ * <ul>
+ * <li> null &rarr; null
+ * <li> {@link MQVuserKeyingMaterial} object
+ * <li> {@link org.bouncycastle.asn1.ASN1Sequence ASN1Sequence} with MQVuserKeyingMaterial inside it.
+ * </ul>
*
* @param obj the object we want converted.
* @throws IllegalArgumentException if the object cannot be converted.
@@ -91,11 +106,6 @@ public class MQVuserKeyingMaterial
/**
* Produce an object suitable for an ASN1OutputStream.
- * <pre>
- * MQVuserKeyingMaterial ::= SEQUENCE {
- * ephemeralPublicKey OriginatorPublicKey,
- * addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL }
- * </pre>
*/
public ASN1Primitive toASN1Primitive()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cms/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/cms/package.html
deleted file mode 100644
index c165a7a..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cms/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting Cryptographic Message Syntax as described in PKCS#7 and RFC 3369 (formerly RFC 2630).
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java
index c36084d..c298a7e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java
@@ -5,17 +5,25 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
public interface CRMFObjectIdentifiers
{
+ /** 1.3.6.1.5.5.7 */
static final ASN1ObjectIdentifier id_pkix = new ASN1ObjectIdentifier("1.3.6.1.5.5.7");
// arc for Internet X.509 PKI protocols and their components
- static final ASN1ObjectIdentifier id_pkip = id_pkix.branch("5");
+ /** 1.3.6.1.5.5.7.5 */
+ static final ASN1ObjectIdentifier id_pkip = id_pkix.branch("5");
+ /** 1.3.6.1.5.5.7.1 */
static final ASN1ObjectIdentifier id_regCtrl = id_pkip.branch("1");
- static final ASN1ObjectIdentifier id_regCtrl_regToken = id_regCtrl.branch("1");
- static final ASN1ObjectIdentifier id_regCtrl_authenticator = id_regCtrl.branch("2");
+ /** 1.3.6.1.5.5.7.1.1 */
+ static final ASN1ObjectIdentifier id_regCtrl_regToken = id_regCtrl.branch("1");
+ /** 1.3.6.1.5.5.7.1.2 */
+ static final ASN1ObjectIdentifier id_regCtrl_authenticator = id_regCtrl.branch("2");
+ /** 1.3.6.1.5.5.7.1.3 */
static final ASN1ObjectIdentifier id_regCtrl_pkiPublicationInfo = id_regCtrl.branch("3");
- static final ASN1ObjectIdentifier id_regCtrl_pkiArchiveOptions = id_regCtrl.branch("4");
+ /** 1.3.6.1.5.5.7.1.4 */
+ static final ASN1ObjectIdentifier id_regCtrl_pkiArchiveOptions = id_regCtrl.branch("4");
- static final ASN1ObjectIdentifier id_ct_encKeyWithID = new ASN1ObjectIdentifier(PKCSObjectIdentifiers.id_ct + ".21");
+ /** 1.2.840.113549.1.9.16.1,21 */
+ static final ASN1ObjectIdentifier id_ct_encKeyWithID = PKCSObjectIdentifiers.id_ct.branch("21");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
index fb5ae79..c6e8e0d 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
@@ -2,47 +2,100 @@ package org.bouncycastle.asn1.cryptopro;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * <pre>
+ * GOST Algorithms OBJECT IDENTIFIERS :
+ * { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)}
+ * </pre>
+ */
public interface CryptoProObjectIdentifiers
{
- // GOST Algorithms OBJECT IDENTIFIERS :
- // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)}
- static final ASN1ObjectIdentifier GOST_id = new ASN1ObjectIdentifier("1.2.643.2.2");
+ /** Base OID: 1.2.643.2.2 */
+ static final ASN1ObjectIdentifier GOST_id = new ASN1ObjectIdentifier("1.2.643.2.2");
+ /** Gost R3411 OID: 1.2.643.2.2.9 */
static final ASN1ObjectIdentifier gostR3411 = GOST_id.branch("9");
+ /** Gost R3411 HMAC OID: 1.2.643.2.2.10 */
static final ASN1ObjectIdentifier gostR3411Hmac = GOST_id.branch("10");
- static final ASN1ObjectIdentifier gostR28147_cbc = new ASN1ObjectIdentifier(GOST_id+".21");
+ /** Gost R28147 OID: 1.2.643.2.2.21 */
+ static final ASN1ObjectIdentifier gostR28147_gcfb = GOST_id.branch("21");
+ /** Gost R28147-89-CryotoPro-A-ParamSet OID: 1.2.643.2.2.31.1 */
static final ASN1ObjectIdentifier id_Gost28147_89_CryptoPro_A_ParamSet = GOST_id.branch("31.1");
- static final ASN1ObjectIdentifier gostR3410_94 = new ASN1ObjectIdentifier(GOST_id+".20");
- static final ASN1ObjectIdentifier gostR3410_2001 = new ASN1ObjectIdentifier(GOST_id+".19");
- static final ASN1ObjectIdentifier gostR3411_94_with_gostR3410_94 = new ASN1ObjectIdentifier(GOST_id+".4");
- static final ASN1ObjectIdentifier gostR3411_94_with_gostR3410_2001 = new ASN1ObjectIdentifier(GOST_id+".3");
-
- // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) }
- static final ASN1ObjectIdentifier gostR3411_94_CryptoProParamSet = new ASN1ObjectIdentifier(GOST_id+".30.1");
-
- // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) }
- static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_A = new ASN1ObjectIdentifier(GOST_id+".32.2");
- static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_B = new ASN1ObjectIdentifier(GOST_id+".32.3");
- static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_C = new ASN1ObjectIdentifier(GOST_id+".32.4");
- static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_D = new ASN1ObjectIdentifier(GOST_id+".32.5");
-
- // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) }
- static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_XchA = new ASN1ObjectIdentifier(GOST_id+".33.1");
- static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_XchB = new ASN1ObjectIdentifier(GOST_id+".33.2");
- static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_XchC = new ASN1ObjectIdentifier(GOST_id+".33.3");
-
- //{ iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) }
- static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_A = new ASN1ObjectIdentifier(GOST_id+".35.1");
- static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_B = new ASN1ObjectIdentifier(GOST_id+".35.2");
- static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_C = new ASN1ObjectIdentifier(GOST_id+".35.3");
-
- // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) }
- static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_XchA = new ASN1ObjectIdentifier(GOST_id+".36.0");
- static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_XchB = new ASN1ObjectIdentifier(GOST_id+".36.1");
+ /** Gost R28147-89-CryotoPro-B-ParamSet OID: 1.2.643.2.2.31.2 */
+ static final ASN1ObjectIdentifier id_Gost28147_89_CryptoPro_B_ParamSet = GOST_id.branch("31.2");
+
+ /** Gost R28147-89-CryotoPro-C-ParamSet OID: 1.2.643.2.2.31.3 */
+ static final ASN1ObjectIdentifier id_Gost28147_89_CryptoPro_C_ParamSet = GOST_id.branch("31.3");
+
+ /** Gost R28147-89-CryotoPro-D-ParamSet OID: 1.2.643.2.2.31.4 */
+ static final ASN1ObjectIdentifier id_Gost28147_89_CryptoPro_D_ParamSet = GOST_id.branch("31.4");
+
+ /** Gost R3410-94 OID: 1.2.643.2.2.20 */
+ static final ASN1ObjectIdentifier gostR3410_94 = GOST_id.branch("20");
+ /** Gost R3410-2001 OID: 1.2.643.2.2.19 */
+ static final ASN1ObjectIdentifier gostR3410_2001 = GOST_id.branch("19");
+
+ /** Gost R3411-94-with-R3410-94 OID: 1.2.643.2.2.4 */
+ static final ASN1ObjectIdentifier gostR3411_94_with_gostR3410_94 = GOST_id.branch("4");
+ /** Gost R3411-94-with-R3410-2001 OID: 1.2.643.2.2.3 */
+ static final ASN1ObjectIdentifier gostR3411_94_with_gostR3410_2001 = GOST_id.branch("3");
+
+ /**
+ * { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) }
+ * <p>
+ * Gost R3411-94-CryptoProParamSet OID: 1.2.643.2.2.30.1
+ */
+ static final ASN1ObjectIdentifier gostR3411_94_CryptoProParamSet = GOST_id.branch("30.1");
+
+ /**
+ * { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) }
+ * <p>
+ * Gost R3410-94-CryptoPro-A OID: 1.2.643.2.2.32.2
+ */
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_A = GOST_id.branch("32.2");
+ /** Gost R3410-94-CryptoPro-B OID: 1.2.643.2.2.32.3 */
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_B = GOST_id.branch("32.3");
+ /** Gost R3410-94-CryptoPro-C OID: 1.2.643.2.2.32.4 */
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_C = GOST_id.branch("32.4");
+ /** Gost R3410-94-CryptoPro-D OID: 1.2.643.2.2.32.5 */
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_D = GOST_id.branch("32.5");
+
+ /**
+ * { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) }
+ * <p>
+ * Gost R3410-94-CryptoPro-XchA OID: 1.2.643.2.2.33.1
+ */
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_XchA = GOST_id.branch("33.1");
+ /** Gost R3410-94-CryptoPro-XchB OID: 1.2.643.2.2.33.2 */
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_XchB = GOST_id.branch("33.2");
+ /** Gost R3410-94-CryptoPro-XchC OID: 1.2.643.2.2.33.3 */
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_XchC = GOST_id.branch("33.3");
+
+ /**
+ * { iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) }
+ * <p>
+ * Gost R3410-2001-CryptoPro-A OID: 1.2.643.2.2.35.1
+ */
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_A = GOST_id.branch("35.1");
+ /** Gost R3410-2001-CryptoPro-B OID: 1.2.643.2.2.35.2 */
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_B = GOST_id.branch("35.2");
+ /** Gost R3410-2001-CryptoPro-C OID: 1.2.643.2.2.35.3 */
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_C = GOST_id.branch("35.3");
+
+ /**
+ * { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) }
+ * <p>
+ * Gost R3410-2001-CryptoPro-XchA OID: 1.2.643.2.2.36.0
+ */
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_XchA = GOST_id.branch("36.0");
+ /** Gost R3410-2001-CryptoPro-XchA OID: 1.2.643.2.2.36.1 */
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_XchB = GOST_id.branch("36.1");
- static final ASN1ObjectIdentifier gost_ElSgDH3410_default = new ASN1ObjectIdentifier(GOST_id+".36.0");
- static final ASN1ObjectIdentifier gost_ElSgDH3410_1 = new ASN1ObjectIdentifier(GOST_id+".36.1");
+ /** Gost R3410-ElSqDH3410-default OID: 1.2.643.2.2.36.0 */
+ static final ASN1ObjectIdentifier gost_ElSgDH3410_default = GOST_id.branch("36.0");
+ /** Gost R3410-ElSqDH3410-1 OID: 1.2.643.2.2.36.1 */
+ static final ASN1ObjectIdentifier gost_ElSgDH3410_1 = GOST_id.branch("36.1");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java
index e203505..fb1d9e9 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java
@@ -7,7 +7,6 @@ import java.util.Hashtable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
/**
@@ -23,7 +22,7 @@ public class ECGOST3410NamedCurves
{
BigInteger mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
BigInteger mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
-
+
ECCurve.Fp curve = new ECCurve.Fp(
mod_p, // p
new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
@@ -31,33 +30,33 @@ public class ECGOST3410NamedCurves
ECDomainParameters ecParams = new ECDomainParameters(
curve,
- new ECPoint.Fp(curve,
- new ECFieldElement.Fp(curve.getQ(),new BigInteger("1")), // x
- new ECFieldElement.Fp(curve.getQ(),new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612"))), // y
+ curve.createPoint(
+ new BigInteger("1"), // x
+ new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
mod_q);
-
+
params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_A, ecParams);
-
+
mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
-
+
curve = new ECCurve.Fp(
- mod_p, // p
- new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"),
- new BigInteger("166"));
+ mod_p, // p
+ new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"),
+ new BigInteger("166"));
ecParams = new ECDomainParameters(
- curve,
- new ECPoint.Fp(curve,
- new ECFieldElement.Fp(curve.getQ(),new BigInteger("1")), // x
- new ECFieldElement.Fp(curve.getQ(),new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612"))), // y
- mod_q);
+ curve,
+ curve.createPoint(
+ new BigInteger("1"), // x
+ new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
+ mod_q);
params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchA, ecParams);
-
+
mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823193"); //p
mod_q = new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703"); //q
-
+
curve = new ECCurve.Fp(
mod_p, // p
new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a
@@ -65,30 +64,30 @@ public class ECGOST3410NamedCurves
ecParams = new ECDomainParameters(
curve,
- new ECPoint.Fp(curve,
- new ECFieldElement.Fp(mod_p,new BigInteger("1")), // x
- new ECFieldElement.Fp(mod_p,new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124"))), // y
+ curve.createPoint(
+ new BigInteger("1"), // x
+ new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124")), // y
mod_q); // q
params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_B, ecParams);
-
+
mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619");
mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601");
-
+
curve = new ECCurve.Fp(
- mod_p, // p
- new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"),
- new BigInteger("32858"));
+ mod_p, // p
+ new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"),
+ new BigInteger("32858"));
ecParams = new ECDomainParameters(
- curve,
- new ECPoint.Fp(curve,
- new ECFieldElement.Fp(mod_p,new BigInteger("0")),
- new ECFieldElement.Fp(mod_p,new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247"))),
+ curve,
+ curve.createPoint(
+ new BigInteger("0"),
+ new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247")),
mod_q);
-
+
params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchB, ecParams);
-
+
mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); //p
mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601"); //q
curve = new ECCurve.Fp(
@@ -98,19 +97,19 @@ public class ECGOST3410NamedCurves
ecParams = new ECDomainParameters(
curve,
- new ECPoint.Fp(curve,
- new ECFieldElement.Fp(mod_p,new BigInteger("0")), // x
- new ECFieldElement.Fp(mod_p,new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247"))), // y
+ curve.createPoint(
+ new BigInteger("0"), // x
+ new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247")), // y
mod_q); // q
params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_C, ecParams);
-
+
objIds.put("GostR3410-2001-CryptoPro-A", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_A);
objIds.put("GostR3410-2001-CryptoPro-B", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_B);
objIds.put("GostR3410-2001-CryptoPro-C", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_C);
objIds.put("GostR3410-2001-CryptoPro-XchA", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchA);
objIds.put("GostR3410-2001-CryptoPro-XchB", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchB);
-
+
names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_A, "GostR3410-2001-CryptoPro-A");
names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_B, "GostR3410-2001-CryptoPro-B");
names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_C, "GostR3410-2001-CryptoPro-C");
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java
index a0459c1..124bca6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java
@@ -11,11 +11,14 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
+/**
+ * ASN.1 algorithm identifier parameters for GOST-28147
+ */
public class GOST28147Parameters
extends ASN1Object
{
- ASN1OctetString iv;
- ASN1ObjectIdentifier paramSet;
+ private ASN1OctetString iv;
+ private ASN1ObjectIdentifier paramSet;
public static GOST28147Parameters getInstance(
ASN1TaggedObject obj,
@@ -27,19 +30,22 @@ public class GOST28147Parameters
public static GOST28147Parameters getInstance(
Object obj)
{
- if(obj == null || obj instanceof GOST28147Parameters)
+ if (obj instanceof GOST28147Parameters)
{
return (GOST28147Parameters)obj;
}
- if(obj instanceof ASN1Sequence)
+ if (obj != null)
{
- return new GOST28147Parameters((ASN1Sequence)obj);
+ return new GOST28147Parameters(ASN1Sequence.getInstance(obj));
}
- throw new IllegalArgumentException("Invalid GOST3410Parameter: " + obj.getClass().getName());
+ return null;
}
+ /**
+ * @deprecated use the getInstance() method. This constructor will vanish!
+ */
public GOST28147Parameters(
ASN1Sequence seq)
{
@@ -69,4 +75,24 @@ public class GOST28147Parameters
return new DERSequence(v);
}
+
+ /**
+ * Return the OID representing the sBox to use.
+ *
+ * @return the sBox OID.
+ */
+ public ASN1ObjectIdentifier getEncryptionParamSet()
+ {
+ return paramSet;
+ }
+
+ /**
+ * Return the initialisation vector to use.
+ *
+ * @return the IV.
+ */
+ public byte[] getIV()
+ {
+ return iv.getOctets();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
index 0307f50..45d7814 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
@@ -57,6 +57,9 @@ public class GOST3410PublicKeyAlgParameters
this.encryptionParamSet = encryptionParamSet;
}
+ /**
+ * @deprecated use getInstance()
+ */
public GOST3410PublicKeyAlgParameters(
ASN1Sequence seq)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/package.html
deleted file mode 100644
index 2b0af9e..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/cryptopro/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes for CRYPTO-PRO related objects - such as GOST identifiers.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/dvcs/DVCSObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/dvcs/DVCSObjectIdentifiers.java
index 1a88c34..d5f6ab6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/dvcs/DVCSObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/dvcs/DVCSObjectIdentifiers.java
@@ -2,35 +2,28 @@ package org.bouncycastle.asn1.dvcs;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * OIDs for <a href="http://tools.ietf.org/html/rfc3029">RFC 3029</a>
+ * Data Validation and Certification Server Protocols
+ */
public interface DVCSObjectIdentifiers
{
+ /** Base OID id-pkix: 1.3.6.1.5.5.7 */
+ static final ASN1ObjectIdentifier id_pkix = new ASN1ObjectIdentifier("1.3.6.1.5.5.7");
+ /** Base OID id-smime: 1.2.840.113549.1.9.16 */
+ static final ASN1ObjectIdentifier id_smime = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16");
- // id-pkix OBJECT IDENTIFIER ::= {iso(1)
- // identified-organization(3) dod(6)
- // internet(1) security(5) mechanisms(5) pkix(7)}
- //
- // id-smime OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) rsadsi(113549) pkcs(1) pkcs-9(9) 16 }
- public static final ASN1ObjectIdentifier id_pkix = new ASN1ObjectIdentifier("1.3.6.1.5.5.7");
- public static final ASN1ObjectIdentifier id_smime = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16");
+ /** Authority Information Access for DVCS; id-ad-dcvs; OID: 1.3.6.1.5.5.7.48.4 */
+ static final ASN1ObjectIdentifier id_ad_dvcs = id_pkix.branch("48.4");
- // -- Authority Information Access for DVCS
- //
- // id-ad-dvcs OBJECT IDENTIFIER ::= {id-pkix id-ad(48) 4}
- public static final ASN1ObjectIdentifier id_ad_dvcs = id_pkix.branch("48.4");
+ /** Key Purpose for DVCS; id-kp-dvcs; OID: 1.3.6.1.5.5.7.3.10 */
+ static final ASN1ObjectIdentifier id_kp_dvcs = id_pkix.branch("3.10");
- // -- Key Purpose for DVCS
- //
- // id-kp-dvcs OBJECT IDENTIFIER ::= {id-pkix id-kp(3) 10}
- public static final ASN1ObjectIdentifier id_kp_dvcs = id_pkix.branch("3.10");
+ /** SMIME eContentType id-ct-DVCSRequestData; OID: 1.2.840.113549.1.9.16.1.7 */
+ static final ASN1ObjectIdentifier id_ct_DVCSRequestData = id_smime.branch("1.7");
+ /** SMIME eContentType id-ct-DVCSResponseData; OID: 1.2.840.113549.1.9.16.1.8 */
+ static final ASN1ObjectIdentifier id_ct_DVCSResponseData = id_smime.branch("1.8");
- // id-ct-DVCSRequestData OBJECT IDENTIFIER ::= { id-smime ct(1) 7 }
- // id-ct-DVCSResponseData OBJECT IDENTIFIER ::= { id-smime ct(1) 8 }
- public static final ASN1ObjectIdentifier id_ct_DVCSRequestData = id_smime.branch("1.7");
- public static final ASN1ObjectIdentifier id_ct_DVCSResponseData = id_smime.branch("1.8");
-
- // -- Data validation certificate attribute
- //
- // id-aa-dvcs-dvc OBJECT IDENTIFIER ::= { id-smime aa(2) 29 }
- public static final ASN1ObjectIdentifier id_aa_dvcs_dvc = id_smime.branch("2.29");
+ /** SMIME DataValidation certificate attribute id-aa-dvcs-dvc; OID: 1.2.840.113549.1.9.16.2,29 */
+ static final ASN1ObjectIdentifier id_aa_dvcs_dvc = id_smime.branch("2.29");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/dvcs/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/dvcs/package.html
deleted file mode 100644
index a941922..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/dvcs/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and processing Data Validation and Certification Server (DVCS) protocols as described in RFC 3029.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
index bef8620..77416dc 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
@@ -2,54 +2,109 @@ package org.bouncycastle.asn1.eac;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * German Federal Office for Information Security
+ * (Bundesamt für Sicherheit in der Informationstechnik)
+ * <a href="http://www.bsi.bund.de/">http://www.bsi.bund.de/</a>
+ * <p>
+ * <a href="https://www.bsi.bund.de/EN/Publications/TechnicalGuidelines/TR03110/BSITR03110.html">BSI TR-03110</a>
+ * Technical Guideline Advanced Security Mechanisms for Machine Readable Travel Documents
+ * <p>
+ * <a href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03110/TR-03110_v2.1_P3pdf.pdf?__blob=publicationFile">Technical Guideline TR-03110-3</a>
+ * Advanced Security Mechanisms for Machine Readable Travel Documents;
+ * Part 3: Common Specifications.
+ */
+
public interface EACObjectIdentifiers
{
- // bsi-de OBJECT IDENTIFIER ::= {
- // itu-t(0) identified-organization(4) etsi(0)
- // reserved(127) etsi-identified-organization(0) 7
- // }
+ /**
+ * <pre>
+ * bsi-de OBJECT IDENTIFIER ::= {
+ * itu-t(0) identified-organization(4) etsi(0)
+ * reserved(127) etsi-identified-organization(0) 7
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7
+ */
static final ASN1ObjectIdentifier bsi_de = new ASN1ObjectIdentifier("0.4.0.127.0.7");
- // id-PK OBJECT IDENTIFIER ::= {
- // bsi-de protocols(2) smartcard(2) 1
- // }
- static final ASN1ObjectIdentifier id_PK = bsi_de.branch("2.2.1");
+ /**
+ * <pre>
+ * id-PK OBJECT IDENTIFIER ::= {
+ * bsi-de protocols(2) smartcard(2) 1
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7.2.2.1
+ */
+ static final ASN1ObjectIdentifier id_PK = bsi_de.branch("2.2.1");
- static final ASN1ObjectIdentifier id_PK_DH = id_PK.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.1.1 */
+ static final ASN1ObjectIdentifier id_PK_DH = id_PK.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.1.2 */
static final ASN1ObjectIdentifier id_PK_ECDH = id_PK.branch("2");
- // id-CA OBJECT IDENTIFIER ::= {
- // bsi-de protocols(2) smartcard(2) 3
- // }
- static final ASN1ObjectIdentifier id_CA = bsi_de.branch("2.2.3");
- static final ASN1ObjectIdentifier id_CA_DH = id_CA.branch("1");
- static final ASN1ObjectIdentifier id_CA_DH_3DES_CBC_CBC = id_CA_DH.branch("1");
- static final ASN1ObjectIdentifier id_CA_ECDH = id_CA.branch("2");
+ /**
+ * <pre>
+ * id-CA OBJECT IDENTIFIER ::= {
+ * bsi-de protocols(2) smartcard(2) 3
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7.2.2.3
+ */
+ static final ASN1ObjectIdentifier id_CA = bsi_de.branch("2.2.3");
+ /** OID: 0.4.0.127.0.7.2.2.3.1 */
+ static final ASN1ObjectIdentifier id_CA_DH = id_CA.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.3.1.1 */
+ static final ASN1ObjectIdentifier id_CA_DH_3DES_CBC_CBC = id_CA_DH.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.3.2 */
+ static final ASN1ObjectIdentifier id_CA_ECDH = id_CA.branch("2");
+ /** OID: 0.4.0.127.0.7.2.2.3.2.1 */
static final ASN1ObjectIdentifier id_CA_ECDH_3DES_CBC_CBC = id_CA_ECDH.branch("1");
- //
- // id-TA OBJECT IDENTIFIER ::= {
- // bsi-de protocols(2) smartcard(2) 2
- // }
+ /**
+ * <pre>
+ * id-TA OBJECT IDENTIFIER ::= {
+ * bsi-de protocols(2) smartcard(2) 2
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7.2.2.2
+ */
static final ASN1ObjectIdentifier id_TA = bsi_de.branch("2.2.2");
- static final ASN1ObjectIdentifier id_TA_RSA = id_TA.branch("1");
- static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_1 = id_TA_RSA .branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.2.1 */
+ static final ASN1ObjectIdentifier id_TA_RSA = id_TA.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.1 */
+ static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_1 = id_TA_RSA.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.2 */
static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_256 = id_TA_RSA.branch("2");
- static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_1 = id_TA_RSA.branch("3");
- static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_256 = id_TA_RSA.branch("4");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.3 */
+ static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_1 = id_TA_RSA.branch("3");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.4 */
+ static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_256 = id_TA_RSA.branch("4");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.5 */
static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_512 = id_TA_RSA.branch("5");
- static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_512 = id_TA_RSA.branch("6");
- static final ASN1ObjectIdentifier id_TA_ECDSA = id_TA.branch("2");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_1 = id_TA_ECDSA.branch("1");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_224 = id_TA_ECDSA.branch("2");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_256 = id_TA_ECDSA.branch("3");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_384 = id_TA_ECDSA.branch("4");
- static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_512 = id_TA_ECDSA.branch("5");
+ /** OID: 0.4.0.127.0.7.2.2.2.1.6 */
+ static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_512 = id_TA_RSA.branch("6");
+ /** OID: 0.4.0.127.0.7.2.2.2.2 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA = id_TA.branch("2");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.1 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_1 = id_TA_ECDSA.branch("1");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.2 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_224 = id_TA_ECDSA.branch("2");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.3 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_256 = id_TA_ECDSA.branch("3");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.4 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_384 = id_TA_ECDSA.branch("4");
+ /** OID: 0.4.0.127.0.7.2.2.2.2.5 */
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_512 = id_TA_ECDSA.branch("5");
/**
+ * <pre>
* id-EAC-ePassport OBJECT IDENTIFIER ::= {
- * bsi-de applications(3) mrtd(1) roles(2) 1}
+ * bsi-de applications(3) mrtd(1) roles(2) 1
+ * }
+ * </pre>
+ * OID: 0.4.0.127.0.7.3.1.2.1
*/
static final ASN1ObjectIdentifier id_EAC_ePassport = bsi_de.branch("3.1.2.1");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/esf/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/esf/package.html
deleted file mode 100644
index de27367..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/esf/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting [ESF] RFC3126
-Electronic Signature Formats for long term electronic signatures.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ess/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/ess/package.html
deleted file mode 100644
index 21854b3..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ess/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting Enhanced Security Services for S/MIME as described RFC 2634 and RFC 5035.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java
index 084a020..a329e63 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java
@@ -2,29 +2,57 @@ package org.bouncycastle.asn1.gnu;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * GNU project OID collection<p>
+ * { iso(1) identifier-organization(3) dod(6) internet(1) private(4) } == IETF defined things
+ */
public interface GNUObjectIdentifiers
{
- public static final ASN1ObjectIdentifier GNU = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.1"); // GNU Radius
- public static final ASN1ObjectIdentifier GnuPG = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.2"); // GnuPG (Ägypten)
+ /** 1.3.6.1.4.1.11591.1 -- used by GNU Radius */
+ public static final ASN1ObjectIdentifier GNU = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.1"); // GNU Radius
+ /** 1.3.6.1.4.1.11591.2 -- used by GNU PG */
+ public static final ASN1ObjectIdentifier GnuPG = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.2"); // GnuPG (Ägypten)
+ /** 1.3.6.1.4.1.11591.2.1 -- notation */
public static final ASN1ObjectIdentifier notation = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.2.1"); // notation
+ /** 1.3.6.1.4.1.11591.2.1.1 -- pkaAddress */
public static final ASN1ObjectIdentifier pkaAddress = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.2.1.1"); // pkaAddress
+ /** 1.3.6.1.4.1.11591.3 -- GNU Radar */
public static final ASN1ObjectIdentifier GnuRadar = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.3"); // GNU Radar
+ /** 1.3.6.1.4.1.11591.12 -- digestAlgorithm */
public static final ASN1ObjectIdentifier digestAlgorithm = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.12"); // digestAlgorithm
+ /** 1.3.6.1.4.1.11591.12.2 -- TIGER/192 */
public static final ASN1ObjectIdentifier Tiger_192 = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.12.2"); // TIGER/192
+ /** 1.3.6.1.4.1.11591.13 -- encryptionAlgorithm */
public static final ASN1ObjectIdentifier encryptionAlgorithm = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13"); // encryptionAlgorithm
+ /** 1.3.6.1.4.1.11591.13.2 -- Serpent */
public static final ASN1ObjectIdentifier Serpent = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2"); // Serpent
+ /** 1.3.6.1.4.1.11591.13.2.1 -- Serpent-128-ECB */
public static final ASN1ObjectIdentifier Serpent_128_ECB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.1"); // Serpent-128-ECB
+ /** 1.3.6.1.4.1.11591.13.2.2 -- Serpent-128-CBC */
public static final ASN1ObjectIdentifier Serpent_128_CBC = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.2"); // Serpent-128-CBC
+ /** 1.3.6.1.4.1.11591.13.2.3 -- Serpent-128-OFB */
public static final ASN1ObjectIdentifier Serpent_128_OFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.3"); // Serpent-128-OFB
+ /** 1.3.6.1.4.1.11591.13.2.4 -- Serpent-128-CFB */
public static final ASN1ObjectIdentifier Serpent_128_CFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.4"); // Serpent-128-CFB
+ /** 1.3.6.1.4.1.11591.13.2.21 -- Serpent-192-ECB */
public static final ASN1ObjectIdentifier Serpent_192_ECB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.21"); // Serpent-192-ECB
+ /** 1.3.6.1.4.1.11591.13.2.22 -- Serpent-192-CCB */
public static final ASN1ObjectIdentifier Serpent_192_CBC = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.22"); // Serpent-192-CBC
+ /** 1.3.6.1.4.1.11591.13.2.23 -- Serpent-192-OFB */
public static final ASN1ObjectIdentifier Serpent_192_OFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.23"); // Serpent-192-OFB
+ /** 1.3.6.1.4.1.11591.13.2.24 -- Serpent-192-CFB */
public static final ASN1ObjectIdentifier Serpent_192_CFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.24"); // Serpent-192-CFB
+ /** 1.3.6.1.4.1.11591.13.2.41 -- Serpent-256-ECB */
public static final ASN1ObjectIdentifier Serpent_256_ECB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.41"); // Serpent-256-ECB
+ /** 1.3.6.1.4.1.11591.13.2.42 -- Serpent-256-CBC */
public static final ASN1ObjectIdentifier Serpent_256_CBC = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.42"); // Serpent-256-CBC
+ /** 1.3.6.1.4.1.11591.13.2.43 -- Serpent-256-OFB */
public static final ASN1ObjectIdentifier Serpent_256_OFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.43"); // Serpent-256-OFB
+ /** 1.3.6.1.4.1.11591.13.2.44 -- Serpent-256-CFB */
public static final ASN1ObjectIdentifier Serpent_256_CFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.44"); // Serpent-256-CFB
+
+ /** 1.3.6.1.4.1.11591.14 -- CRC algorithms */
public static final ASN1ObjectIdentifier CRC = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.14"); // CRC algorithms
+ /** 1.3.6.1.4.1.11591.14,1 -- CRC32 */
public static final ASN1ObjectIdentifier CRC32 = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.14.1"); // CRC 32
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java
index e9ab8d6..5bfdbab 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java
@@ -2,19 +2,59 @@ package org.bouncycastle.asn1.iana;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * IANA:
+ * { iso(1) identifier-organization(3) dod(6) internet(1) } == IETF defined things
+ */
public interface IANAObjectIdentifiers
{
+
+ /** { iso(1) identifier-organization(3) dod(6) internet(1) } == IETF defined things */
+ static final ASN1ObjectIdentifier internet = new ASN1ObjectIdentifier("1.3.6.1");
+ /** 1.3.6.1.1: Internet directory: X.500 */
+ static final ASN1ObjectIdentifier directory = internet.branch("1");
+ /** 1.3.6.1.2: Internet management */
+ static final ASN1ObjectIdentifier mgmt = internet.branch("2");
+ /** 1.3.6.1.3: */
+ static final ASN1ObjectIdentifier experimental = internet.branch("3");
+ /** 1.3.6.1.4: */
+ static final ASN1ObjectIdentifier _private = internet.branch("4");
+ /** 1.3.6.1.5: Security services */
+ static final ASN1ObjectIdentifier security = internet.branch("5");
+ /** 1.3.6.1.6: SNMPv2 -- never really used */
+ static final ASN1ObjectIdentifier SNMPv2 = internet.branch("6");
+ /** 1.3.6.1.7: mail -- never really used */
+ static final ASN1ObjectIdentifier mail = internet.branch("7");
+
+
// id-SHA1 OBJECT IDENTIFIER ::=
// {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1)}
//
- static final ASN1ObjectIdentifier isakmpOakley = new ASN1ObjectIdentifier("1.3.6.1.5.5.8.1");
- static final ASN1ObjectIdentifier hmacMD5 = new ASN1ObjectIdentifier(isakmpOakley + ".1");
- static final ASN1ObjectIdentifier hmacSHA1 = new ASN1ObjectIdentifier(isakmpOakley + ".2");
+ /** IANA security mechanisms; 1.3.6.1.5.5 */
+ static final ASN1ObjectIdentifier security_mechanisms = security.branch("5");
+ /** IANA security nametypes; 1.3.6.1.5.6 */
+ static final ASN1ObjectIdentifier security_nametypes = security.branch("6");
+
+ /** PKIX base OID: 1.3.6.1.5.6.6 */
+ static final ASN1ObjectIdentifier pkix = security_mechanisms.branch("6");
+
+
+ /** IPSEC base OID: 1.3.6.1.5.5.8 */
+ static final ASN1ObjectIdentifier ipsec = security_mechanisms.branch("8");
+ /** IPSEC ISAKMP-Oakley OID: 1.3.6.1.5.5.8.1 */
+ static final ASN1ObjectIdentifier isakmpOakley = ipsec.branch("1");
+
+ /** IPSEC ISAKMP-Oakley hmacMD5 OID: 1.3.6.1.5.5.8.1.1 */
+ static final ASN1ObjectIdentifier hmacMD5 = isakmpOakley.branch("1");
+ /** IPSEC ISAKMP-Oakley hmacSHA1 OID: 1.3.6.1.5.5.8.1.2 */
+ static final ASN1ObjectIdentifier hmacSHA1 = isakmpOakley.branch("2");
- static final ASN1ObjectIdentifier hmacTIGER = new ASN1ObjectIdentifier(isakmpOakley + ".3");
+ /** IPSEC ISAKMP-Oakley hmacTIGER OID: 1.3.6.1.5.5.8.1.3 */
+ static final ASN1ObjectIdentifier hmacTIGER = isakmpOakley.branch("3");
- static final ASN1ObjectIdentifier hmacRIPEMD160 = new ASN1ObjectIdentifier(isakmpOakley + ".4");
+ /** IPSEC ISAKMP-Oakley hmacRIPEMD160 OID: 1.3.6.1.5.5.8.1.4 */
+ static final ASN1ObjectIdentifier hmacRIPEMD160 = isakmpOakley.branch("4");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java
index 0b5da2b..3c271da 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java
@@ -2,32 +2,48 @@ package org.bouncycastle.asn1.icao;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ *
+ * { ISOITU(2) intorgs(23) icao(136) }
+ */
public interface ICAOObjectIdentifiers
{
//
// base id
//
+ /** 2.23.136 */
static final ASN1ObjectIdentifier id_icao = new ASN1ObjectIdentifier("2.23.136");
+ /** 2.23.136.1 */
static final ASN1ObjectIdentifier id_icao_mrtd = id_icao.branch("1");
+ /** 2.23.136.1.1 */
static final ASN1ObjectIdentifier id_icao_mrtd_security = id_icao_mrtd.branch("1");
- // LDS security object, see ICAO Doc 9303-Volume 2-Section IV-A3.2
+ /** LDS security object, see ICAO Doc 9303-Volume 2-Section IV-A3.2<p>
+ * 2.23.136.1.1.1 */
static final ASN1ObjectIdentifier id_icao_ldsSecurityObject = id_icao_mrtd_security.branch("1");
- // CSCA master list, see TR CSCA Countersigning and Master List issuance
+ /** CSCA master list, see TR CSCA Countersigning and Master List issuance<p>
+ * 2.23.136.1.1.2
+ */
static final ASN1ObjectIdentifier id_icao_cscaMasterList = id_icao_mrtd_security.branch("2");
+ /** 2.23.136.1.1.3 */
static final ASN1ObjectIdentifier id_icao_cscaMasterListSigningKey = id_icao_mrtd_security.branch("3");
- // document type list, see draft TR LDS and PKI Maintenance, par. 3.2.1
+ /** document type list, see draft TR LDS and PKI Maintenance, par. 3.2.1 <p>
+ * 2.23.136.1.1.4
+ */
static final ASN1ObjectIdentifier id_icao_documentTypeList = id_icao_mrtd_security.branch("4");
- // Active Authentication protocol, see draft TR LDS and PKI Maintenance,
- // par. 5.2.2
+ /** Active Authentication protocol, see draft TR LDS and PKI Maintenance, par. 5.2.2<p>
+ * 2.23.136.1.1.5
+ */
static final ASN1ObjectIdentifier id_icao_aaProtocolObject = id_icao_mrtd_security.branch("5");
- // CSCA name change and key reoll-over, see draft TR LDS and PKI
- // Maintenance, par. 3.2.1
+ /** CSCA name change and key reoll-over, see draft TR LDS and PKI Maintenance, par. 3.2.1<p>
+ * 2.23.136.1.1.6
+ */
static final ASN1ObjectIdentifier id_icao_extensions = id_icao_mrtd_security.branch("6");
+ /** 2.23.136.1.1.6.1 */
static final ASN1ObjectIdentifier id_icao_extensions_namechangekeyrollover = id_icao_extensions.branch("1");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/icao/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/icao/package.html
deleted file mode 100644
index f2301db..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/icao/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-ICAO ASN.1 classes for electronic passport.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
index bc2ac8d..6b75fde 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
@@ -2,11 +2,16 @@ package org.bouncycastle.asn1.isismtt;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * ISISMT -- Industrial Signature Interoperability Specification
+ */
public interface ISISMTTObjectIdentifiers
{
+ /** 1.3.36.8 */
static final ASN1ObjectIdentifier id_isismtt = new ASN1ObjectIdentifier("1.3.36.8");
+ /** 1.3.36.8.1 */
static final ASN1ObjectIdentifier id_isismtt_cp = id_isismtt.branch("1");
/**
@@ -15,29 +20,37 @@ public interface ISISMTTObjectIdentifiers
* Parliament and of the Council of 13 December 1999 on a Community
* Framework for Electronic Signatures, which additionally conforms the
* special requirements of the SigG and has been issued by an accredited CA.
+ * <p>
+ * 1.3.36.8.1.1
*/
+
static final ASN1ObjectIdentifier id_isismtt_cp_accredited = id_isismtt_cp.branch("1");
+ /** 1.3.36.8.3 */
static final ASN1ObjectIdentifier id_isismtt_at = id_isismtt.branch("3");
/**
* Certificate extensionDate of certificate generation
- *
* <pre>
- * DateOfCertGenSyntax ::= GeneralizedTime
+ * DateOfCertGenSyntax ::= GeneralizedTime
* </pre>
+ * OID: 1.3.36.8.3.1
*/
static final ASN1ObjectIdentifier id_isismtt_at_dateOfCertGen = id_isismtt_at.branch("1");
/**
* Attribute to indicate that the certificate holder may sign in the name of
* a third person. May also be used as extension in a certificate.
+ * <p>
+ * OID: 1.3.36.8.3.2
*/
static final ASN1ObjectIdentifier id_isismtt_at_procuration = id_isismtt_at.branch("2");
/**
* Attribute to indicate admissions to certain professions. May be used as
* attribute in attribute certificate or as extension in a certificate
+ * <p>
+ * OID: 1.3.36.8.3.3
*/
static final ASN1ObjectIdentifier id_isismtt_at_admission = id_isismtt_at.branch("3");
@@ -47,33 +60,37 @@ public interface ISISMTTObjectIdentifiers
* MonetaryLimit since January 1, 2004. For the sake of backward
* compatibility with certificates already in use, SigG conforming
* components MUST support MonetaryLimit (as well as QcEuLimitValue).
+ * <p>
+ * OID: 1.3.36.8.3.4
*/
static final ASN1ObjectIdentifier id_isismtt_at_monetaryLimit = id_isismtt_at.branch("4");
/**
* A declaration of majority. May be used as attribute in attribute
* certificate or as extension in a certificate
+ * <p>
+ * OID: 1.3.36.8.3.5
*/
static final ASN1ObjectIdentifier id_isismtt_at_declarationOfMajority = id_isismtt_at.branch("5");
/**
- *
* Serial number of the smart card containing the corresponding private key
- *
* <pre>
- * ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
+ * ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.6
*/
static final ASN1ObjectIdentifier id_isismtt_at_iCCSN = id_isismtt_at.branch("6");
/**
- *
* Reference for a file of a smartcard that stores the public key of this
- * certificate and that is used as �security anchor�.
- *
+ * certificate and that is used as "security anchor".
* <pre>
- * PKReferenceSyntax ::= OCTET STRING (SIZE(20))
+ * PKReferenceSyntax ::= OCTET STRING (SIZE(20))
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.7
*/
static final ASN1ObjectIdentifier id_isismtt_at_PKReference = id_isismtt_at.branch("7");
@@ -81,28 +98,28 @@ public interface ISISMTTObjectIdentifiers
* Some other restriction regarding the usage of this certificate. May be
* used as attribute in attribute certificate or as extension in a
* certificate.
- *
* <pre>
- * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.8
*
* @see org.bouncycastle.asn1.isismtt.x509.Restriction
*/
static final ASN1ObjectIdentifier id_isismtt_at_restriction = id_isismtt_at.branch("8");
/**
- *
* (Single)Request extension: Clients may include this extension in a
* (single) Request to request the responder to send the certificate in the
* response message along with the status information. Besides the LDAP
* service, this extension provides another mechanism for the distribution
* of certificates, which MAY optionally be provided by certificate
* repositories.
- *
* <pre>
- * RetrieveIfAllowed ::= BOOLEAN
- *
+ * RetrieveIfAllowed ::= BOOLEAN
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.9
*/
static final ASN1ObjectIdentifier id_isismtt_at_retrieveIfAllowed = id_isismtt_at.branch("9");
@@ -110,6 +127,8 @@ public interface ISISMTTObjectIdentifiers
* SingleOCSPResponse extension: The certificate requested by the client by
* inserting the RetrieveIfAllowed extension in the request, will be
* returned in this extension.
+ * <p>
+ * OID: 1.3.36.8.3.10
*
* @see org.bouncycastle.asn1.isismtt.ocsp.RequestedCertificate
*/
@@ -117,6 +136,8 @@ public interface ISISMTTObjectIdentifiers
/**
* Base ObjectIdentifier for naming authorities
+ * <p>
+ * OID: 1.3.36.8.3.11
*/
static final ASN1ObjectIdentifier id_isismtt_at_namingAuthorities = id_isismtt_at.branch("11");
@@ -127,13 +148,17 @@ public interface ISISMTTObjectIdentifiers
* this extension in the responses.
*
* <pre>
- * CertInDirSince ::= GeneralizedTime
+ * CertInDirSince ::= GeneralizedTime
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.12
*/
static final ASN1ObjectIdentifier id_isismtt_at_certInDirSince = id_isismtt_at.branch("12");
/**
* Hash of a certificate in OCSP.
+ * <p>
+ * OID: 1.3.36.8.3.13
*
* @see org.bouncycastle.asn1.isismtt.ocsp.CertHash
*/
@@ -141,11 +166,13 @@ public interface ISISMTTObjectIdentifiers
/**
* <pre>
- * NameAtBirth ::= DirectoryString(SIZE(1..64)
+ * NameAtBirth ::= DirectoryString(SIZE(1..64)
* </pre>
*
* Used in
* {@link org.bouncycastle.asn1.x509.SubjectDirectoryAttributes SubjectDirectoryAttributes}
+ * <p>
+ * OID: 1.3.36.8.3.14
*/
static final ASN1ObjectIdentifier id_isismtt_at_nameAtBirth = id_isismtt_at.branch("14");
@@ -155,8 +182,10 @@ public interface ISISMTTObjectIdentifiers
* extension in a certificate.
*
* <pre>
- * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
* </pre>
+ * <p>
+ * OID: 1.3.36.8.3.15
*
* @see org.bouncycastle.asn1.isismtt.x509.AdditionalInformationSyntax
*/
@@ -171,10 +200,11 @@ public interface ISISMTTObjectIdentifiers
* PKC as base certificate) contains some attribute that restricts the
* usability of the PKC too. Attribute certificates with restricting content
* MUST always be included in the signed document.
- *
* <pre>
- * LiabilityLimitationFlagSyntax ::= BOOLEAN
+ * LiabilityLimitationFlagSyntax ::= BOOLEAN
* </pre>
+ * <p>
+ * OID: 0.2.262.1.10.12.0
*/
static final ASN1ObjectIdentifier id_isismtt_at_liabilityLimitationFlag = new ASN1ObjectIdentifier("0.2.262.1.10.12.0");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java
index 73e0c58..73575f1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java
@@ -2,8 +2,30 @@ package org.bouncycastle.asn1.kisa;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * Korea Information Security Agency (KISA)
+ * ({iso(1) member-body(2) kr(410) kisa(200004)})
+ * <p>
+ * See <a href="http://tools.ietf.org/html/rfc4010">RFC 4010</a>
+ * Use of the SEED Encryption Algorithm
+ * in Cryptographic Message Syntax (CMS),
+ * and <a href="http://tools.ietf.org/html/rfc4269">RFC 4269</a>
+ * The SEED Encryption Algorithm
+ */
public interface KISAObjectIdentifiers
{
- public static final ASN1ObjectIdentifier id_seedCBC = new ASN1ObjectIdentifier("1.2.410.200004.1.4");
- public static final ASN1ObjectIdentifier id_npki_app_cmsSeed_wrap = new ASN1ObjectIdentifier("1.2.410.200004.7.1.1.1");
+ /** RFC 4010, 4269: id-seedCBC; OID 1.2.410.200004.1.4 */
+ static final ASN1ObjectIdentifier id_seedCBC = new ASN1ObjectIdentifier("1.2.410.200004.1.4");
+
+ /** RFC 4269: id-seedMAC; OID 1.2.410.200004.1.7 */
+ static final ASN1ObjectIdentifier id_seedMAC = new ASN1ObjectIdentifier("1.2.410.200004.1.7");
+
+ /** RFC 4269: pbeWithSHA1AndSEED-CBC; OID 1.2.410.200004.1.15 */
+ static final ASN1ObjectIdentifier pbeWithSHA1AndSEED_CBC = new ASN1ObjectIdentifier("1.2.410.200004.1.15");
+
+ /** RFC 4010: id-npki-app-cmsSeed-wrap; OID 1.2.410.200004.7.1.1.1 */
+ static final ASN1ObjectIdentifier id_npki_app_cmsSeed_wrap = new ASN1ObjectIdentifier("1.2.410.200004.7.1.1.1");
+
+ /** RFC 4010: SeedEncryptionAlgorithmInCMS; OID 1.2.840.113549.1.9.16.0.24 */
+ static final ASN1ObjectIdentifier id_mod_cms_seed = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.0.24");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java
index f40a943..8ba2cf5 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java
@@ -2,16 +2,27 @@ package org.bouncycastle.asn1.microsoft;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * Microsoft
+ * <p>
+ * Object identifier base:
+ * <pre>
+ * iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) microsoft(311)
+ * </pre>
+ * 1.3.6.1.4.1.311
+ */
public interface MicrosoftObjectIdentifiers
{
- //
- // Microsoft
- // iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) microsoft(311)
- //
+ /** Base OID: 1.3.6.1.4.1.311 */
static final ASN1ObjectIdentifier microsoft = new ASN1ObjectIdentifier("1.3.6.1.4.1.311");
+ /** OID: 1.3.6.1.4.1.311.20.2 */
static final ASN1ObjectIdentifier microsoftCertTemplateV1 = microsoft.branch("20.2");
+ /** OID: 1.3.6.1.4.1.311.21.1 */
static final ASN1ObjectIdentifier microsoftCaVersion = microsoft.branch("21.1");
+ /** OID: 1.3.6.1.4.1.311.21.2 */
static final ASN1ObjectIdentifier microsoftPrevCaCertHash = microsoft.branch("21.2");
+ /** OID: 1.3.6.1.4.1.311.21.7 */
static final ASN1ObjectIdentifier microsoftCertTemplateV2 = microsoft.branch("21.7");
+ /** OID: 1.3.6.1.4.1.311.21.10 */
static final ASN1ObjectIdentifier microsoftAppPolicies = microsoft.branch("21.10");
}
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 debf268..6aff988 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
@@ -8,40 +8,52 @@ 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");
//
// 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");
- //
- // CZAG - country, zip, age, and gender
- //
+ /** Verisign CZAG (Country,Zip,Age,Gender) Extension OID: 2.16.840.1.113733.1.6.3 */
static final ASN1ObjectIdentifier verisignCzagExtension = verisign.branch("6.3");
- // D&B D-U-N-S number
+ /** Verisign D&B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15 */
static final ASN1ObjectIdentifier verisignDnbDunsNumber = verisign.branch("6.15");
//
// 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");
//
// 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");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/misc/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/misc/package.html
deleted file mode 100644
index e3bda64..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/misc/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Miscellaneous object identifiers and objects.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/mozilla/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/mozilla/package.html
deleted file mode 100644
index 40776b0..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/mozilla/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding objects used by mozilla.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java
index afa93c4..e3613c6 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java
@@ -2,59 +2,95 @@ package org.bouncycastle.asn1.nist;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ *
+ * NIST:
+ * iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3)
+ */
public interface NISTObjectIdentifiers
{
//
- // NIST
- // iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3)
-
- //
// nistalgorithms(4)
//
+ /** 2.16.840.1.101.3.4 -- algorithms */
static final ASN1ObjectIdentifier nistAlgorithm = new ASN1ObjectIdentifier("2.16.840.1.101.3.4");
+ /** 2.16.840.1.101.3.4.2 */
static final ASN1ObjectIdentifier hashAlgs = nistAlgorithm.branch("2");
+ /** 2.16.840.1.101.3.4.2.1 */
static final ASN1ObjectIdentifier id_sha256 = hashAlgs.branch("1");
+ /** 2.16.840.1.101.3.4.2.2 */
static final ASN1ObjectIdentifier id_sha384 = hashAlgs.branch("2");
+ /** 2.16.840.1.101.3.4.2.3 */
static final ASN1ObjectIdentifier id_sha512 = hashAlgs.branch("3");
+ /** 2.16.840.1.101.3.4.2.4 */
static final ASN1ObjectIdentifier id_sha224 = hashAlgs.branch("4");
+ /** 2.16.840.1.101.3.4.2.5 */
static final ASN1ObjectIdentifier id_sha512_224 = hashAlgs.branch("5");
+ /** 2.16.840.1.101.3.4.2.6 */
static final ASN1ObjectIdentifier id_sha512_256 = hashAlgs.branch("6");
- static final ASN1ObjectIdentifier aes = nistAlgorithm.branch("1");
+ /** 2.16.840.1.101.3.4.1 */
+ static final ASN1ObjectIdentifier aes = nistAlgorithm.branch("1");
+ /** 2.16.840.1.101.3.4.1.1 */
static final ASN1ObjectIdentifier id_aes128_ECB = aes.branch("1");
+ /** 2.16.840.1.101.3.4.1.2 */
static final ASN1ObjectIdentifier id_aes128_CBC = aes.branch("2");
+ /** 2.16.840.1.101.3.4.1.3 */
static final ASN1ObjectIdentifier id_aes128_OFB = aes.branch("3");
+ /** 2.16.840.1.101.3.4.1.4 */
static final ASN1ObjectIdentifier id_aes128_CFB = aes.branch("4");
+ /** 2.16.840.1.101.3.4.1.5 */
static final ASN1ObjectIdentifier id_aes128_wrap = aes.branch("5");
+ /** 2.16.840.1.101.3.4.1.6 */
static final ASN1ObjectIdentifier id_aes128_GCM = aes.branch("6");
+ /** 2.16.840.1.101.3.4.1.7 */
static final ASN1ObjectIdentifier id_aes128_CCM = aes.branch("7");
+ /** 2.16.840.1.101.3.4.1.21 */
static final ASN1ObjectIdentifier id_aes192_ECB = aes.branch("21");
+ /** 2.16.840.1.101.3.4.1.22 */
static final ASN1ObjectIdentifier id_aes192_CBC = aes.branch("22");
+ /** 2.16.840.1.101.3.4.1.23 */
static final ASN1ObjectIdentifier id_aes192_OFB = aes.branch("23");
+ /** 2.16.840.1.101.3.4.1.24 */
static final ASN1ObjectIdentifier id_aes192_CFB = aes.branch("24");
+ /** 2.16.840.1.101.3.4.1.25 */
static final ASN1ObjectIdentifier id_aes192_wrap = aes.branch("25");
+ /** 2.16.840.1.101.3.4.1.26 */
static final ASN1ObjectIdentifier id_aes192_GCM = aes.branch("26");
+ /** 2.16.840.1.101.3.4.1.27 */
static final ASN1ObjectIdentifier id_aes192_CCM = aes.branch("27");
+ /** 2.16.840.1.101.3.4.1.41 */
static final ASN1ObjectIdentifier id_aes256_ECB = aes.branch("41");
+ /** 2.16.840.1.101.3.4.1.42 */
static final ASN1ObjectIdentifier id_aes256_CBC = aes.branch("42");
+ /** 2.16.840.1.101.3.4.1.43 */
static final ASN1ObjectIdentifier id_aes256_OFB = aes.branch("43");
+ /** 2.16.840.1.101.3.4.1.44 */
static final ASN1ObjectIdentifier id_aes256_CFB = aes.branch("44");
+ /** 2.16.840.1.101.3.4.1.45 */
static final ASN1ObjectIdentifier id_aes256_wrap = aes.branch("45");
+ /** 2.16.840.1.101.3.4.1.46 */
static final ASN1ObjectIdentifier id_aes256_GCM = aes.branch("46");
+ /** 2.16.840.1.101.3.4.1.47 */
static final ASN1ObjectIdentifier id_aes256_CCM = aes.branch("47");
//
// signatures
//
+ /** 2.16.840.1.101.3.4.3 */
static final ASN1ObjectIdentifier id_dsa_with_sha2 = nistAlgorithm.branch("3");
+ /** 2.16.840.1.101.3.4.3.1 */
static final ASN1ObjectIdentifier dsa_with_sha224 = id_dsa_with_sha2.branch("1");
+ /** 2.16.840.1.101.3.4.3.2 */
static final ASN1ObjectIdentifier dsa_with_sha256 = id_dsa_with_sha2.branch("2");
+ /** 2.16.840.1.101.3.4.3.3 */
static final ASN1ObjectIdentifier dsa_with_sha384 = id_dsa_with_sha2.branch("3");
+ /** 2.16.840.1.101.3.4.3.4 */
static final ASN1ObjectIdentifier dsa_with_sha512 = id_dsa_with_sha2.branch("4");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nist/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/nist/package.html
deleted file mode 100644
index 1cdca76..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/nist/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes for NIST related objects.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java
index 2e4132a..fa32068 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java
@@ -3,15 +3,23 @@ package org.bouncycastle.asn1.ntt;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
/**
- * From RFC 3657
+ * From <a href="http://tools.ietf.org/html/rfc3657">RFC 3657</a>
+ * Use of the Camellia Encryption Algorithm
+ * in Cryptographic Message Syntax (CMS)
*/
public interface NTTObjectIdentifiers
{
- public static final ASN1ObjectIdentifier id_camellia128_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.2");
- public static final ASN1ObjectIdentifier id_camellia192_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.3");
- public static final ASN1ObjectIdentifier id_camellia256_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.4");
+ /** id-camellia128-cbc; OID 1.2.392.200011.61.1.1.1.2 */
+ static final ASN1ObjectIdentifier id_camellia128_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.2");
+ /** id-camellia192-cbc; OID 1.2.392.200011.61.1.1.1.3 */
+ static final ASN1ObjectIdentifier id_camellia192_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.3");
+ /** id-camellia256-cbc; OID 1.2.392.200011.61.1.1.1.4 */
+ static final ASN1ObjectIdentifier id_camellia256_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.4");
- public static final ASN1ObjectIdentifier id_camellia128_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.2");
- public static final ASN1ObjectIdentifier id_camellia192_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.3");
- public static final ASN1ObjectIdentifier id_camellia256_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.4");
+ /** id-camellia128-wrap; OID 1.2.392.200011.61.1.1.3.2 */
+ static final ASN1ObjectIdentifier id_camellia128_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.2");
+ /** id-camellia192-wrap; OID 1.2.392.200011.61.1.1.3.3 */
+ static final ASN1ObjectIdentifier id_camellia192_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.3");
+ /** id-camellia256-wrap; OID 1.2.392.200011.61.1.1.3.4 */
+ static final ASN1ObjectIdentifier id_camellia256_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.4");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java
index 40b15e9..f8ea8f7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java
@@ -2,21 +2,28 @@ package org.bouncycastle.asn1.ocsp;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * OIDs for <a href="http://tools.ietf.org/html/rfc2560">RFC 2560</a>
+ * Online Certificate Status Protocol - OCSP.
+ */
public interface OCSPObjectIdentifiers
{
- public static final String pkix_ocsp = "1.3.6.1.5.5.7.48.1";
-
- public static final ASN1ObjectIdentifier id_pkix_ocsp = new ASN1ObjectIdentifier(pkix_ocsp);
- public static final ASN1ObjectIdentifier id_pkix_ocsp_basic = new ASN1ObjectIdentifier(pkix_ocsp + ".1");
+ /** OID: 1.3.6.1.5.5.7.48.1 */
+ static final ASN1ObjectIdentifier id_pkix_ocsp = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1");
+ /** OID: 1.3.6.1.5.5.7.48.1.1 */
+ static final ASN1ObjectIdentifier id_pkix_ocsp_basic = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1.1");
- //
- // extensions
- //
- public static final ASN1ObjectIdentifier id_pkix_ocsp_nonce = new ASN1ObjectIdentifier(pkix_ocsp + ".2");
- public static final ASN1ObjectIdentifier id_pkix_ocsp_crl = new ASN1ObjectIdentifier(pkix_ocsp + ".3");
+ /** OID: 1.3.6.1.5.5.7.48.1.2 */
+ static final ASN1ObjectIdentifier id_pkix_ocsp_nonce = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1.2");
+ /** OID: 1.3.6.1.5.5.7.48.1.3 */
+ static final ASN1ObjectIdentifier id_pkix_ocsp_crl = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1.3");
- public static final ASN1ObjectIdentifier id_pkix_ocsp_response = new ASN1ObjectIdentifier(pkix_ocsp + ".4");
- public static final ASN1ObjectIdentifier id_pkix_ocsp_nocheck = new ASN1ObjectIdentifier(pkix_ocsp + ".5");
- public static final ASN1ObjectIdentifier id_pkix_ocsp_archive_cutoff = new ASN1ObjectIdentifier(pkix_ocsp + ".6");
- public static final ASN1ObjectIdentifier id_pkix_ocsp_service_locator = new ASN1ObjectIdentifier(pkix_ocsp + ".7");
+ /** OID: 1.3.6.1.5.5.7.48.1.4 */
+ static final ASN1ObjectIdentifier id_pkix_ocsp_response = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1.4");
+ /** OID: 1.3.6.1.5.5.7.48.1.5 */
+ static final ASN1ObjectIdentifier id_pkix_ocsp_nocheck = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1.5");
+ /** OID: 1.3.6.1.5.5.7.48.1.6 */
+ static final ASN1ObjectIdentifier id_pkix_ocsp_archive_cutoff = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1.6");
+ /** OID: 1.3.6.1.5.5.7.48.1.7 */
+ static final ASN1ObjectIdentifier id_pkix_ocsp_service_locator = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1.7");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/RevokedInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/RevokedInfo.java
index 7279ae1..6770050 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/RevokedInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/RevokedInfo.java
@@ -1,12 +1,12 @@
package org.bouncycastle.asn1.ocsp;
import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Enumerated;
import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEREnumerated;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.CRLReason;
@@ -32,8 +32,8 @@ public class RevokedInfo
if (seq.size() > 1)
{
- this.revocationReason = CRLReason.getInstance(DEREnumerated.getInstance(
- (ASN1TaggedObject)seq.getObjectAt(1), true));
+ this.revocationReason = CRLReason.getInstance(ASN1Enumerated.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true));
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/package.html
deleted file mode 100644
index 22c560d..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting OCSP objects.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
index c8ce26b..c169c16 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
@@ -2,30 +2,49 @@ package org.bouncycastle.asn1.oiw;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * OIW organization's OIDs:
+ * <p>
+ * id-SHA1 OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }
+ */
public interface OIWObjectIdentifiers
{
- // id-SHA1 OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
+ /** OID: 1.3.14.3.2.2 */
static final ASN1ObjectIdentifier md4WithRSA = new ASN1ObjectIdentifier("1.3.14.3.2.2");
+ /** OID: 1.3.14.3.2.3 */
static final ASN1ObjectIdentifier md5WithRSA = new ASN1ObjectIdentifier("1.3.14.3.2.3");
+ /** OID: 1.3.14.3.2.4 */
static final ASN1ObjectIdentifier md4WithRSAEncryption = new ASN1ObjectIdentifier("1.3.14.3.2.4");
+ /** OID: 1.3.14.3.2.6 */
static final ASN1ObjectIdentifier desECB = new ASN1ObjectIdentifier("1.3.14.3.2.6");
+ /** OID: 1.3.14.3.2.7 */
static final ASN1ObjectIdentifier desCBC = new ASN1ObjectIdentifier("1.3.14.3.2.7");
+ /** OID: 1.3.14.3.2.8 */
static final ASN1ObjectIdentifier desOFB = new ASN1ObjectIdentifier("1.3.14.3.2.8");
+ /** OID: 1.3.14.3.2.9 */
static final ASN1ObjectIdentifier desCFB = new ASN1ObjectIdentifier("1.3.14.3.2.9");
+ /** OID: 1.3.14.3.2.17 */
static final ASN1ObjectIdentifier desEDE = new ASN1ObjectIdentifier("1.3.14.3.2.17");
+ /** OID: 1.3.14.3.2.26 */
static final ASN1ObjectIdentifier idSHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.26");
+ /** OID: 1.3.14.3.2.27 */
static final ASN1ObjectIdentifier dsaWithSHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.27");
+ /** OID: 1.3.14.3.2.29 */
static final ASN1ObjectIdentifier sha1WithRSA = new ASN1ObjectIdentifier("1.3.14.3.2.29");
- // ElGamal Algorithm OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
- //
+ /**
+ * <pre>
+ * ElGamal Algorithm OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
+ * </pre>
+ * OID: 1.3.14.7.2.1.1
+ */
static final ASN1ObjectIdentifier elGamalAlgorithm = new ASN1ObjectIdentifier("1.3.14.7.2.1.1");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/oiw/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/oiw/package.html
deleted file mode 100644
index 44eb2fe..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/oiw/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Objects and OID for the support of ISO OIW.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/package.html
deleted file mode 100644
index 1ac16a5..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-A library for parsing and writing ASN.1 objects. Support is provided for DER and BER encoding.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
index 65c0fa8..92c4e8f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
@@ -9,16 +9,39 @@ import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
-
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * <pre>
+ * PBKDF2-params ::= SEQUENCE {
+ * salt CHOICE {
+ * specified OCTET STRING,
+ * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
+ * },
+ * iterationCount INTEGER (1..MAX),
+ * keyLength INTEGER (1..MAX) OPTIONAL,
+ * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
+ * </pre>
+ */
public class PBKDF2Params
extends ASN1Object
{
+ private static final AlgorithmIdentifier algid_hmacWithSHA1 = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA1, DERNull.INSTANCE);
+
private ASN1OctetString octStr;
private ASN1Integer iterationCount;
private ASN1Integer keyLength;
-
+ private AlgorithmIdentifier prf;
+
+ /**
+ * Create PBKDF2Params from the passed in object,
+ *
+ * @param obj either PBKDF2Params or an ASN2Sequence.
+ * @return a PBKDF2Params instance.
+ */
public static PBKDF2Params getInstance(
Object obj)
{
@@ -34,7 +57,13 @@ public class PBKDF2Params
return null;
}
-
+
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, and algid-hmacWithSHA1 for the prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ */
public PBKDF2Params(
byte[] salt,
int iterationCount)
@@ -43,6 +72,13 @@ public class PBKDF2Params
this.iterationCount = new ASN1Integer(iterationCount);
}
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, keyLength, and algid-hmacWithSHA1 for the prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ * @param keyLength intended key length to be produced.
+ */
public PBKDF2Params(
byte[] salt,
int iterationCount,
@@ -53,6 +89,42 @@ public class PBKDF2Params
this.keyLength = new ASN1Integer(keyLength);
}
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, keyLength, and a defined prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ * @param keyLength intended key length to be produced.
+ * @param prf the pseudo-random function to use.
+ */
+ public PBKDF2Params(
+ byte[] salt,
+ int iterationCount,
+ int keyLength,
+ AlgorithmIdentifier prf)
+ {
+ this(salt, iterationCount);
+
+ this.keyLength = new ASN1Integer(keyLength);
+ this.prf = prf;
+ }
+
+ /**
+ * Create a PBKDF2Params with the specified salt, iteration count, and a defined prf.
+ *
+ * @param salt input salt.
+ * @param iterationCount input iteration count.
+ * @param prf the pseudo-random function to use.
+ */
+ public PBKDF2Params(
+ byte[] salt,
+ int iterationCount,
+ AlgorithmIdentifier prf)
+ {
+ this(salt, iterationCount);
+ this.prf = prf;
+ }
+
private PBKDF2Params(
ASN1Sequence seq)
{
@@ -63,24 +135,57 @@ public class PBKDF2Params
if (e.hasMoreElements())
{
- keyLength = (ASN1Integer)e.nextElement();
- }
- else
- {
- keyLength = null;
+ Object o = e.nextElement();
+
+ if (o instanceof ASN1Integer)
+ {
+ keyLength = ASN1Integer.getInstance(o);
+ if (e.hasMoreElements())
+ {
+ o = e.nextElement();
+ }
+ else
+ {
+ o = null;
+ }
+ }
+ else
+ {
+ keyLength = null;
+ }
+
+ if (o != null)
+ {
+ prf = AlgorithmIdentifier.getInstance(o);
+ }
}
}
+ /**
+ * Return the salt to use.
+ *
+ * @return the input salt.
+ */
public byte[] getSalt()
{
return octStr.getOctets();
}
+ /**
+ * Return the iteration count to use.
+ *
+ * @return the input iteration count.
+ */
public BigInteger getIterationCount()
{
return iterationCount.getValue();
}
+ /**
+ * Return the intended length in octets of the derived key.
+ *
+ * @return length in octets for derived key, if specified.
+ */
public BigInteger getKeyLength()
{
if (keyLength != null)
@@ -91,6 +196,36 @@ public class PBKDF2Params
return null;
}
+ /**
+ * Return true if the PRF is the default (hmacWithSHA1)
+ *
+ * @return true if PRF is default, false otherwise.
+ */
+ public boolean isDefaultPrf()
+ {
+ return prf == null || prf.equals(algid_hmacWithSHA1);
+ }
+
+ /**
+ * Return the algId of the underlying pseudo random function to use.
+ *
+ * @return the prf algorithm identifier.
+ */
+ public AlgorithmIdentifier getPrf()
+ {
+ if (prf != null)
+ {
+ return prf;
+ }
+
+ return algid_hmacWithSHA1;
+ }
+
+ /**
+ * Return an ASN.1 structure suitable for encoding.
+ *
+ * @return the object as an ASN.1 encodable structure.
+ */
public ASN1Primitive toASN1Primitive()
{
ASN1EncodableVector v = new ASN1EncodableVector();
@@ -103,6 +238,11 @@ public class PBKDF2Params
v.add(keyLength);
}
+ if (prf != null && !prf.equals(algid_hmacWithSHA1))
+ {
+ v.add(prf);
+ }
+
return new DERSequence(v);
}
}
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 405d0b4..05fced0 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
@@ -2,257 +2,389 @@ package org.bouncycastle.asn1.pkcs;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * pkcs-1 OBJECT IDENTIFIER ::=<p>
+ * { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
+ *
+ */
public interface PKCSObjectIdentifiers
{
- //
- // pkcs-1 OBJECT IDENTIFIER ::= {
- // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
- //
+ /** PKCS#1: 1.2.840.113549.1.1 */
static final 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");
+ /** PKCS#1: 1.2.840.113549.1.1.2 */
static final ASN1ObjectIdentifier md2WithRSAEncryption = pkcs_1.branch("2");
+ /** PKCS#1: 1.2.840.113549.1.1.3 */
static final ASN1ObjectIdentifier md4WithRSAEncryption = pkcs_1.branch("3");
+ /** PKCS#1: 1.2.840.113549.1.1.4 */
static final ASN1ObjectIdentifier md5WithRSAEncryption = pkcs_1.branch("4");
+ /** PKCS#1: 1.2.840.113549.1.1.5 */
static final ASN1ObjectIdentifier sha1WithRSAEncryption = pkcs_1.branch("5");
+ /** PKCS#1: 1.2.840.113549.1.1.6 */
static final 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");
+ /** PKCS#1: 1.2.840.113549.1.1.8 */
static final 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");
+ /** PKCS#1: 1.2.840.113549.1.1.10 */
static final 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");
+ /** PKCS#1: 1.2.840.113549.1.1.12 */
static final ASN1ObjectIdentifier sha384WithRSAEncryption = pkcs_1.branch("12");
+ /** PKCS#1: 1.2.840.113549.1.1.13 */
static final ASN1ObjectIdentifier sha512WithRSAEncryption = pkcs_1.branch("13");
+ /** PKCS#1: 1.2.840.113549.1.1.14 */
static final ASN1ObjectIdentifier sha224WithRSAEncryption = pkcs_1.branch("14");
//
// pkcs-3 OBJECT IDENTIFIER ::= {
// 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");
+ /** PKCS#3: 1.2.840.113549.1.3.1 */
static final 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");
+ /** PKCS#5: 1.2.840.113549.1.5.1 */
static final 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");
+ /** PKCS#5: 1.2.840.113549.1.5.3 */
static final 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");
+ /** PKCS#5: 1.2.840.113549.1.5.10 */
static final 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");
-
+ /** PKCS#5: 1.2.840.113549.1.5.13 */
static final 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");
//
// 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");
+ /** 1.2.840.113549.3.7 */
static final ASN1ObjectIdentifier des_EDE3_CBC = encryptionAlgorithm.branch("7");
+ /** 1.2.840.113549.3.2 */
static final ASN1ObjectIdentifier RC2_CBC = encryptionAlgorithm.branch("2");
+ /** 1.2.840.113549.3.4 */
static final 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");
//
// md2 OBJECT IDENTIFIER ::=
// {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2}
//
+ /** 1.2.840.113549.2.2 */
static final ASN1ObjectIdentifier md2 = digestAlgorithm.branch("2");
//
// md4 OBJECT IDENTIFIER ::=
// {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 4}
//
- static final ASN1ObjectIdentifier md4 = digestAlgorithm.branch("4");
+ /** 1.2.840.113549.2.4 */
+ static final ASN1ObjectIdentifier md4 = digestAlgorithm.branch("4");
//
// md5 OBJECT IDENTIFIER ::=
// {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
//
- static final ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5");
+ /** 1.2.840.113549.2.5 */
+ static final ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5");
- static final ASN1ObjectIdentifier id_hmacWithSHA1 = digestAlgorithm.branch("7");
- static final ASN1ObjectIdentifier id_hmacWithSHA224 = digestAlgorithm.branch("8");
- static final ASN1ObjectIdentifier id_hmacWithSHA256 = digestAlgorithm.branch("9");
- static final ASN1ObjectIdentifier id_hmacWithSHA384 = digestAlgorithm.branch("10");
- static final ASN1ObjectIdentifier id_hmacWithSHA512 = digestAlgorithm.branch("11");
+ /** 1.2.840.113549.2.7 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA1 = digestAlgorithm.branch("7");
+ /** 1.2.840.113549.2.8 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA224 = digestAlgorithm.branch("8");
+ /** 1.2.840.113549.2.9 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA256 = digestAlgorithm.branch("9");
+ /** 1.2.840.113549.2.10 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA384 = digestAlgorithm.branch("10");
+ /** 1.2.840.113549.2.11 */
+ static final ASN1ObjectIdentifier id_hmacWithSHA512 = digestAlgorithm.branch("11");
//
// pkcs-7 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
//
- static final String pkcs_7 = "1.2.840.113549.1.7";
- static final ASN1ObjectIdentifier data = new ASN1ObjectIdentifier(pkcs_7 + ".1");
- static final ASN1ObjectIdentifier signedData = new ASN1ObjectIdentifier(pkcs_7 + ".2");
- static final ASN1ObjectIdentifier envelopedData = new ASN1ObjectIdentifier(pkcs_7 + ".3");
- static final ASN1ObjectIdentifier signedAndEnvelopedData = new ASN1ObjectIdentifier(pkcs_7 + ".4");
- static final ASN1ObjectIdentifier digestedData = new ASN1ObjectIdentifier(pkcs_7 + ".5");
- static final ASN1ObjectIdentifier encryptedData = new ASN1ObjectIdentifier(pkcs_7 + ".6");
+ /** pkcs#7: 1.2.840.113549.1.7 */
+ static final ASN1ObjectIdentifier pkcs_7 = new ASN1ObjectIdentifier("1.2.840.113549.1.7");
+ /** PKCS#7: 1.2.840.113549.1.7.1 */
+ static final ASN1ObjectIdentifier data = new ASN1ObjectIdentifier("1.2.840.113549.1.7.1");
+ /** PKCS#7: 1.2.840.113549.1.7.2 */
+ static final ASN1ObjectIdentifier signedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.2");
+ /** PKCS#7: 1.2.840.113549.1.7.3 */
+ static final ASN1ObjectIdentifier envelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.3");
+ /** PKCS#7: 1.2.840.113549.1.7.4 */
+ static final ASN1ObjectIdentifier signedAndEnvelopedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.4");
+ /** PKCS#7: 1.2.840.113549.1.7.5 */
+ static final ASN1ObjectIdentifier digestedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.5");
+ /** PKCS#7: 1.2.840.113549.1.7.76 */
+ static final ASN1ObjectIdentifier encryptedData = new ASN1ObjectIdentifier("1.2.840.113549.1.7.6");
//
// 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");
- static final ASN1ObjectIdentifier pkcs_9_at_emailAddress = pkcs_9.branch("1");
- static final ASN1ObjectIdentifier pkcs_9_at_unstructuredName = pkcs_9.branch("2");
- static final ASN1ObjectIdentifier pkcs_9_at_contentType = pkcs_9.branch("3");
- static final ASN1ObjectIdentifier pkcs_9_at_messageDigest = pkcs_9.branch("4");
- static final ASN1ObjectIdentifier pkcs_9_at_signingTime = pkcs_9.branch("5");
- static final ASN1ObjectIdentifier pkcs_9_at_counterSignature = pkcs_9.branch("6");
- static final ASN1ObjectIdentifier pkcs_9_at_challengePassword = pkcs_9.branch("7");
+ /** PKCS#9: 1.2.840.113549.1.9.1 */
+ static final ASN1ObjectIdentifier pkcs_9_at_emailAddress = pkcs_9.branch("1");
+ /** PKCS#9: 1.2.840.113549.1.9.2 */
+ static final ASN1ObjectIdentifier pkcs_9_at_unstructuredName = pkcs_9.branch("2");
+ /** PKCS#9: 1.2.840.113549.1.9.3 */
+ static final ASN1ObjectIdentifier pkcs_9_at_contentType = pkcs_9.branch("3");
+ /** PKCS#9: 1.2.840.113549.1.9.4 */
+ static final ASN1ObjectIdentifier pkcs_9_at_messageDigest = pkcs_9.branch("4");
+ /** PKCS#9: 1.2.840.113549.1.9.5 */
+ static final ASN1ObjectIdentifier pkcs_9_at_signingTime = pkcs_9.branch("5");
+ /** PKCS#9: 1.2.840.113549.1.9.6 */
+ static final ASN1ObjectIdentifier pkcs_9_at_counterSignature = pkcs_9.branch("6");
+ /** PKCS#9: 1.2.840.113549.1.9.7 */
+ static final ASN1ObjectIdentifier pkcs_9_at_challengePassword = pkcs_9.branch("7");
+ /** PKCS#9: 1.2.840.113549.1.9.8 */
static final ASN1ObjectIdentifier pkcs_9_at_unstructuredAddress = pkcs_9.branch("8");
+ /** PKCS#9: 1.2.840.113549.1.9.9 */
static final ASN1ObjectIdentifier pkcs_9_at_extendedCertificateAttributes = pkcs_9.branch("9");
+ /** PKCS#9: 1.2.840.113549.1.9.13 */
static final ASN1ObjectIdentifier pkcs_9_at_signingDescription = pkcs_9.branch("13");
- static final ASN1ObjectIdentifier pkcs_9_at_extensionRequest = pkcs_9.branch("14");
- static final ASN1ObjectIdentifier pkcs_9_at_smimeCapabilities = pkcs_9.branch("15");
-
+ /** PKCS#9: 1.2.840.113549.1.9.14 */
+ static final ASN1ObjectIdentifier pkcs_9_at_extensionRequest = pkcs_9.branch("14");
+ /** PKCS#9: 1.2.840.113549.1.9.15 */
+ static final ASN1ObjectIdentifier pkcs_9_at_smimeCapabilities = pkcs_9.branch("15");
+ /** PKCS#9: 1.2.840.113549.1.9.16 */
+ static final ASN1ObjectIdentifier id_smime = pkcs_9.branch("16");
+
+ /** PKCS#9: 1.2.840.113549.1.9.20 */
static final ASN1ObjectIdentifier pkcs_9_at_friendlyName = pkcs_9.branch("20");
+ /** PKCS#9: 1.2.840.113549.1.9.21 */
static final ASN1ObjectIdentifier pkcs_9_at_localKeyId = pkcs_9.branch("21");
- /** @deprecated use x509Certificate instead */
+ /** PKCS#9: 1.2.840.113549.1.9.22.1
+ * @deprecated use x509Certificate instead */
static final ASN1ObjectIdentifier x509certType = pkcs_9.branch("22.1");
+ /** PKCS#9: 1.2.840.113549.1.9.22 */
static final ASN1ObjectIdentifier certTypes = pkcs_9.branch("22");
+ /** PKCS#9: 1.2.840.113549.1.9.22.1 */
static final ASN1ObjectIdentifier x509Certificate = certTypes.branch("1");
+ /** PKCS#9: 1.2.840.113549.1.9.22.2 */
static final ASN1ObjectIdentifier sdsiCertificate = certTypes.branch("2");
+ /** PKCS#9: 1.2.840.113549.1.9.23 */
static final ASN1ObjectIdentifier crlTypes = pkcs_9.branch("23");
+ /** PKCS#9: 1.2.840.113549.1.9.23.1 */
static final ASN1ObjectIdentifier x509Crl = crlTypes.branch("1");
- static final ASN1ObjectIdentifier id_alg_PWRI_KEK = pkcs_9.branch("16.3.9");
-
//
// 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");
+ /** PKCS#9: 1.2.840.113549.1.9.15.2 -- smime capability */
static final 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");
//
// 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");
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.2 -- smime ct authData */
static final 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");
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.9 -- smime ct compressedData */
static final 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");
+ /** PKCS#9: 1.2.840.113549.1.9.16.1.31 -- smime ct timestampedData*/
static final 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");
+ /** PKCS#9: 1.2.840.113549.1.9.16.3.9 */
+ static final ASN1ObjectIdentifier id_alg_PWRI_KEK = id_alg.branch("9");
+
//
// 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");
- static final ASN1ObjectIdentifier id_cti_ets_proofOfOrigin = id_cti.branch("1");
- static final ASN1ObjectIdentifier id_cti_ets_proofOfReceipt = id_cti.branch("2");
+ /** 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");
+ /** 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");
+ /** 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");
- static final ASN1ObjectIdentifier id_cti_ets_proofOfSender = id_cti.branch("4");
+ /** 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");
+ /** 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");
+ /** 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");
//
// 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.6.2.1 -- smime attribute receiptRequest */
static final ASN1ObjectIdentifier id_aa_receiptRequest = id_aa.branch("1");
- static final ASN1ObjectIdentifier id_aa_contentHint = id_aa.branch("4"); // See RFC 2634
- static final ASN1ObjectIdentifier id_aa_msgSigDigest = id_aa.branch("5");
+ /** 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");
/*
* id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
*
*/
- static final ASN1ObjectIdentifier id_aa_encrypKeyPref = id_aa.branch("11");
- static final ASN1ObjectIdentifier id_aa_signingCertificate = id_aa.branch("12");
+ /** 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.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
/*
* 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.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.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");
/** @deprecated use id_aa_ets_sigPolicyId instead */
- static final ASN1ObjectIdentifier id_aa_sigPolicyId = id_aa_ets_sigPolicyId;
+ static final 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;
/** @deprecated use id_aa_ets_signerLocation instead */
static final 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;
+ static final ASN1ObjectIdentifier id_aa_otherSigCert = id_aa_ets_otherSigCert;
- //
- // id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
- // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-spq(5)}
- //
+ /**
+ * id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ * rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-spq(5)}; <p>
+ * 1.2.840.113549.1.9.16.5
+ */
final String id_spq = "1.2.840.113549.1.9.16.5";
- static final ASN1ObjectIdentifier id_spq_ets_uri = new ASN1ObjectIdentifier(id_spq + ".1");
+ /** SMIME SPQ URI: 1.2.840.113549.1.9.16.5.1 */
+ static final 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");
//
// 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");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1 */
static final 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");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.2 */
static final ASN1ObjectIdentifier pkcs8ShroudedKeyBag = bagtypes.branch("2");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.3 */
static final ASN1ObjectIdentifier certBag = bagtypes.branch("3");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.4 */
static final ASN1ObjectIdentifier crlBag = bagtypes.branch("4");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.5 */
static final ASN1ObjectIdentifier secretBag = bagtypes.branch("5");
+ /** PKCS#12: 1.2.840.113549.1.12.10.1.6 */
static final ASN1ObjectIdentifier safeContentsBag = bagtypes.branch("6");
- static final ASN1ObjectIdentifier pkcs_12PbeIds = pkcs_12.branch("1");
+ /** PKCS#12: 1.2.840.113549.1.12.1 */
+ static final ASN1ObjectIdentifier pkcs_12PbeIds = pkcs_12.branch("1");
- static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC4 = pkcs_12PbeIds.branch("1");
- static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC4 = pkcs_12PbeIds.branch("2");
+ /** PKCS#12: 1.2.840.113549.1.12.1.1 */
+ static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC4 = pkcs_12PbeIds.branch("1");
+ /** PKCS#12: 1.2.840.113549.1.12.1.2 */
+ static final 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");
+ /** PKCS#12: 1.2.840.113549.1.12.1.4 */
static final ASN1ObjectIdentifier pbeWithSHAAnd2_KeyTripleDES_CBC = pkcs_12PbeIds.branch("4");
- static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC2_CBC = pkcs_12PbeIds.branch("5");
- static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
+ /** PKCS#12: 1.2.840.113549.1.12.1.5 */
+ static final 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");
/**
+ * PKCS#12: 1.2.840.113549.1.12.1.6
* @deprecated use pbeWithSHAAnd40BitRC2_CBC
*/
static final 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");
- static final ASN1ObjectIdentifier id_alg_CMSRC2wrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7");
+ /** PKCS#9: 1.2.840.113549.1.9.16.3.7 */
+ static final ASN1ObjectIdentifier id_alg_CMSRC2wrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java
index 515b515..e707fd1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java
@@ -57,7 +57,11 @@ public class RSAESOAEPparams
this.maskGenAlgorithm = maskGenAlgorithm;
this.pSourceAlgorithm = pSourceAlgorithm;
}
-
+
+ /**
+ * @deprecated use getInstance()
+ * @param seq
+ */
public RSAESOAEPparams(
ASN1Sequence seq)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/package.html
deleted file mode 100644
index ab800f4..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting the various RSA PKCS documents.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
index 4bf6b2b..df2238a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
@@ -62,7 +62,7 @@ public class ECPrivateKey
public ECPrivateKey(
BigInteger key,
- ASN1Object parameters)
+ ASN1Encodable parameters)
{
this(key, null, parameters);
}
@@ -70,7 +70,7 @@ public class ECPrivateKey
public ECPrivateKey(
BigInteger key,
DERBitString publicKey,
- ASN1Object parameters)
+ ASN1Encodable parameters)
{
byte[] bytes = BigIntegers.asUnsignedByteArray(key);
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
index 44c811b..50a7a63 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java
@@ -15,6 +15,21 @@ import org.bouncycastle.util.encoders.Hex;
public class SECNamedCurves
{
+ private static ECCurve configureCurve(ECCurve curve)
+ {
+// int coord = ECCurve.COORD_JACOBIAN_MODIFIED;
+//
+// if (curve.getCoordinateSystem() != coord && curve.supportsCoordinateSystem(coord))
+// {
+// return curve.configure()
+// .setCoordinateSystem(coord)
+//// .setMultiplier(new WNafL2RMultiplier())
+// .create();
+// }
+
+ return curve;
+ }
+
private static BigInteger fromHex(
String hex)
{
@@ -36,7 +51,7 @@ public class SECNamedCurves
BigInteger n = fromHex("DB7C2ABF62E35E7628DFAC6561C5");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "09487239995A5EE76B55F9C2F098"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -62,7 +77,7 @@ public class SECNamedCurves
BigInteger n = fromHex("36DF0AAFD8B8D7597CA10520D04B");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "4BA30AB5E892B4E1649DD0928643"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -88,7 +103,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFE0000000075A30D1B9038A115");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "161FF7528B899B2D0C28607CA52C5B86"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -114,7 +129,7 @@ public class SECNamedCurves
BigInteger n = fromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "7B6AA5D85E572983E6FB32A7CDEBC140"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -140,7 +155,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
// ECPoint G = curve.decodePoint(Hex.decode("02"
// + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -166,7 +181,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000000001F4C8F927AED3CA752257");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "4A96B5688EF573284664698968C38BB913CBFC82"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -192,7 +207,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000000000351EE786A818F3A1A16B");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -218,7 +233,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -244,7 +259,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -270,7 +285,7 @@ public class SECNamedCurves
BigInteger n = fromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -296,7 +311,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -322,7 +337,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -348,7 +363,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -374,7 +389,7 @@ public class SECNamedCurves
BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -400,7 +415,8 @@ public class SECNamedCurves
BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409");
BigInteger h = BigInteger.valueOf(1);
- ECCurve curve = new ECCurve.Fp(p, a, b);
+ ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b));
+
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -410,7 +426,7 @@ public class SECNamedCurves
return new X9ECParameters(curve, G, n, h, S);
}
};
-
+
/*
* sect113r1
*/
@@ -427,7 +443,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0100000000000000D9CCEC8A39E56F");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "009D73616F35F4AB1407D73562C10F"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -454,7 +470,7 @@ public class SECNamedCurves
BigInteger n = fromHex("010000000000000108789B2496AF93");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "01A57A6A7B26CA5EF52FCDB8164797"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -483,7 +499,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0400000000000000023123953A9464B54D");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0081BAF91FDF9833C40F9C181343638399"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -512,7 +528,7 @@ public class SECNamedCurves
BigInteger n = fromHex("0400000000000000016954A233049BA98F");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0356DCD8F2F95031AD652D23951BB366A8"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -541,7 +557,7 @@ public class SECNamedCurves
BigInteger n = fromHex("04000000000000000000020108A2E0CC0D99F8A5EF");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -570,7 +586,7 @@ public class SECNamedCurves
BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0369979697AB43897789566789567F787A7876A654"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -599,7 +615,7 @@ public class SECNamedCurves
BigInteger n = fromHex("040000000000000000000292FE77E70C12A4234C33");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "03F0EBA16286A2D57EA0991168D4994637E8343E36"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -626,7 +642,7 @@ public class SECNamedCurves
BigInteger n = fromHex("01000000000000000000000000C7F34A778F443ACC920EBA49");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -653,7 +669,7 @@ public class SECNamedCurves
BigInteger n = fromHex("010000000000000000000000015AAB561B005413CCD4EE99D5");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -680,7 +696,7 @@ public class SECNamedCurves
BigInteger n = fromHex("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -707,7 +723,7 @@ public class SECNamedCurves
BigInteger n = fromHex("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -734,7 +750,7 @@ public class SECNamedCurves
BigInteger n = fromHex("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -763,7 +779,7 @@ public class SECNamedCurves
BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -792,7 +808,7 @@ public class SECNamedCurves
BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -819,7 +835,7 @@ public class SECNamedCurves
BigInteger n = fromHex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -846,7 +862,7 @@ public class SECNamedCurves
BigInteger n = fromHex("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -875,7 +891,7 @@ public class SECNamedCurves
BigInteger n = fromHex("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001");
BigInteger h = BigInteger.valueOf(4);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("02"
//+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"));
ECPoint G = curve.decodePoint(Hex.decode("04"
@@ -904,7 +920,7 @@ public class SECNamedCurves
BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47");
BigInteger h = BigInteger.valueOf(2);
- ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ ECCurve curve = configureCurve(new ECCurve.F2m(m, k1, k2, k3, a, b, n, h));
//ECPoint G = curve.decodePoint(Hex.decode("03"
//+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"));
ECPoint G = curve.decodePoint(Hex.decode("04"
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 8b19cd6..fb60aca 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
@@ -3,48 +3,85 @@ package org.bouncycastle.asn1.sec;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+/**
+ * Certicom object identifiers
+ * <pre>
+ * ellipticCurve OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0)
+ * }
+ * </pre>
+ */
public interface SECObjectIdentifiers
{
- /**
- * ellipticCurve OBJECT IDENTIFIER ::= {
- * iso(1) identified-organization(3) certicom(132) curve(0)
- * }
- */
+ /** Base OID: 1.3.132.0 */
static final ASN1ObjectIdentifier ellipticCurve = new ASN1ObjectIdentifier("1.3.132.0");
+ /** sect163k1 OID: 1.3.132.0.1 */
static final ASN1ObjectIdentifier sect163k1 = ellipticCurve.branch("1");
+ /** sect163r1 OID: 1.3.132.0.2 */
static final ASN1ObjectIdentifier sect163r1 = ellipticCurve.branch("2");
+ /** sect239k1 OID: 1.3.132.0.3 */
static final ASN1ObjectIdentifier sect239k1 = ellipticCurve.branch("3");
+ /** sect113r1 OID: 1.3.132.0.4 */
static final ASN1ObjectIdentifier sect113r1 = ellipticCurve.branch("4");
+ /** sect113r2 OID: 1.3.132.0.5 */
static final ASN1ObjectIdentifier sect113r2 = ellipticCurve.branch("5");
+ /** secp112r1 OID: 1.3.132.0.6 */
static final ASN1ObjectIdentifier secp112r1 = ellipticCurve.branch("6");
+ /** secp112r2 OID: 1.3.132.0.7 */
static final ASN1ObjectIdentifier secp112r2 = ellipticCurve.branch("7");
+ /** secp160r1 OID: 1.3.132.0.8 */
static final ASN1ObjectIdentifier secp160r1 = ellipticCurve.branch("8");
+ /** secp160k1 OID: 1.3.132.0.9 */
static final ASN1ObjectIdentifier secp160k1 = ellipticCurve.branch("9");
+ /** secp256k1 OID: 1.3.132.0.10 */
static final ASN1ObjectIdentifier secp256k1 = ellipticCurve.branch("10");
+ /** sect163r2 OID: 1.3.132.0.15 */
static final ASN1ObjectIdentifier sect163r2 = ellipticCurve.branch("15");
+ /** sect283k1 OID: 1.3.132.0.16 */
static final ASN1ObjectIdentifier sect283k1 = ellipticCurve.branch("16");
+ /** sect283r1 OID: 1.3.132.0.17 */
static final ASN1ObjectIdentifier sect283r1 = ellipticCurve.branch("17");
+ /** sect131r1 OID: 1.3.132.0.22 */
static final ASN1ObjectIdentifier sect131r1 = ellipticCurve.branch("22");
+ /** sect131r2 OID: 1.3.132.0.23 */
static final ASN1ObjectIdentifier sect131r2 = ellipticCurve.branch("23");
+ /** sect193r1 OID: 1.3.132.0.24 */
static final ASN1ObjectIdentifier sect193r1 = ellipticCurve.branch("24");
+ /** sect193r2 OID: 1.3.132.0.25 */
static final ASN1ObjectIdentifier sect193r2 = ellipticCurve.branch("25");
+ /** sect233k1 OID: 1.3.132.0.26 */
static final ASN1ObjectIdentifier sect233k1 = ellipticCurve.branch("26");
+ /** sect233r1 OID: 1.3.132.0.27 */
static final ASN1ObjectIdentifier sect233r1 = ellipticCurve.branch("27");
+ /** secp128r1 OID: 1.3.132.0.28 */
static final ASN1ObjectIdentifier secp128r1 = ellipticCurve.branch("28");
+ /** secp128r2 OID: 1.3.132.0.29 */
static final ASN1ObjectIdentifier secp128r2 = ellipticCurve.branch("29");
+ /** secp160r2 OID: 1.3.132.0.30 */
static final ASN1ObjectIdentifier secp160r2 = ellipticCurve.branch("30");
+ /** secp192k1 OID: 1.3.132.0.31 */
static final ASN1ObjectIdentifier secp192k1 = ellipticCurve.branch("31");
+ /** secp224k1 OID: 1.3.132.0.32 */
static final ASN1ObjectIdentifier secp224k1 = ellipticCurve.branch("32");
+ /** secp224r1 OID: 1.3.132.0.33 */
static final ASN1ObjectIdentifier secp224r1 = ellipticCurve.branch("33");
+ /** secp384r1 OID: 1.3.132.0.34 */
static final ASN1ObjectIdentifier secp384r1 = ellipticCurve.branch("34");
+ /** secp521r1 OID: 1.3.132.0.35 */
static final ASN1ObjectIdentifier secp521r1 = ellipticCurve.branch("35");
+ /** sect409k1 OID: 1.3.132.0.36 */
static final ASN1ObjectIdentifier sect409k1 = ellipticCurve.branch("36");
+ /** sect409r1 OID: 1.3.132.0.37 */
static final ASN1ObjectIdentifier sect409r1 = ellipticCurve.branch("37");
+ /** sect571k1 OID: 1.3.132.0.38 */
static final ASN1ObjectIdentifier sect571k1 = ellipticCurve.branch("38");
+ /** sect571r1 OID: 1.3.132.0.39 */
static final ASN1ObjectIdentifier sect571r1 = ellipticCurve.branch("39");
+ /** secp192r1 OID: 1.3.132.0.prime192v1 */
static final ASN1ObjectIdentifier secp192r1 = X9ObjectIdentifiers.prime192v1;
+ /** secp256r1 OID: 1.3.132.0.prime256v1 */
static final ASN1ObjectIdentifier secp256r1 = X9ObjectIdentifiers.prime256v1;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/sec/package.html
deleted file mode 100644
index 5e34dec..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for support of the SEC standard for Elliptic Curve.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/smime/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/smime/package.html
deleted file mode 100644
index d527aba..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/smime/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting S/MIME.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java
index 17f0491..ba2f19e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java
@@ -17,14 +17,19 @@ import org.bouncycastle.util.encoders.Hex;
*/
public class TeleTrusTNamedCurves
{
+ private static ECCurve configureCurve(ECCurve curve)
+ {
+ return curve;
+ }
+
static X9ECParametersHolder brainpoolP160r1 = new X9ECParametersHolder()
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
new BigInteger("340E7BE2A280EB74E2BE61BADA745D97E8F7C300", 16), // a
- new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16)); // b
+ new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16))); // b
return new X9ECParameters(
curve,
@@ -38,11 +43,11 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
// new BigInteger("24DBFF5DEC9B986BBFE5295A29BFBAE45E0F5D0B", 16), // Z
new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620C", 16), // a'
- new BigInteger("7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", 16)); // b'
+ new BigInteger("7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", 16))); // b'
return new X9ECParameters(
curve,
@@ -56,10 +61,10 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
new BigInteger("6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", 16), // a
- new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16)); // b
+ new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16))); // b
return new X9ECParameters(
curve,
@@ -73,11 +78,11 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
//new BigInteger("1B6F5CC8DB4DC7AF19458A9CB80DC2295E5EB9C3732104CB") //Z
new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", 16), // a'
- new BigInteger("13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", 16)); // b'
+ new BigInteger("13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", 16))); // b'
return new X9ECParameters(
curve,
@@ -91,10 +96,10 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
new BigInteger("68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", 16), // a
- new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16)); // b
+ new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16))); // b
return new X9ECParameters(
curve,
@@ -107,11 +112,11 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
//new BigInteger("2DF271E14427A346910CF7A2E6CFA7B3F484E5C2CCE1C8B730E28B3F") //Z
new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", 16), // a'
- new BigInteger("4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", 16)); // b'
+ new BigInteger("4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", 16))); // b'
return new X9ECParameters(
curve,
@@ -124,10 +129,10 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
new BigInteger("7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", 16), // a
- new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16)); // b
+ new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16))); // b
return new X9ECParameters(
curve,
@@ -140,11 +145,11 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
//new BigInteger("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0") //Z
new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", 16), // a'
- new BigInteger("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16)); // b'
+ new BigInteger("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16))); // b'
return new X9ECParameters(
curve,
@@ -157,10 +162,10 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
new BigInteger("3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", 16), // a
- new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16)); // b
+ new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16))); // b
return new X9ECParameters(
curve,
@@ -173,11 +178,11 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
//new BigInteger("15F75CAF668077F7E85B42EB01F0A81FF56ECD6191D55CB82B7D861458A18FEFC3E5AB7496F3C7B1") //Z
new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", 16), // a'
- new BigInteger("A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", 16)); // b'
+ new BigInteger("A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", 16))); // b'
return new X9ECParameters(
curve,
@@ -190,10 +195,10 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
new BigInteger("7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", 16), // a
- new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16)); // b
+ new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16))); // b
return new X9ECParameters(
curve,
@@ -206,11 +211,11 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
//new BigInteger("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C") //Z
new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", 16), // a'
- new BigInteger("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16)); // b'
+ new BigInteger("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16))); // b'
return new X9ECParameters(
curve,
@@ -223,10 +228,10 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
new BigInteger("7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", 16), // a
- new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16)); // b
+ new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16))); // b
return new X9ECParameters(
curve,
@@ -239,11 +244,11 @@ public class TeleTrusTNamedCurves
{
protected X9ECParameters createParameters()
{
- ECCurve curve = new ECCurve.Fp(
+ ECCurve curve = configureCurve(new ECCurve.Fp(
//new BigInteger("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB") //Z
new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", 16), // a'
- new BigInteger("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16)); // b'
+ new BigInteger("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16))); // b'
return new X9ECParameters(
curve,
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
index df9a0ff..895f5e8 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
@@ -2,41 +2,74 @@ package org.bouncycastle.asn1.teletrust;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * TeleTrusT:
+ * { iso(1) identifier-organization(3) teleTrust(36) algorithm(3)
+ *
+ */
public interface TeleTrusTObjectIdentifiers
{
+ /** 1.3.36.3 */
static final ASN1ObjectIdentifier teleTrusTAlgorithm = new ASN1ObjectIdentifier("1.3.36.3");
+ /** 1.3.36.3.2.1 */
static final ASN1ObjectIdentifier ripemd160 = teleTrusTAlgorithm.branch("2.1");
+ /** 1.3.36.3.2.2 */
static final ASN1ObjectIdentifier ripemd128 = teleTrusTAlgorithm.branch("2.2");
+ /** 1.3.36.3.2.3 */
static final ASN1ObjectIdentifier ripemd256 = teleTrusTAlgorithm.branch("2.3");
+ /** 1.3.36.3.3.1 */
static final ASN1ObjectIdentifier teleTrusTRSAsignatureAlgorithm = teleTrusTAlgorithm.branch("3.1");
- static final ASN1ObjectIdentifier rsaSignatureWithripemd160 = teleTrusTRSAsignatureAlgorithm.branch("2");
- static final ASN1ObjectIdentifier rsaSignatureWithripemd128 = teleTrusTRSAsignatureAlgorithm.branch("3");
- static final ASN1ObjectIdentifier rsaSignatureWithripemd256 = teleTrusTRSAsignatureAlgorithm.branch("4");
+ /** 1.3.36.3.3.1.2 */
+ static final ASN1ObjectIdentifier rsaSignatureWithripemd160 = teleTrusTRSAsignatureAlgorithm.branch("2");
+ /** 1.3.36.3.3.1.3 */
+ static final ASN1ObjectIdentifier rsaSignatureWithripemd128 = teleTrusTRSAsignatureAlgorithm.branch("3");
+ /** 1.3.36.3.3.1.4 */
+ static final ASN1ObjectIdentifier rsaSignatureWithripemd256 = teleTrusTRSAsignatureAlgorithm.branch("4");
- static final ASN1ObjectIdentifier ecSign = teleTrusTAlgorithm.branch("3.2");
+ /** 1.3.36.3.3.2 */
+ static final ASN1ObjectIdentifier ecSign = teleTrusTAlgorithm.branch("3.2");
- static final ASN1ObjectIdentifier ecSignWithSha1 = ecSign.branch("1");
+ /** 1.3.36.3.3.2,1 */
+ static final ASN1ObjectIdentifier ecSignWithSha1 = ecSign.branch("1");
+ /** 1.3.36.3.3.2.2 */
static final ASN1ObjectIdentifier ecSignWithRipemd160 = ecSign.branch("2");
+ /** 1.3.36.3.3.2.8 */
static final ASN1ObjectIdentifier ecc_brainpool = teleTrusTAlgorithm.branch("3.2.8");
+ /** 1.3.36.3.3.2.8.1 */
static final ASN1ObjectIdentifier ellipticCurve = ecc_brainpool.branch("1");
+ /** 1.3.36.3.3.2.8.1 */
static final ASN1ObjectIdentifier versionOne = ellipticCurve.branch("1");
+ /** 1.3.36.3.3.2.8.1.1 */
static final ASN1ObjectIdentifier brainpoolP160r1 = versionOne.branch("1");
+ /** 1.3.36.3.3.2.8.1.2 */
static final ASN1ObjectIdentifier brainpoolP160t1 = versionOne.branch("2");
+ /** 1.3.36.3.3.2.8.1.3 */
static final ASN1ObjectIdentifier brainpoolP192r1 = versionOne.branch("3");
+ /** 1.3.36.3.3.2.8.1.4 */
static final ASN1ObjectIdentifier brainpoolP192t1 = versionOne.branch("4");
+ /** 1.3.36.3.3.2.8.1.5 */
static final ASN1ObjectIdentifier brainpoolP224r1 = versionOne.branch("5");
+ /** 1.3.36.3.3.2.8.1.6 */
static final ASN1ObjectIdentifier brainpoolP224t1 = versionOne.branch("6");
+ /** 1.3.36.3.3.2.8.1.7 */
static final ASN1ObjectIdentifier brainpoolP256r1 = versionOne.branch("7");
+ /** 1.3.36.3.3.2.8.1.8 */
static final ASN1ObjectIdentifier brainpoolP256t1 = versionOne.branch("8");
+ /** 1.3.36.3.3.2.8.1.9 */
static final ASN1ObjectIdentifier brainpoolP320r1 = versionOne.branch("9");
+ /** 1.3.36.3.3.2.8.1.10 */
static final ASN1ObjectIdentifier brainpoolP320t1 = versionOne.branch("10");
+ /** 1.3.36.3.3.2.8.1.11 */
static final ASN1ObjectIdentifier brainpoolP384r1 = versionOne.branch("11");
+ /** 1.3.36.3.3.2.8.1.12 */
static final ASN1ObjectIdentifier brainpoolP384t1 = versionOne.branch("12");
+ /** 1.3.36.3.3.2.8.1.13 */
static final ASN1ObjectIdentifier brainpoolP512r1 = versionOne.branch("13");
+ /** 1.3.36.3.3.2.8.1.14 */
static final ASN1ObjectIdentifier brainpoolP512t1 = versionOne.branch("14");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/package.html
deleted file mode 100644
index 86606c3..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes for TeleTrust related objects.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/tsp/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/tsp/package.html
deleted file mode 100644
index d6265f0..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/tsp/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting Time Stamp Protocol as described RFC 3161.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java
index 353c196..312bacb 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java
@@ -34,16 +34,16 @@ public class DSTU4145NamedCurves
curves[9] = new ECCurve.F2m(431, 1, 3, 5, ONE, new BigInteger("03CE10490F6A708FC26DFE8C3D27C4F94E690134D5BFF988D8D28AAEAEDE975936C66BAC536B18AE2DC312CA493117DAA469C640CAF3", 16));
ECPoint[] points = new ECPoint[10];
- points[0] = curves[0].createPoint(new BigInteger("2E2F85F5DD74CE983A5C4237229DAF8A3F35823BE", 16), new BigInteger("3826F008A8C51D7B95284D9D03FF0E00CE2CD723A", 16), false);
- points[1] = curves[1].createPoint(new BigInteger("7A1F6653786A68192803910A3D30B2A2018B21CD54", 16), new BigInteger("5F49EB26781C0EC6B8909156D98ED435E45FD59918", 16), false);
- points[2] = curves[2].createPoint(new BigInteger("4D41A619BCC6EADF0448FA22FAD567A9181D37389CA", 16), new BigInteger("10B51CC12849B234C75E6DD2028BF7FF5C1CE0D991A1", 16), false);
- points[3] = curves[3].createPoint(new BigInteger("6BA06FE51464B2BD26DC57F48819BA9954667022C7D03", 16), new BigInteger("25FBC363582DCEC065080CA8287AAFF09788A66DC3A9E", 16), false);
- points[4] = curves[4].createPoint(new BigInteger("714114B762F2FF4A7912A6D2AC58B9B5C2FCFE76DAEB7129", 16), new BigInteger("29C41E568B77C617EFE5902F11DB96FA9613CD8D03DB08DA", 16), false);
- points[5] = curves[5].createPoint(new BigInteger("3FCDA526B6CDF83BA1118DF35B3C31761D3545F32728D003EEB25EFE96", 16), new BigInteger("9CA8B57A934C54DEEDA9E54A7BBAD95E3B2E91C54D32BE0B9DF96D8D35", 16), false);
- points[6] = curves[6].createPoint(new BigInteger("02A29EF207D0E9B6C55CD260B306C7E007AC491CA1B10C62334A9E8DCD8D20FB7", 16), new BigInteger("10686D41FF744D4449FCCF6D8EEA03102E6812C93A9D60B978B702CF156D814EF", 16), false);
- points[7] = curves[7].createPoint(new BigInteger("216EE8B189D291A0224984C1E92F1D16BF75CCD825A087A239B276D3167743C52C02D6E7232AA", 16), new BigInteger("5D9306BACD22B7FAEB09D2E049C6E2866C5D1677762A8F2F2DC9A11C7F7BE8340AB2237C7F2A0", 16), false);
- points[8] = curves[8].createPoint(new BigInteger("324A6EDDD512F08C49A99AE0D3F961197A76413E7BE81A400CA681E09639B5FE12E59A109F78BF4A373541B3B9A1", 16), new BigInteger("1AB597A5B4477F59E39539007C7F977D1A567B92B043A49C6B61984C3FE3481AAF454CD41BA1F051626442B3C10", 16), false);
- points[9] = curves[9].createPoint(new BigInteger("1A62BA79D98133A16BBAE7ED9A8E03C32E0824D57AEF72F88986874E5AAE49C27BED49A2A95058068426C2171E99FD3B43C5947C857D", 16), new BigInteger("70B5E1E14031C1F70BBEFE96BDDE66F451754B4CA5F48DA241F331AA396B8D1839A855C1769B1EA14BA53308B5E2723724E090E02DB9", 16), false);
+ points[0] = curves[0].createPoint(new BigInteger("2E2F85F5DD74CE983A5C4237229DAF8A3F35823BE", 16), new BigInteger("3826F008A8C51D7B95284D9D03FF0E00CE2CD723A", 16));
+ points[1] = curves[1].createPoint(new BigInteger("7A1F6653786A68192803910A3D30B2A2018B21CD54", 16), new BigInteger("5F49EB26781C0EC6B8909156D98ED435E45FD59918", 16));
+ points[2] = curves[2].createPoint(new BigInteger("4D41A619BCC6EADF0448FA22FAD567A9181D37389CA", 16), new BigInteger("10B51CC12849B234C75E6DD2028BF7FF5C1CE0D991A1", 16));
+ points[3] = curves[3].createPoint(new BigInteger("6BA06FE51464B2BD26DC57F48819BA9954667022C7D03", 16), new BigInteger("25FBC363582DCEC065080CA8287AAFF09788A66DC3A9E", 16));
+ points[4] = curves[4].createPoint(new BigInteger("714114B762F2FF4A7912A6D2AC58B9B5C2FCFE76DAEB7129", 16), new BigInteger("29C41E568B77C617EFE5902F11DB96FA9613CD8D03DB08DA", 16));
+ points[5] = curves[5].createPoint(new BigInteger("3FCDA526B6CDF83BA1118DF35B3C31761D3545F32728D003EEB25EFE96", 16), new BigInteger("9CA8B57A934C54DEEDA9E54A7BBAD95E3B2E91C54D32BE0B9DF96D8D35", 16));
+ points[6] = curves[6].createPoint(new BigInteger("02A29EF207D0E9B6C55CD260B306C7E007AC491CA1B10C62334A9E8DCD8D20FB7", 16), new BigInteger("10686D41FF744D4449FCCF6D8EEA03102E6812C93A9D60B978B702CF156D814EF", 16));
+ points[7] = curves[7].createPoint(new BigInteger("216EE8B189D291A0224984C1E92F1D16BF75CCD825A087A239B276D3167743C52C02D6E7232AA", 16), new BigInteger("5D9306BACD22B7FAEB09D2E049C6E2866C5D1677762A8F2F2DC9A11C7F7BE8340AB2237C7F2A0", 16));
+ points[8] = curves[8].createPoint(new BigInteger("324A6EDDD512F08C49A99AE0D3F961197A76413E7BE81A400CA681E09639B5FE12E59A109F78BF4A373541B3B9A1", 16), new BigInteger("1AB597A5B4477F59E39539007C7F977D1A567B92B043A49C6B61984C3FE3481AAF454CD41BA1F051626442B3C10", 16));
+ points[9] = curves[9].createPoint(new BigInteger("1A62BA79D98133A16BBAE7ED9A8E03C32E0824D57AEF72F88986874E5AAE49C27BED49A2A95058068426C2171E99FD3B43C5947C857D", 16), new BigInteger("70B5E1E14031C1F70BBEFE96BDDE66F451754B4CA5F48DA241F331AA396B8D1839A855C1769B1EA14BA53308B5E2723724E090E02DB9", 16));
BigInteger[] n_s = new BigInteger[10];
n_s[0] = new BigInteger("400000000000000000002BEC12BE2262D39BCF14D", 16);
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java b/bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java
index 0227d2a..8c16620 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java
@@ -3,7 +3,6 @@ package org.bouncycastle.asn1.ua;
import java.math.BigInteger;
import java.util.Random;
-import org.bouncycastle.asn1.x9.X9IntegerConverter;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
@@ -14,12 +13,8 @@ import org.bouncycastle.util.Arrays;
* DSTU4145 encodes points somewhat differently than X9.62
* It compresses the point to the size of the field element
*/
-
public abstract class DSTU4145PointEncoder
{
-
- private static X9IntegerConverter converter = new X9IntegerConverter();
-
private static BigInteger trace(ECFieldElement fe)
{
ECFieldElement t = fe;
@@ -38,26 +33,23 @@ public abstract class DSTU4145PointEncoder
* @return the solution for <code>z<sup>2</sup> + z = beta</code> or
* <code>null</code> if no solution exists.
*/
- private static ECFieldElement solveQuadradicEquation(ECFieldElement beta)
+ private static ECFieldElement solveQuadraticEquation(ECCurve curve, ECFieldElement beta)
{
- ECFieldElement.F2m b = (ECFieldElement.F2m)beta;
- ECFieldElement zeroElement = new ECFieldElement.F2m(
- b.getM(), b.getK1(), b.getK2(), b.getK3(), ECConstants.ZERO);
-
- if (beta.toBigInteger().equals(ECConstants.ZERO))
+ if (beta.isZero())
{
- return zeroElement;
+ return beta;
}
+ ECFieldElement zeroElement = curve.fromBigInteger(ECConstants.ZERO);
+
ECFieldElement z = null;
- ECFieldElement gamma = zeroElement;
+ ECFieldElement gamma = null;
Random rand = new Random();
- int m = b.getM();
+ int m = beta.getFieldSize();
do
{
- ECFieldElement t = new ECFieldElement.F2m(b.getM(), b.getK1(),
- b.getK2(), b.getK3(), new BigInteger(m, rand));
+ ECFieldElement t = curve.fromBigInteger(new BigInteger(m, rand));
z = zeroElement;
ECFieldElement w = beta;
for (int i = 1; i <= m - 1; i++)
@@ -66,13 +58,13 @@ public abstract class DSTU4145PointEncoder
z = z.square().add(w2.multiply(t));
w = w2.add(beta);
}
- if (!w.toBigInteger().equals(ECConstants.ZERO))
+ if (!w.isZero())
{
return null;
}
gamma = z.square().add(z);
}
- while (gamma.toBigInteger().equals(ECConstants.ZERO));
+ while (gamma.isZero());
return z;
}
@@ -91,12 +83,15 @@ public abstract class DSTU4145PointEncoder
return Arrays.copyOfRange(bytes, 1, bytes.length);*/
- int byteCount = converter.getByteLength(Q.getX());
- byte[] bytes = converter.integerToBytes(Q.getX().toBigInteger(), byteCount);
+ Q = Q.normalize();
+
+ ECFieldElement x = Q.getAffineXCoord();
+
+ byte[] bytes = x.getEncoded();
- if (!(Q.getX().toBigInteger().equals(ECConstants.ZERO)))
+ if (!x.isZero())
{
- ECFieldElement y = Q.getY().multiply(Q.getX().invert());
+ ECFieldElement y = Q.getAffineYCoord().divide(x);
if (trace(y).equals(ECConstants.ONE))
{
bytes[bytes.length - 1] |= 0x01;
@@ -129,13 +124,12 @@ public abstract class DSTU4145PointEncoder
bytes = Arrays.clone(bytes);
bytes[bytes.length - 1] ^= 0x01;
}
- ECCurve.F2m c = (ECCurve.F2m)curve;
ECFieldElement xp = curve.fromBigInteger(new BigInteger(1, bytes));
ECFieldElement yp = null;
- if (xp.toBigInteger().equals(ECConstants.ZERO))
+ if (xp.isZero())
{
yp = (ECFieldElement.F2m)curve.getB();
- for (int i = 0; i < c.getM() - 1; i++)
+ for (int i = 0; i < curve.getFieldSize() - 1; i++)
{
yp = yp.square();
}
@@ -144,14 +138,14 @@ public abstract class DSTU4145PointEncoder
{
ECFieldElement beta = xp.add(curve.getA()).add(
curve.getB().multiply(xp.square().invert()));
- ECFieldElement z = solveQuadradicEquation(beta);
+ ECFieldElement z = solveQuadraticEquation(curve, beta);
if (z == null)
{
throw new RuntimeException("Invalid point compression");
}
if (!trace(z).equals(k))
{
- z = z.add(curve.fromBigInteger(ECConstants.ONE));
+ z = z.addOne();
}
yp = xp.multiply(z);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java
index 046bc6f..ccdb34e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java
@@ -2,15 +2,22 @@ package org.bouncycastle.asn1.ua;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * Ukrainian object identifiers
+ * <p>
+ * {iso(1) member-body(2) Ukraine(804) root(2) security(1) cryptography(1) pki(1)}
+ * <p>
+ * { ... pki-alg(1) pki-alg-sym(3) Dstu4145WithGost34311(1) PB(1)}
+ * <p>
+ * DSTU4145 in polynomial basis has 2 oids, one for little-endian representation and one for big-endian
+ */
public interface UAObjectIdentifiers
{
- // Ukrainian object identifiers
- // {iso(1) member-body(2) Ukraine(804 ) root(2) security(1) cryptography(1) pki(1)}
-
+ /** Base OID: 1.2.804.2.1.1.1 */
static final ASN1ObjectIdentifier UaOid = new ASN1ObjectIdentifier("1.2.804.2.1.1.1");
- // {pki-alg(1) pki-alg-�sym(3) Dstu4145WithGost34311(1) PB(1)}
- // DSTU4145 in polynomial basis has 2 oids, one for little-endian representation and one for big-endian
+ /** DSTU4145 Little Endian presentation. OID: 1.2.804.2.1.1.1.1.3.1.1 */
static final ASN1ObjectIdentifier dstu4145le = UaOid.branch("1.3.1.1");
+ /** DSTU4145 Big Endian presentation. OID: 1.2.804.2.1.1.1.1.3.1.1.1 */
static final ASN1ObjectIdentifier dstu4145be = UaOid.branch("1.3.1.1.1.1");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/util/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/util/package.html
deleted file mode 100644
index 1db893d..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/util/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-An ASN.1 dump utility.
-</body>
-</html>
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 714a32c..6842182 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java
@@ -1,6 +1,7 @@
package org.bouncycastle.asn1.x500.style;
import java.io.IOException;
+import java.util.Enumeration;
import java.util.Hashtable;
import org.bouncycastle.asn1.ASN1Encodable;
@@ -19,8 +20,6 @@ import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
public class BCStyle
implements X500NameStyle
{
- public static final X500NameStyle INSTANCE = new BCStyle();
-
/**
* country code - StringType(SIZE(2))
*/
@@ -273,9 +272,18 @@ public class BCStyle
DefaultLookUp.put("name", NAME);
}
+ /**
+ * Singleton instance.
+ */
+ public static final X500NameStyle INSTANCE = new BCStyle();
+
+ protected final Hashtable defaultLookUp;
+ protected final Hashtable defaultSymbols;
+
protected BCStyle()
{
-
+ defaultSymbols = copyHashTable(DefaultSymbols);
+ defaultLookUp = copyHashTable(DefaultLookUp);
}
public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
@@ -322,12 +330,12 @@ public class BCStyle
public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
{
- return IETFUtils.findAttrNamesForOID(oid, DefaultLookUp);
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
}
public ASN1ObjectIdentifier attrNameToOID(String attrName)
{
- return IETFUtils.decodeAttrName(attrName, DefaultLookUp);
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
}
public boolean areEqual(X500Name name1, X500Name name2)
@@ -451,9 +459,23 @@ public class BCStyle
buf.append(',');
}
- IETFUtils.appendRDN(buf, rdns[i], DefaultSymbols);
+ IETFUtils.appendRDN(buf, rdns[i], defaultSymbols);
}
return buf.toString();
}
+
+ private static Hashtable copyHashTable(Hashtable paramsMap)
+ {
+ Hashtable newTable = new Hashtable();
+
+ Enumeration keys = paramsMap.keys();
+ while (keys.hasMoreElements())
+ {
+ Object key = keys.nextElement();
+ newTable.put(key, paramsMap.get(key));
+ }
+
+ return newTable;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
index c73107e..b4f1794 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
@@ -405,7 +405,7 @@ public class IETFUtils
int start = 0;
if (vBuf.length() > 0)
{
- while (vBuf.charAt(start) == ' ')
+ while (vBuf.length() > start && vBuf.charAt(start) == ' ')
{
vBuf.insert(start, "\\");
start += 2;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
index 8486989..8c92257 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/RFC4519Style.java
@@ -1,6 +1,7 @@
package org.bouncycastle.asn1.x500.style;
import java.io.IOException;
+import java.util.Enumeration;
import java.util.Hashtable;
import org.bouncycastle.asn1.ASN1Encodable;
@@ -16,8 +17,6 @@ import org.bouncycastle.asn1.x500.X500NameStyle;
public class RFC4519Style
implements X500NameStyle
{
- public static final X500NameStyle INSTANCE = new RFC4519Style();
-
public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15");
public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6");
public static final ASN1ObjectIdentifier cn = new ASN1ObjectIdentifier("2.5.4.3");
@@ -166,9 +165,18 @@ public class RFC4519Style
// TODO: need to add correct matching for equality comparisons.
}
+ /**
+ * Singleton instance.
+ */
+ public static final X500NameStyle INSTANCE = new RFC4519Style();
+
+ protected final Hashtable defaultLookUp;
+ protected final Hashtable defaultSymbols;
+
protected RFC4519Style()
{
-
+ defaultSymbols = copyHashTable(DefaultSymbols);
+ defaultLookUp = copyHashTable(DefaultLookUp);
}
public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
@@ -211,12 +219,12 @@ public class RFC4519Style
public String[] oidToAttrNames(ASN1ObjectIdentifier oid)
{
- return IETFUtils.findAttrNamesForOID(oid, DefaultLookUp);
+ return IETFUtils.findAttrNamesForOID(oid, defaultLookUp);
}
public ASN1ObjectIdentifier attrNameToOID(String attrName)
{
- return IETFUtils.decodeAttrName(attrName, DefaultLookUp);
+ return IETFUtils.decodeAttrName(attrName, defaultLookUp);
}
public boolean areEqual(X500Name name1, X500Name name2)
@@ -350,9 +358,23 @@ public class RFC4519Style
buf.append(',');
}
- IETFUtils.appendRDN(buf, rdns[i], DefaultSymbols);
+ IETFUtils.appendRDN(buf, rdns[i], defaultSymbols);
}
return buf.toString();
}
+
+ private static Hashtable copyHashTable(Hashtable paramsMap)
+ {
+ Hashtable newTable = new Hashtable();
+
+ Enumeration keys = paramsMap.keys();
+ while (keys.hasMoreElements())
+ {
+ Object key = keys.nextElement();
+ newTable.put(key, paramsMap.get(key));
+ }
+
+ return newTable;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java
index 92aa0f7..73fe7b4 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificate.java
@@ -41,7 +41,10 @@ public class AttributeCertificate
this.signatureAlgorithm = signatureAlgorithm;
this.signatureValue = signatureValue;
}
-
+
+ /**
+ * @deprecated use getInstance() method.
+ */
public AttributeCertificate(
ASN1Sequence seq)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
index 7b9d450..ae539f4 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
@@ -13,7 +13,7 @@ import org.bouncycastle.asn1.DERSequence;
public class AttributeCertificateInfo
extends ASN1Object
{
- private ASN1Integer version;
+ private ASN1Integer version;
private Holder holder;
private AttCertIssuer issuer;
private AlgorithmIdentifier signature;
@@ -48,22 +48,33 @@ public class AttributeCertificateInfo
private AttributeCertificateInfo(
ASN1Sequence seq)
{
- if (seq.size() < 7 || seq.size() > 9)
+ if (seq.size() < 6 || seq.size() > 9)
{
throw new IllegalArgumentException("Bad sequence size: " + seq.size());
}
- this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
- this.holder = Holder.getInstance(seq.getObjectAt(1));
- this.issuer = AttCertIssuer.getInstance(seq.getObjectAt(2));
- this.signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(3));
- this.serialNumber = ASN1Integer.getInstance(seq.getObjectAt(4));
- this.attrCertValidityPeriod = AttCertValidityPeriod.getInstance(seq.getObjectAt(5));
- this.attributes = ASN1Sequence.getInstance(seq.getObjectAt(6));
+ int start;
+ if (seq.getObjectAt(0) instanceof ASN1Integer) // in version 1 certs version is DEFAULT v1(0)
+ {
+ this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ start = 1;
+ }
+ else
+ {
+ this.version = new ASN1Integer(0);
+ start = 0;
+ }
+
+ this.holder = Holder.getInstance(seq.getObjectAt(start));
+ this.issuer = AttCertIssuer.getInstance(seq.getObjectAt(start + 1));
+ this.signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(start + 2));
+ this.serialNumber = ASN1Integer.getInstance(seq.getObjectAt(start + 3));
+ this.attrCertValidityPeriod = AttCertValidityPeriod.getInstance(seq.getObjectAt(start + 4));
+ this.attributes = ASN1Sequence.getInstance(seq.getObjectAt(start + 5));
- for (int i = 7; i < seq.size(); i++)
+ for (int i = start + 6; i < seq.size(); i++)
{
- ASN1Encodable obj = (ASN1Encodable)seq.getObjectAt(i);
+ ASN1Encodable obj = seq.getObjectAt(i);
if (obj instanceof DERBitString)
{
@@ -143,7 +154,10 @@ public class AttributeCertificateInfo
{
ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(version);
+ if (version.getValue().intValue() != 0)
+ {
+ v.add(version);
+ }
v.add(holder);
v.add(issuer);
v.add(signature);
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java
index 91a37ad..61d7d4a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificateList.java
@@ -31,6 +31,8 @@ public class CertificateList
TBSCertList tbsCertList;
AlgorithmIdentifier sigAlgId;
DERBitString sig;
+ boolean isHashCodeSet = false;
+ int hashCodeValue;
public static CertificateList getInstance(
ASN1TaggedObject obj,
@@ -54,6 +56,10 @@ public class CertificateList
return null;
}
+ /**
+ * @deprecated use getInstance() method.
+ * @param seq
+ */
public CertificateList(
ASN1Sequence seq)
{
@@ -124,4 +130,15 @@ public class CertificateList
return new DERSequence(v);
}
+
+ public int hashCode()
+ {
+ if (!isHashCodeSet)
+ {
+ hashCodeValue = super.hashCode();
+ isHashCodeSet = true;
+ }
+
+ return hashCodeValue;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java
index e42cefa..4d7fc0b 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/CertificatePolicies.java
@@ -1,6 +1,7 @@
package org.bouncycastle.asn1.x509;
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;
@@ -35,6 +36,17 @@ public class CertificatePolicies
}
/**
+ * Retrieve a CertificatePolicies for a passed in Extensions object, if present.
+ *
+ * @param extensions the extensions object to be examined.
+ * @return the CertificatePolicies, null if the extension is not present.
+ */
+ public static CertificatePolicies fromExtensions(Extensions extensions)
+ {
+ return CertificatePolicies.getInstance(extensions.getExtensionParsedValue(Extension.certificatePolicies));
+ }
+
+ /**
* Construct a CertificatePolicies object containing one PolicyInformation.
*
* @param name the name to be contained.
@@ -71,6 +83,19 @@ public class CertificatePolicies
return tmp;
}
+ public PolicyInformation getPolicyInformation(ASN1ObjectIdentifier policyIdentifier)
+ {
+ for (int i = 0; i != policyInformation.length; i++)
+ {
+ if (policyIdentifier.equals(policyInformation[i].getPolicyIdentifier()))
+ {
+ return policyInformation[i];
+ }
+ }
+
+ return null;
+ }
+
/**
* Produce an object suitable for an ASN1OutputStream.
* <pre>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
index dcc1b1f..84d21ca 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
@@ -25,6 +25,13 @@ public class ExtendedKeyUsage
Hashtable usageTable = new Hashtable();
ASN1Sequence seq;
+ /**
+ * Return an ExtendedKeyUsage from the passed in tagged object.
+ *
+ * @param obj the tagged object containing the ExtendedKeyUsage
+ * @param explicit true if the tagged object should be interpreted as explicitly tagged, false if implicit.
+ * @return the ExtendedKeyUsage contained.
+ */
public static ExtendedKeyUsage getInstance(
ASN1TaggedObject obj,
boolean explicit)
@@ -32,6 +39,12 @@ public class ExtendedKeyUsage
return getInstance(ASN1Sequence.getInstance(obj, explicit));
}
+ /**
+ * Return an ExtendedKeyUsage from the passed in object.
+ *
+ * @param obj an ExtendedKeyUsage, some form or encoding of one, or null.
+ * @return an ExtendedKeyUsage object, or null if null is passed in.
+ */
public static ExtendedKeyUsage getInstance(
Object obj)
{
@@ -47,11 +60,22 @@ public class ExtendedKeyUsage
return null;
}
+ /**
+ * Retrieve an ExtendedKeyUsage for a passed in Extensions object, if present.
+ *
+ * @param extensions the extensions object to be examined.
+ * @return the ExtendedKeyUsage, null if the extension is not present.
+ */
public static ExtendedKeyUsage fromExtensions(Extensions extensions)
{
return ExtendedKeyUsage.getInstance(extensions.getExtensionParsedValue(Extension.extendedKeyUsage));
}
+ /**
+ * Base constructor, from a single KeyPurposeId.
+ *
+ * @param usage the keyPurposeId to be included.
+ */
public ExtendedKeyUsage(
KeyPurposeId usage)
{
@@ -78,6 +102,11 @@ public class ExtendedKeyUsage
}
}
+ /**
+ * Base constructor, from multiple KeyPurposeIds.
+ *
+ * @param usages an array of KeyPurposeIds.
+ */
public ExtendedKeyUsage(
KeyPurposeId[] usages)
{
@@ -103,7 +132,7 @@ public class ExtendedKeyUsage
while (e.hasMoreElements())
{
- ASN1Primitive o = (ASN1Primitive)e.nextElement();
+ KeyPurposeId o = KeyPurposeId.getInstance(e.nextElement());
v.add(o);
this.usageTable.put(o, o);
@@ -112,6 +141,12 @@ public class ExtendedKeyUsage
this.seq = new DERSequence(v);
}
+ /**
+ * Return true if this ExtendedKeyUsage object contains the passed in keyPurposeId.
+ *
+ * @param keyPurposeId the KeyPurposeId of interest.
+ * @return true if the keyPurposeId is present, false otherwise.
+ */
public boolean hasKeyPurposeId(
KeyPurposeId keyPurposeId)
{
@@ -120,7 +155,7 @@ public class ExtendedKeyUsage
/**
* Returns all extended key usages.
- * The returned vector contains DERObjectIdentifiers.
+ *
* @return An array with all key purposes.
*/
public KeyPurposeId[] getUsages()
@@ -135,11 +170,21 @@ public class ExtendedKeyUsage
return temp;
}
+ /**
+ * Return the number of KeyPurposeIds present in this ExtendedKeyUsage.
+ *
+ * @return the number of KeyPurposeIds
+ */
public int size()
{
return usageTable.size();
}
-
+
+ /**
+ * Return the ASN.1 primitive form of this object.
+ *
+ * @return an ASN1Sequence.
+ */
public ASN1Primitive toASN1Primitive()
{
return seq;
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java
index 6ae6e35..e854681 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Holder.java
@@ -31,9 +31,9 @@ import org.bouncycastle.asn1.DERTaggedObject;
*
* <pre>
* subject CHOICE {
- * baseCertificateID [0] IssuerSerial,
+ * baseCertificateID [0] EXPLICIT IssuerSerial,
* -- associated with a Public Key Certificate
- * subjectName [1] GeneralNames },
+ * subjectName [1] EXPLICIT GeneralNames },
* -- associated with a name
* </pre>
*/
@@ -79,10 +79,10 @@ public class Holder
switch (tagObj.getTagNo())
{
case 0:
- baseCertificateID = IssuerSerial.getInstance(tagObj, false);
+ baseCertificateID = IssuerSerial.getInstance(tagObj, true);
break;
case 1:
- entityName = GeneralNames.getInstance(tagObj, false);
+ entityName = GeneralNames.getInstance(tagObj, true);
break;
default:
throw new IllegalArgumentException("unknown tag in Holder");
@@ -234,11 +234,11 @@ public class Holder
{
if (entityName != null)
{
- return new DERTaggedObject(false, 1, entityName);
+ return new DERTaggedObject(true, 1, entityName);
}
else
{
- return new DERTaggedObject(false, 0, baseCertificateID);
+ return new DERTaggedObject(true, 0, baseCertificateID);
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java
index 8d3036b..fefc939 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/IssuerSerial.java
@@ -10,6 +10,7 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.x500.X500Name;
public class IssuerSerial
extends ASN1Object
@@ -59,6 +60,13 @@ public class IssuerSerial
}
public IssuerSerial(
+ X500Name issuer,
+ BigInteger serial)
+ {
+ this(new GeneralNames(new GeneralName(issuer)), new ASN1Integer(serial));
+ }
+
+ public IssuerSerial(
GeneralNames issuer,
BigInteger serial)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java
index 2943c0b..d4456b7 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyUsage.java
@@ -74,6 +74,17 @@ public class KeyUsage
this.bitString = bitString;
}
+ /**
+ * Return true if a given usage bit is set, false otherwise.
+ *
+ * @param usages combination of usage flags.
+ * @return true if all bits are set, false otherwise.
+ */
+ public boolean hasUsages(int usages)
+ {
+ return (bitString.intValue() & usages) == usages;
+ }
+
public byte[] getBytes()
{
return bitString.getBytes();
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java
new file mode 100644
index 0000000..aeb53f0
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java
@@ -0,0 +1,106 @@
+package org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1Object;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * PKIX RFC 5280
+ * <pre>
+ * id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 }
+ *
+ * PolicyConstraints ::= SEQUENCE {
+ * requireExplicitPolicy [0] SkipCerts OPTIONAL,
+ * inhibitPolicyMapping [1] SkipCerts OPTIONAL }
+ *
+ * SkipCerts ::= INTEGER (0..MAX)
+ * </pre>
+ */
+public class PolicyConstraints
+ extends ASN1Object
+{
+ private BigInteger requireExplicitPolicyMapping;
+ private BigInteger inhibitPolicyMapping;
+
+ public PolicyConstraints(BigInteger requireExplicitPolicyMapping, BigInteger inhibitPolicyMapping)
+ {
+ this.requireExplicitPolicyMapping = requireExplicitPolicyMapping;
+ this.inhibitPolicyMapping = inhibitPolicyMapping;
+ }
+
+ private PolicyConstraints(ASN1Sequence seq)
+ {
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject to = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+
+ if (to.getTagNo() == 0)
+ {
+ requireExplicitPolicyMapping = ASN1Integer.getInstance(to, false).getValue();
+ }
+ else if (to.getTagNo() == 1)
+ {
+ inhibitPolicyMapping = ASN1Integer.getInstance(to, false).getValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Unknown tag encountered.");
+ }
+ }
+ }
+
+ public static PolicyConstraints getInstance(
+ Object obj)
+ {
+ if (obj instanceof PolicyConstraints)
+ {
+ return (PolicyConstraints)obj;
+ }
+
+ if (obj != null)
+ {
+ return new PolicyConstraints(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static PolicyConstraints fromExtensions(Extensions extensions)
+ {
+ return PolicyConstraints.getInstance(extensions.getExtensionParsedValue(Extension.policyConstraints));
+ }
+
+ public BigInteger getRequireExplicitPolicyMapping()
+ {
+ return requireExplicitPolicyMapping;
+ }
+
+ public BigInteger getInhibitPolicyMapping()
+ {
+ return inhibitPolicyMapping;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (requireExplicitPolicyMapping != null)
+ {
+ v.add(new DERTaggedObject(0, new ASN1Integer(requireExplicitPolicyMapping)));
+ }
+
+ if (inhibitPolicyMapping != null)
+ {
+ v.add(new DERTaggedObject(1, new ASN1Integer(inhibitPolicyMapping)));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java
index 295accf..fe09169 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java
@@ -57,7 +57,8 @@ public class PolicyQualifierInfo
* Creates a new <code>PolicyQualifierInfo</code> instance.
*
* @param as <code>PolicyQualifierInfo</code> X509 structure
- * encoded as an ASN1Sequence.
+ * encoded as an ASN1Sequence.
+ * @deprecated use PolicyQualifierInfo.getInstance()
*/
public PolicyQualifierInfo(
ASN1Sequence as)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
index f020bcb..f29284d 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Extension.java
@@ -10,6 +10,7 @@ import org.bouncycastle.asn1.DERBoolean;
/**
* an object for the elements in the X.509 V3 extension block.
+ * @deprecated use Extension
*/
public class X509Extension
{
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java
index af2c9a9..ff7af8c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509Name.java
@@ -1238,49 +1238,47 @@ public class X509Name
buf.append('=');
- int index = buf.length();
- int start = index;
-
+ int start = buf.length();
buf.append(value);
-
- int end = buf.length();
+ int end = buf.length();
if (value.length() >= 2 && value.charAt(0) == '\\' && value.charAt(1) == '#')
{
- index += 2;
- }
-
- while (index != end)
- {
- if ((buf.charAt(index) == ',')
- || (buf.charAt(index) == '"')
- || (buf.charAt(index) == '\\')
- || (buf.charAt(index) == '+')
- || (buf.charAt(index) == '=')
- || (buf.charAt(index) == '<')
- || (buf.charAt(index) == '>')
- || (buf.charAt(index) == ';'))
- {
- buf.insert(index, "\\");
- index++;
- end++;
- }
-
- index++;
+ start += 2;
}
- while (buf.charAt(start) == ' ')
+ while (start < end && buf.charAt(start) == ' ')
{
buf.insert(start, "\\");
start += 2;
+ ++end;
}
- int endBuf = buf.length() - 1;
+ while (--end > start && buf.charAt(end) == ' ')
+ {
+ buf.insert(end, '\\');
+ }
- while (endBuf >= 0 && buf.charAt(endBuf) == ' ')
+ while (start <= end)
{
- buf.insert(endBuf, '\\');
- endBuf--;
+ switch (buf.charAt(start))
+ {
+ case ',':
+ case '"':
+ case '\\':
+ case '+':
+ case '=':
+ case '<':
+ case '>':
+ case ';':
+ buf.insert(start, "\\");
+ start += 2;
+ ++end;
+ break;
+ default:
+ ++start;
+ break;
+ }
}
}
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 ed4dd32..e1c7a54 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
@@ -4,64 +4,78 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
public interface X509ObjectIdentifiers
{
- //
- // base id
- //
- static final String id = "2.5.4";
-
- static final ASN1ObjectIdentifier commonName = new ASN1ObjectIdentifier(id + ".3");
- static final ASN1ObjectIdentifier countryName = new ASN1ObjectIdentifier(id + ".6");
- static final ASN1ObjectIdentifier localityName = new ASN1ObjectIdentifier(id + ".7");
- static final ASN1ObjectIdentifier stateOrProvinceName = new ASN1ObjectIdentifier(id + ".8");
- static final ASN1ObjectIdentifier organization = new ASN1ObjectIdentifier(id + ".10");
- static final ASN1ObjectIdentifier organizationalUnitName = new ASN1ObjectIdentifier(id + ".11");
+
+ /** Subject RDN components: commonName = 2.5.4.3 */
+ static final ASN1ObjectIdentifier commonName = new ASN1ObjectIdentifier("2.5.4.3");
+ /** Subject RDN components: countryName = 2.5.4.6 */
+ static final ASN1ObjectIdentifier countryName = new ASN1ObjectIdentifier("2.5.4.6");
+ /** Subject RDN components: localityName = 2.5.4.7 */
+ static final ASN1ObjectIdentifier localityName = new ASN1ObjectIdentifier("2.5.4.7");
+ /** Subject RDN components: stateOrProvinceName = 2.5.4.8 */
+ static final ASN1ObjectIdentifier stateOrProvinceName = new ASN1ObjectIdentifier("2.5.4.8");
+ /** Subject RDN components: organization = 2.5.4.10 */
+ static final ASN1ObjectIdentifier organization = new ASN1ObjectIdentifier("2.5.4.10");
+ /** Subject RDN components: organizationalUnitName = 2.5.4.11 */
+ static final ASN1ObjectIdentifier organizationalUnitName = new ASN1ObjectIdentifier("2.5.4.11");
+ /** Subject RDN components: telephone_number = 2.5.4.20 */
static final ASN1ObjectIdentifier id_at_telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20");
- static final ASN1ObjectIdentifier id_at_name = new ASN1ObjectIdentifier(id + ".41");
+ /** Subject RDN components: name = 2.5.4.41 */
+ static final ASN1ObjectIdentifier id_at_name = new ASN1ObjectIdentifier("2.5.4.41");
- // id-SHA1 OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
+ /**
+ * id-SHA1 OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }
+ * <p>
+ * OID: 1.3.14.3.2.27
+ */
static final ASN1ObjectIdentifier id_SHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.26");
- //
- // ripemd160 OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RIPEMD-160(1)}
- //
+ /**
+ * ripemd160 OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RIPEMD-160(1)}
+ * <p>
+ * OID: 1.3.36.3.2.1
+ */
static final ASN1ObjectIdentifier ripemd160 = new ASN1ObjectIdentifier("1.3.36.3.2.1");
- //
- // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
- // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
- //
+ /**
+ * ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
+ * {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
+ * <p>
+ * OID: 1.3.36.3.3.1.2
+ */
static final ASN1ObjectIdentifier ripemd160WithRSAEncryption = new ASN1ObjectIdentifier("1.3.36.3.3.1.2");
+ /** OID: 2.5.8.1.1 */
static final ASN1ObjectIdentifier id_ea_rsa = new ASN1ObjectIdentifier("2.5.8.1.1");
- // id-pkix
- static final ASN1ObjectIdentifier id_pkix = new ASN1ObjectIdentifier("1.3.6.1.5.5.7");
+ /** id-pkix OID: 1.3.6.1.5.5.7
+ */
+ static final ASN1ObjectIdentifier id_pkix = new ASN1ObjectIdentifier("1.3.6.1.5.5.7");
- //
- // private internet extensions
- //
- static final ASN1ObjectIdentifier id_pe = new ASN1ObjectIdentifier(id_pkix + ".1");
+ /**
+ * private internet extensions; OID = 1.3.6.1.5.5.7.1
+ */
+ static final ASN1ObjectIdentifier id_pe = id_pkix.branch("1");
- //
- // ISO ARC for standard certificate and CRL extensions
- //
+ /**
+ * ISO ARC for standard certificate and CRL extensions
+ * <p>
+ * OID: 2.5.29
+ */
static final ASN1ObjectIdentifier id_ce = new ASN1ObjectIdentifier("2.5.29");
- //
- // authority information access
- //
- static final ASN1ObjectIdentifier id_ad = new ASN1ObjectIdentifier(id_pkix + ".48");
- static final ASN1ObjectIdentifier id_ad_caIssuers = new ASN1ObjectIdentifier(id_ad + ".2");
- static final ASN1ObjectIdentifier id_ad_ocsp = new ASN1ObjectIdentifier(id_ad + ".1");
+ /** id-pkix OID: 1.3.6.1.5.5.7.48 */
+ static final ASN1ObjectIdentifier id_ad = id_pkix.branch("48");
+ /** id-ad-caIssuers OID: 1.3.6.1.5.5.7.48.2 */
+ static final ASN1ObjectIdentifier id_ad_caIssuers = id_ad.branch("2");
+ /** id-ad-ocsp OID: 1.3.6.1.5.5.7.48.1 */
+ static final ASN1ObjectIdentifier id_ad_ocsp = id_ad.branch("1");
- //
- // OID for ocsp and crl uri in AuthorityInformationAccess extension
- //
+ /** OID for ocsp uri in AuthorityInformationAccess extension */
static final ASN1ObjectIdentifier ocspAccessMethod = id_ad_ocsp;
- static final ASN1ObjectIdentifier crlAccessMethod = id_ad_caIssuers;
+ /** OID for crl uri in AuthorityInformationAccess extension */
+ static final ASN1ObjectIdentifier crlAccessMethod = id_ad_caIssuers;
}
-
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/x509/package.html
deleted file mode 100644
index 728921a..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and processing X.509 certificates.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java
index 19ef12b..22db8cb 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java
@@ -4,13 +4,8 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
public interface ETSIQCObjectIdentifiers
{
- //
- // base id
- //
- static final ASN1ObjectIdentifier id_etsi_qcs = new ASN1ObjectIdentifier("0.4.0.1862.1");
-
- static final ASN1ObjectIdentifier id_etsi_qcs_QcCompliance = id_etsi_qcs.branch("1");
- static final ASN1ObjectIdentifier id_etsi_qcs_LimiteValue = id_etsi_qcs.branch("2");
- static final ASN1ObjectIdentifier id_etsi_qcs_RetentionPeriod = id_etsi_qcs.branch("3");
- static final ASN1ObjectIdentifier id_etsi_qcs_QcSSCD = id_etsi_qcs.branch("4");
+ static final ASN1ObjectIdentifier id_etsi_qcs_QcCompliance = new ASN1ObjectIdentifier("0.4.0.1862.1.1");
+ static final ASN1ObjectIdentifier id_etsi_qcs_LimiteValue = new ASN1ObjectIdentifier("0.4.0.1862.1.2");
+ static final ASN1ObjectIdentifier id_etsi_qcs_RetentionPeriod = new ASN1ObjectIdentifier("0.4.0.1862.1.3");
+ static final ASN1ObjectIdentifier id_etsi_qcs_QcSSCD = new ASN1ObjectIdentifier("0.4.0.1862.1.4");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java
index ecb5cce..0c840bd 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java
@@ -4,11 +4,8 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
public interface RFC3739QCObjectIdentifiers
{
- //
- // base id
- //
- static final ASN1ObjectIdentifier id_qcs = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.11");
-
- static final ASN1ObjectIdentifier id_qcs_pkixQCSyntax_v1 = id_qcs.branch("1");
- static final ASN1ObjectIdentifier id_qcs_pkixQCSyntax_v2 = id_qcs.branch("2");
+ /** OID: 1.3.6.1.5.5.7.11.1 */
+ static final ASN1ObjectIdentifier id_qcs_pkixQCSyntax_v1 = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.11.1");
+ /** OID: 1.3.6.1.5.5.7.11.2 */
+ static final ASN1ObjectIdentifier id_qcs_pkixQCSyntax_v2 = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.11.2");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/package.html
deleted file mode 100644
index 28cfef9..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/qualified/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and processing messages based around RFC3739
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java
index 8cac124..d338614 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java
@@ -8,38 +8,53 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
*/
public interface SigIObjectIdentifiers
{
+ /**
+ * OID: 1.3.36.8
+ */
public final static ASN1ObjectIdentifier id_sigi = new ASN1ObjectIdentifier("1.3.36.8");
/**
* Key purpose IDs for German SigI (Signature Interoperability
* Specification)
+ * <p>
+ * OID: 1.3.36.8.2
*/
- public final static ASN1ObjectIdentifier id_sigi_kp = new ASN1ObjectIdentifier(id_sigi + ".2");
+ public final static ASN1ObjectIdentifier id_sigi_kp = new ASN1ObjectIdentifier("1.3.36.8.2");
/**
* Certificate policy IDs for German SigI (Signature Interoperability
* Specification)
+ * <p>
+ * OID: 1.3.36.8.1
*/
- public final static ASN1ObjectIdentifier id_sigi_cp = new ASN1ObjectIdentifier(id_sigi + ".1");
+ public final static ASN1ObjectIdentifier id_sigi_cp = new ASN1ObjectIdentifier("1.3.36.8.1");
/**
* Other Name IDs for German SigI (Signature Interoperability Specification)
+ * <p>
+ * OID: 1.3.36.8.4
*/
- public final static ASN1ObjectIdentifier id_sigi_on = new ASN1ObjectIdentifier(id_sigi + ".4");
+ public final static ASN1ObjectIdentifier id_sigi_on = new ASN1ObjectIdentifier("1.3.36.8.4");
/**
* To be used for for the generation of directory service certificates.
+ * <p>
+ * OID: 1.3.36.8.2.1
*/
- public static final ASN1ObjectIdentifier id_sigi_kp_directoryService = new ASN1ObjectIdentifier(id_sigi_kp + ".1");
+ public static final ASN1ObjectIdentifier id_sigi_kp_directoryService = new ASN1ObjectIdentifier("1.3.36.8.2.1");
/**
* ID for PersonalData
+ * <p>
+ * OID: 1.3.36.8.4.1
*/
- public static final ASN1ObjectIdentifier id_sigi_on_personalData = new ASN1ObjectIdentifier(id_sigi_on + ".1");
+ public static final ASN1ObjectIdentifier id_sigi_on_personalData = new ASN1ObjectIdentifier("1.3.36.8.4.1");
/**
- * Certificate is conform to german signature law.
+ * Certificate is conformant to german signature law.
+ * <p>
+ * OID: 1.3.36.8.1.1
*/
- public static final ASN1ObjectIdentifier id_sigi_cp_sigconform = new ASN1ObjectIdentifier(id_sigi_cp + ".1");
+ public static final ASN1ObjectIdentifier id_sigi_cp_sigconform = new ASN1ObjectIdentifier("1.3.36.8.1.1");
}
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 fb545c2..eeae0de 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
@@ -65,6 +65,8 @@ public class ECNamedCurveTable
ecP = TeleTrusTNamedCurves.getByOID(oid);
}
+ // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup
+
return ecP;
}
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 e059089..60f9008 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECParameters.java
@@ -39,11 +39,21 @@ public class X9ECParameters
}
X9Curve x9c = new X9Curve(
- new X9FieldID((ASN1Sequence)seq.getObjectAt(1)),
- (ASN1Sequence)seq.getObjectAt(2));
+ X9FieldID.getInstance(seq.getObjectAt(1)),
+ ASN1Sequence.getInstance(seq.getObjectAt(2)));
this.curve = x9c.getCurve();
- this.g = new X9ECPoint(curve, (ASN1OctetString)seq.getObjectAt(3)).getPoint();
+ Object p = seq.getObjectAt(3);
+
+ if (p instanceof X9ECPoint)
+ {
+ this.g = ((X9ECPoint)p).getPoint();
+ }
+ else
+ {
+ this.g = new X9ECPoint(curve, (ASN1OctetString)p).getPoint();
+ }
+
this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue();
this.seed = x9c.getSeed();
@@ -93,7 +103,7 @@ public class X9ECParameters
byte[] seed)
{
this.curve = curve;
- this.g = g;
+ this.g = g.normalize();
this.n = n;
this.h = h;
this.seed = seed;
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 a4acb6e..cbb9116 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java
@@ -18,7 +18,7 @@ public class X9ECPoint
public X9ECPoint(
ECPoint p)
{
- this.p = p;
+ this.p = p.normalize();
}
public X9ECPoint(
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
index 30598e2..a210352 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9FieldID.java
@@ -71,11 +71,26 @@ public class X9FieldID
this.parameters = new DERSequence(fieldIdParams);
}
- public X9FieldID(
+ private X9FieldID(
ASN1Sequence seq)
{
- this.id = (ASN1ObjectIdentifier)seq.getObjectAt(0);
- this.parameters = (ASN1Primitive)seq.getObjectAt(1);
+ this.id = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ this.parameters = seq.getObjectAt(1).toASN1Primitive();
+ }
+
+ public static X9FieldID getInstance(Object obj)
+ {
+ if (obj instanceof X9FieldID)
+ {
+ return (X9FieldID)obj;
+ }
+
+ if (obj != null)
+ {
+ return new X9FieldID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
}
public ASN1ObjectIdentifier getIdentifier()
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 f005cfa..eabf90e 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
@@ -2,109 +2,172 @@ package org.bouncycastle.asn1.x9;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ *
+ * X9.62
+ * <pre>
+ * ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ * us(840) ansi-x962(10045) }
+ * </pre>
+ */
public interface X9ObjectIdentifiers
{
- //
- // X9.62
- //
- // ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-x962(10045) }
- //
+ /** Base OID: 1.2.840.10045 */
static final 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");
+ /** OID: 1.2.840.10045.1.1 */
static final ASN1ObjectIdentifier prime_field = id_fieldType.branch("1");
+ /** OID: 1.2.840.10045.1.2 */
static final 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");
+ /** OID: 1.2.840.10045.1.2.3.2 */
static final 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");
+ /** OID: 1.2.840.10045.4 */
static final ASN1ObjectIdentifier id_ecSigType = ansi_X9_62.branch("4");
- static final ASN1ObjectIdentifier ecdsa_with_SHA1 = new ASN1ObjectIdentifier(id_ecSigType + ".1");
+ /** OID: 1.2.840.10045.4.1 */
+ static final ASN1ObjectIdentifier ecdsa_with_SHA1 = id_ecSigType.branch("1");
+ /** OID: 1.2.840.10045.2 */
static final ASN1ObjectIdentifier id_publicKeyType = ansi_X9_62.branch("2");
+ /** OID: 1.2.840.10045.2.1 */
static final ASN1ObjectIdentifier id_ecPublicKey = id_publicKeyType.branch("1");
+ /** OID: 1.2.840.10045.4.3 */
static final 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");
+ /** OID: 1.2.840.10045.4.3.2 */
static final 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");
+ /** OID: 1.2.840.10045.4.3.4 */
static final ASN1ObjectIdentifier ecdsa_with_SHA512 = ecdsa_with_SHA2.branch("4");
- //
- // named curves
- //
+ /**
+ * Named curves base
+ * <p>
+ * OID: 1.2.840.10045.1
+ */
static final ASN1ObjectIdentifier ellipticCurve = ansi_X9_62.branch("3");
- //
- // Two Curves
- //
+ /**
+ * Two Curves
+ * <p>
+ * OID: 1.2.840.10045.1.0
+ */
static final ASN1ObjectIdentifier cTwoCurve = ellipticCurve.branch("0");
+ /** Two Curve c2pnb163v1, OID: 1.2.840.10045.1.0.1 */
static final ASN1ObjectIdentifier c2pnb163v1 = cTwoCurve.branch("1");
+ /** Two Curve c2pnb163v2, OID: 1.2.840.10045.1.0.2 */
static final ASN1ObjectIdentifier c2pnb163v2 = cTwoCurve.branch("2");
+ /** Two Curve c2pnb163v3, OID: 1.2.840.10045.1.0.3 */
static final ASN1ObjectIdentifier c2pnb163v3 = cTwoCurve.branch("3");
+ /** Two Curve c2pnb176w1, OID: 1.2.840.10045.1.0.4 */
static final ASN1ObjectIdentifier c2pnb176w1 = cTwoCurve.branch("4");
+ /** Two Curve c2tnb191v1, OID: 1.2.840.10045.1.0.5 */
static final ASN1ObjectIdentifier c2tnb191v1 = cTwoCurve.branch("5");
+ /** Two Curve c2tnb191v2, OID: 1.2.840.10045.1.0.6 */
static final ASN1ObjectIdentifier c2tnb191v2 = cTwoCurve.branch("6");
+ /** Two Curve c2tnb191v3, OID: 1.2.840.10045.1.0.7 */
static final ASN1ObjectIdentifier c2tnb191v3 = cTwoCurve.branch("7");
+ /** Two Curve c2onb191v4, OID: 1.2.840.10045.1.0.8 */
static final ASN1ObjectIdentifier c2onb191v4 = cTwoCurve.branch("8");
+ /** Two Curve c2onb191v5, OID: 1.2.840.10045.1.0.9 */
static final ASN1ObjectIdentifier c2onb191v5 = cTwoCurve.branch("9");
+ /** Two Curve c2pnb208w1, OID: 1.2.840.10045.1.0.10 */
static final ASN1ObjectIdentifier c2pnb208w1 = cTwoCurve.branch("10");
+ /** Two Curve c2tnb239v1, OID: 1.2.840.10045.1.0.11 */
static final ASN1ObjectIdentifier c2tnb239v1 = cTwoCurve.branch("11");
+ /** Two Curve c2tnb239v2, OID: 1.2.840.10045.1.0.12 */
static final ASN1ObjectIdentifier c2tnb239v2 = cTwoCurve.branch("12");
+ /** Two Curve c2tnb239v3, OID: 1.2.840.10045.1.0.13 */
static final ASN1ObjectIdentifier c2tnb239v3 = cTwoCurve.branch("13");
+ /** Two Curve c2onb239v4, OID: 1.2.840.10045.1.0.14 */
static final ASN1ObjectIdentifier c2onb239v4 = cTwoCurve.branch("14");
+ /** Two Curve c2onb239v5, OID: 1.2.840.10045.1.0.15 */
static final ASN1ObjectIdentifier c2onb239v5 = cTwoCurve.branch("15");
+ /** Two Curve c2pnb272w1, OID: 1.2.840.10045.1.0.16 */
static final ASN1ObjectIdentifier c2pnb272w1 = cTwoCurve.branch("16");
+ /** Two Curve c2pnb304w1, OID: 1.2.840.10045.1.0.17 */
static final ASN1ObjectIdentifier c2pnb304w1 = cTwoCurve.branch("17");
+ /** Two Curve c2tnb359v1, OID: 1.2.840.10045.1.0.18 */
static final ASN1ObjectIdentifier c2tnb359v1 = cTwoCurve.branch("18");
+ /** Two Curve c2pnb368w1, OID: 1.2.840.10045.1.0.19 */
static final ASN1ObjectIdentifier c2pnb368w1 = cTwoCurve.branch("19");
+ /** Two Curve c2tnb431r1, OID: 1.2.840.10045.1.0.20 */
static final ASN1ObjectIdentifier c2tnb431r1 = cTwoCurve.branch("20");
- //
- // Prime
- //
+ /**
+ * Prime Curves
+ * <p>
+ * OID: 1.2.840.10045.1.1
+ */
static final ASN1ObjectIdentifier primeCurve = ellipticCurve.branch("1");
+ /** Prime Curve prime192v1, OID: 1.2.840.10045.1.1.1 */
static final ASN1ObjectIdentifier prime192v1 = primeCurve.branch("1");
+ /** Prime Curve prime192v2, OID: 1.2.840.10045.1.1.2 */
static final ASN1ObjectIdentifier prime192v2 = primeCurve.branch("2");
+ /** Prime Curve prime192v3, OID: 1.2.840.10045.1.1.3 */
static final ASN1ObjectIdentifier prime192v3 = primeCurve.branch("3");
+ /** Prime Curve prime239v1, OID: 1.2.840.10045.1.1.4 */
static final ASN1ObjectIdentifier prime239v1 = primeCurve.branch("4");
+ /** Prime Curve prime239v2, OID: 1.2.840.10045.1.1.5 */
static final ASN1ObjectIdentifier prime239v2 = primeCurve.branch("5");
+ /** Prime Curve prime239v3, OID: 1.2.840.10045.1.1.6 */
static final ASN1ObjectIdentifier prime239v3 = primeCurve.branch("6");
+ /** Prime Curve prime256v1, OID: 1.2.840.10045.1.1.7 */
static final ASN1ObjectIdentifier prime256v1 = primeCurve.branch("7");
- //
- // DSA
- //
- // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-x957(10040) number-type(4) 1 }
+ /**
+ * DSA
+ * <pre>
+ * dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ * us(840) ansi-x957(10040) number-type(4) 1 }
+ * </pre>
+ * Base OID: 1.2.840.10040.4.1
+ */
static final ASN1ObjectIdentifier id_dsa = new ASN1ObjectIdentifier("1.2.840.10040.4.1");
/**
- * id-dsa-with-sha1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) x9-57
- * (10040) x9cm(4) 3 }
+ * <pre>
+ * id-dsa-with-sha1 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
+ * </pre>
+ * OID: 1.2.840.10040.4.3
*/
- public static final ASN1ObjectIdentifier id_dsa_with_sha1 = new ASN1ObjectIdentifier("1.2.840.10040.4.3");
+ static final ASN1ObjectIdentifier id_dsa_with_sha1 = new ASN1ObjectIdentifier("1.2.840.10040.4.3");
/**
- * X9.63
+ * X9.63 - Signature Specification
+ * <p>
+ * Base OID: 1.3.133.16.840.63.0
*/
- public static final ASN1ObjectIdentifier x9_63_scheme = new ASN1ObjectIdentifier("1.3.133.16.840.63.0");
- public static final ASN1ObjectIdentifier dhSinglePass_stdDH_sha1kdf_scheme = x9_63_scheme.branch("2");
- public static final ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha1kdf_scheme = x9_63_scheme.branch("3");
- public static final ASN1ObjectIdentifier mqvSinglePass_sha1kdf_scheme = x9_63_scheme.branch("16");
+ static final 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");
+ /** OID: 1.3.133.16.840.63.0.3 */
+ static final 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");
/**
* X9.42
@@ -112,21 +175,33 @@ public interface X9ObjectIdentifiers
static final ASN1ObjectIdentifier ansi_X9_42 = new ASN1ObjectIdentifier("1.2.840.10046");
- //
- // Diffie-Hellman
- //
- // dhpublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-x942(10046) number-type(2) 1 }
- //
- public static final ASN1ObjectIdentifier dhpublicnumber = ansi_X9_42.branch("2.1");
-
- public static final ASN1ObjectIdentifier x9_42_schemes = ansi_X9_42.branch("3");
- public static final ASN1ObjectIdentifier dhStatic = x9_42_schemes.branch("1");
- public static final ASN1ObjectIdentifier dhEphem = x9_42_schemes.branch("2");
- public static final ASN1ObjectIdentifier dhOneFlow = x9_42_schemes.branch("3");
- public static final ASN1ObjectIdentifier dhHybrid1 = x9_42_schemes.branch("4");
- public static final ASN1ObjectIdentifier dhHybrid2 = x9_42_schemes.branch("5");
- public static final ASN1ObjectIdentifier dhHybridOneFlow = x9_42_schemes.branch("6");
- public static final ASN1ObjectIdentifier mqv2 = x9_42_schemes.branch("7");
- public static final ASN1ObjectIdentifier mqv1 = x9_42_schemes.branch("8");
+ /**
+ * Diffie-Hellman
+ * <pre>
+ * dhpublicnumber OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-x942(10046) number-type(2) 1
+ * }
+ * </pre>
+ * OID: 1.2.840.10046.2.1
+ */
+ static final 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");
+ /** X9.42 dhStatic OID: 1.2.840.10046.3.1 */
+ static final 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");
+ /** X9.42 dhOneFlow OID: 1.2.840.10046.3.3 */
+ static final 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");
+ /** X9.42 dhHybrid2 OID: 1.2.840.10046.3.5 */
+ static final 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");
+ /** X9.42 MQV2 OID: 1.2.840.10046.3.7 */
+ static final ASN1ObjectIdentifier mqv2 = x9_42_schemes.branch("7");
+ /** X9.42 MQV1 OID: 1.2.840.10046.3.8 */
+ static final ASN1ObjectIdentifier mqv1 = x9_42_schemes.branch("8");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/package.html b/bcprov/src/main/java/org/bouncycastle/asn1/x9/package.html
deleted file mode 100644
index 42fc97c..0000000
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting X9.62 elliptic curve.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
index bdb694d..dd056ac 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
@@ -54,7 +54,7 @@ public class BufferedBlockCipher
}
else
{
- partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
+ partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("GCFB", idx) ||name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java b/bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java
index ef6e29e..0e2b4b0 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/DerivationFunction.java
@@ -7,11 +7,6 @@ public interface DerivationFunction
{
public void init(DerivationParameters param);
- /**
- * return the message digest used as the basis for the function
- */
- public Digest getDigest();
-
public int generateBytes(byte[] out, int outOff, int len)
throws DataLengthException, IllegalArgumentException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/DigestDerivationFunction.java b/bcprov/src/main/java/org/bouncycastle/crypto/DigestDerivationFunction.java
new file mode 100644
index 0000000..180382d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/DigestDerivationFunction.java
@@ -0,0 +1,13 @@
+package org.bouncycastle.crypto;
+
+/**
+ * base interface for general purpose Digest based byte derivation functions.
+ */
+public interface DigestDerivationFunction
+ extends DerivationFunction
+{
+ /**
+ * return the message digest used as the basis for the function
+ */
+ public Digest getDigest();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/MacDerivationFunction.java b/bcprov/src/main/java/org/bouncycastle/crypto/MacDerivationFunction.java
new file mode 100644
index 0000000..16198ba
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/MacDerivationFunction.java
@@ -0,0 +1,13 @@
+package org.bouncycastle.crypto;
+
+/**
+ * base interface for general purpose Mac based byte derivation functions.
+ */
+public interface MacDerivationFunction
+ extends DerivationFunction
+{
+ /**
+ * return the MAC used as the basis for the function
+ */
+ public Mac getMac();
+}
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 59944e0..a491b9d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
@@ -42,10 +42,13 @@ public class ECDHBasicAgreement
CipherParameters pubKey)
{
ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
- ECPoint P = pub.getQ().multiply(key.getD());
+ ECPoint P = pub.getQ().multiply(key.getD()).normalize();
- // if (p.isInfinity()) throw new RuntimeException("d*Q == infinity");
+ if (P.isInfinity())
+ {
+ throw new IllegalStateException("Infinity is not a valid agreement value for ECDH");
+ }
- return P.getX().toBigInteger();
+ return P.getAffineXCoord().toBigInteger();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java
index 12b8405..28140df 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java
@@ -47,12 +47,18 @@ public class ECDHCBasicAgreement
public BigInteger calculateAgreement(
CipherParameters pubKey)
{
- ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
- ECDomainParameters params = pub.getParameters();
- ECPoint P = pub.getQ().multiply(params.getH().multiply(key.getD()));
+ ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
+ ECDomainParameters params = pub.getParameters();
- // if (p.isInfinity()) throw new RuntimeException("Invalid public key");
+ BigInteger hd = params.getH().multiply(key.getD()).mod(params.getN());
- return P.getX().toBigInteger();
+ ECPoint P = pub.getQ().multiply(hd).normalize();
+
+ if (P.isInfinity())
+ {
+ throw new IllegalStateException("Infinity is not a valid agreement value for ECDHC");
+ }
+
+ return P.getAffineXCoord().toBigInteger();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java
index da88b4a..794f555 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java
@@ -11,6 +11,7 @@ import org.bouncycastle.crypto.params.MQVPrivateParameters;
import org.bouncycastle.crypto.params.MQVPublicParameters;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECConstants;
+import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
public class ECMQVBasicAgreement
@@ -37,9 +38,14 @@ public class ECMQVBasicAgreement
ECPoint agreement = calculateMqvAgreement(staticPrivateKey.getParameters(), staticPrivateKey,
privParams.getEphemeralPrivateKey(), privParams.getEphemeralPublicKey(),
- pubParams.getStaticPublicKey(), pubParams.getEphemeralPublicKey());
+ pubParams.getStaticPublicKey(), pubParams.getEphemeralPublicKey()).normalize();
- return agreement.getX().toBigInteger();
+ if (agreement.isInfinity())
+ {
+ throw new IllegalStateException("Infinity is not a valid agreement value for MQV");
+ }
+
+ return agreement.getAffineXCoord().toBigInteger();
}
// The ECMQV Primitive as described in SEC-1, 3.4
@@ -55,37 +61,31 @@ public class ECMQVBasicAgreement
int e = (n.bitLength() + 1) / 2;
BigInteger powE = ECConstants.ONE.shiftLeft(e);
- // The Q2U public key is optional
- ECPoint q;
- if (Q2U == null)
- {
- q = parameters.getG().multiply(d2U.getD());
- }
- else
- {
- q = Q2U.getQ();
- }
+ ECCurve curve = parameters.getCurve();
- BigInteger x = q.getX().toBigInteger();
+ ECPoint[] points = new ECPoint[]{
+ // The Q2U public key is optional
+ ECAlgorithms.importPoint(curve, Q2U == null ? parameters.getG().multiply(d2U.getD()) : Q2U.getQ()),
+ ECAlgorithms.importPoint(curve, Q1V.getQ()),
+ ECAlgorithms.importPoint(curve, Q2V.getQ())
+ };
+
+ curve.normalizeAll(points);
+
+ ECPoint q2u = points[0], q1v = points[1], q2v = points[2];
+
+ BigInteger x = q2u.getAffineXCoord().toBigInteger();
BigInteger xBar = x.mod(powE);
BigInteger Q2UBar = xBar.setBit(e);
- BigInteger s = d1U.getD().multiply(Q2UBar).mod(n).add(d2U.getD()).mod(n);
+ BigInteger s = d1U.getD().multiply(Q2UBar).add(d2U.getD()).mod(n);
- BigInteger xPrime = Q2V.getQ().getX().toBigInteger();
+ BigInteger xPrime = q2v.getAffineXCoord().toBigInteger();
BigInteger xPrimeBar = xPrime.mod(powE);
BigInteger Q2VBar = xPrimeBar.setBit(e);
BigInteger hs = parameters.getH().multiply(s).mod(n);
-// ECPoint p = Q1V.getQ().multiply(Q2VBar).add(Q2V.getQ()).multiply(hs);
- ECPoint p = ECAlgorithms.sumOfTwoMultiplies(
- Q1V.getQ(), Q2VBar.multiply(hs).mod(n), Q2V.getQ(), hs);
-
- if (p.isInfinity())
- {
- throw new IllegalStateException("Infinity is not a valid agreement value for MQV");
- }
-
- return p;
+ return ECAlgorithms.sumOfTwoMultiplies(
+ q1v, Q2VBar.multiply(hs).mod(n), q2v, hs);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/jpake/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/jpake/package.html
deleted file mode 100644
index db47144..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/jpake/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Password Authenticated Key Exchange by Juggling (J-PAKE).
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
index 6803953..500b1dd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
@@ -11,9 +11,9 @@ import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.DerivationParameters;
import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.DigestDerivationFunction;
import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
import org.bouncycastle.crypto.params.KDFParameters;
import org.bouncycastle.crypto.util.Pack;
@@ -22,9 +22,9 @@ import org.bouncycastle.crypto.util.Pack;
* X9.63 based key derivation function for ECDH CMS.
*/
public class ECDHKEKGenerator
- implements DerivationFunction
+ implements DigestDerivationFunction
{
- private DerivationFunction kdf;
+ private DigestDerivationFunction kdf;
private ASN1ObjectIdentifier algorithm;
private int keySize;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/package.html
deleted file mode 100644
index 4b49331..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Basic key agreement classes.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/commitments/GeneralHashCommitter.java b/bcprov/src/main/java/org/bouncycastle/crypto/commitments/GeneralHashCommitter.java
new file mode 100644
index 0000000..3969fe8
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/commitments/GeneralHashCommitter.java
@@ -0,0 +1,93 @@
+package org.bouncycastle.crypto.commitments;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.Commitment;
+import org.bouncycastle.crypto.Committer;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.ExtendedDigest;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * A basic hash-committer based on the one described in "Making Mix Nets Robust for Electronic Voting by Randomized Partial Checking",
+ * by Jakobsson, Juels, and Rivest (11th Usenix Security Symposium, 2002).
+ * <p>
+ * The algorithm used by this class differs from the one given in that it includes the length of the message in the hash calculation.
+ * </p>
+ */
+public class GeneralHashCommitter
+ implements Committer
+{
+ private final Digest digest;
+ private final int byteLength;
+ private final SecureRandom random;
+
+ /**
+ * Base Constructor. The maximum message length that can be committed to is half the length of the internal
+ * block size for the digest (ExtendedDigest.getBlockLength()).
+ *
+ * @param digest digest to use for creating commitments.
+ * @param random source of randomness for generating secrets.
+ */
+ public GeneralHashCommitter(ExtendedDigest digest, SecureRandom random)
+ {
+ this.digest = digest;
+ this.byteLength = digest.getByteLength();
+ this.random = random;
+ }
+
+ /**
+ * Generate a commitment for the passed in message.
+ *
+ * @param message the message to be committed to,
+ * @return a Commitment
+ */
+ public Commitment commit(byte[] message)
+ {
+ if (message.length > byteLength / 2)
+ {
+ throw new DataLengthException("Message to be committed to too large for digest.");
+ }
+
+ byte[] w = new byte[byteLength - message.length];
+
+ random.nextBytes(w);
+
+ return new Commitment(w, calculateCommitment(w, message));
+ }
+
+ /**
+ * Return true if the passed in commitment represents a commitment to the passed in message.
+ *
+ * @param commitment a commitment previously generated.
+ * @param message the message that was expected to have been committed to.
+ * @return true if commitment matches message, false otherwise.
+ */
+ public boolean isRevealed(Commitment commitment, byte[] message)
+ {
+ if (message.length + commitment.getSecret().length != byteLength)
+ {
+ throw new DataLengthException("Message and witness secret lengths do not match.");
+ }
+
+ byte[] calcCommitment = calculateCommitment(commitment.getSecret(), message);
+
+ return Arrays.constantTimeAreEqual(commitment.getCommitment(), calcCommitment);
+ }
+
+ private byte[] calculateCommitment(byte[] w, byte[] message)
+ {
+ byte[] commitment = new byte[digest.getDigestSize()];
+
+ digest.update(w, 0, w.length);
+ digest.update(message, 0, message.length);
+
+ digest.update((byte)((message.length >>> 8)));
+ digest.update((byte)(message.length));
+
+ digest.doFinal(commitment, 0);
+
+ return commitment;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java b/bcprov/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java
index 1494c3c..b5860b5 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/commitments/HashCommitter.java
@@ -12,6 +12,9 @@ import org.bouncycastle.util.Arrays;
/**
* A basic hash-committer as described in "Making Mix Nets Robust for Electronic Voting by Randomized Partial Checking",
* by Jakobsson, Juels, and Rivest (11th Usenix Security Symposium, 2002).
+ * <p>
+ * Use this class if you can enforce fixed length for messages. If you need something more general, use the GeneralHashCommitter.
+ * </p>
*/
public class HashCommitter
implements Committer
@@ -55,7 +58,7 @@ public class HashCommitter
}
/**
- * Return true if the passed in commitment represents a commitment to the passed in maessage.
+ * Return true if the passed in commitment represents a commitment to the passed in message.
*
* @param commitment a commitment previously generated.
* @param message the message that was expected to have been committed to.
@@ -63,6 +66,11 @@ public class HashCommitter
*/
public boolean isRevealed(Commitment commitment, byte[] message)
{
+ if (message.length + commitment.getSecret().length != byteLength)
+ {
+ throw new DataLengthException("Message and witness secret lengths do not match.");
+ }
+
byte[] calcCommitment = calculateCommitment(commitment.getSecret(), message);
return Arrays.constantTimeAreEqual(commitment.getCommitment(), calcCommitment);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/commitments/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/commitments/package.html
deleted file mode 100644
index 302cc60..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/commitments/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Commitment algorithms.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SM3Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SM3Digest.java
new file mode 100644
index 0000000..55e579e
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SM3Digest.java
@@ -0,0 +1,333 @@
+package org.bouncycastle.crypto.digests;
+
+import org.bouncycastle.crypto.util.Pack;
+import org.bouncycastle.util.Memoable;
+
+/**
+ * Implementation of Chinese SM3 digest as described at
+ * http://tools.ietf.org/html/draft-shen-sm3-hash-00
+ * and at .... ( Chinese PDF )
+ * <p/>
+ * The specification says "process a bit stream",
+ * but this is written to process bytes in blocks of 4,
+ * meaning this will process 32-bit word groups.
+ * But so do also most other digest specifications,
+ * including the SHA-256 which was a origin for
+ * this specification.
+ */
+public class SM3Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 32; // bytes
+ private static final int BLOCK_SIZE = 64 / 4; // of 32 bit ints (16 ints)
+
+ private int[] V = new int[DIGEST_LENGTH / 4]; // in 32 bit ints (8 ints)
+ private int[] inwords = new int[BLOCK_SIZE];
+ private int xOff;
+
+ // Work-bufs used within processBlock()
+ private int[] W = new int[68];
+ private int[] W1 = new int[64];
+
+ // Round constant T for processBlock() which is 32 bit integer rolled left up to (63 MOD 32) bit positions.
+ private static final int[] T = new int[64];
+
+ static
+ {
+ for (int i = 0; i < 16; ++i)
+ {
+ int t = 0x79CC4519;
+ T[i] = (t << i) | (t >>> (32 - i));
+ }
+ for (int i = 16; i < 64; ++i)
+ {
+ int n = i % 32;
+ int t = 0x7A879D8A;
+ T[i] = (t << n) | (t >>> (32 - n));
+ }
+ }
+
+
+ /**
+ * Standard constructor
+ */
+ public SM3Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SM3Digest(SM3Digest t)
+ {
+ super(t);
+
+ copyIn(t);
+ }
+
+ private void copyIn(SM3Digest t)
+ {
+ System.arraycopy(t.V, 0, this.V, 0, this.V.length);
+ System.arraycopy(t.inwords, 0, this.inwords, 0, this.inwords.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SM3";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+
+ public Memoable copy()
+ {
+ return new SM3Digest(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ SM3Digest d = (SM3Digest)other;
+
+ super.copyIn(d);
+ copyIn(d);
+ }
+
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ this.V[0] = 0x7380166F;
+ this.V[1] = 0x4914B2B9;
+ this.V[2] = 0x172442D7;
+ this.V[3] = 0xDA8A0600;
+ this.V[4] = 0xA96F30BC;
+ this.V[5] = 0x163138AA;
+ this.V[6] = 0xE38DEE4D;
+ this.V[7] = 0xB0FB0E4E;
+
+ this.xOff = 0;
+ }
+
+
+ public int doFinal(byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.intToBigEndian(this.V[0], out, outOff + 0);
+ Pack.intToBigEndian(this.V[1], out, outOff + 4);
+ Pack.intToBigEndian(this.V[2], out, outOff + 8);
+ Pack.intToBigEndian(this.V[3], out, outOff + 12);
+ Pack.intToBigEndian(this.V[4], out, outOff + 16);
+ Pack.intToBigEndian(this.V[5], out, outOff + 20);
+ Pack.intToBigEndian(this.V[6], out, outOff + 24);
+ Pack.intToBigEndian(this.V[7], out, outOff + 28);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+
+ protected void processWord(byte[] in,
+ int inOff)
+ {
+ // Note: Inlined for performance
+ // this.inwords[xOff] = Pack.bigEndianToInt(in, inOff);
+ int n = (((in[inOff] & 0xff) << 24) |
+ ((in[++inOff] & 0xff) << 16) |
+ ((in[++inOff] & 0xff) << 8) |
+ ((in[++inOff] & 0xff)));
+
+ this.inwords[this.xOff] = n;
+ ++this.xOff;
+
+ if (this.xOff >= 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(long bitLength)
+ {
+ if (this.xOff > (BLOCK_SIZE - 2))
+ {
+ // xOff == 15 --> can't fit the 64 bit length field at tail..
+ this.inwords[this.xOff] = 0; // fill with zero
+ ++this.xOff;
+
+ processBlock();
+ }
+ // Fill with zero words, until reach 2nd to last slot
+ while (this.xOff < (BLOCK_SIZE - 2))
+ {
+ this.inwords[this.xOff] = 0;
+ ++this.xOff;
+ }
+
+ // Store input data length in BITS
+ this.inwords[this.xOff++] = (int)(bitLength >>> 32);
+ this.inwords[this.xOff++] = (int)(bitLength);
+ }
+
+/*
+
+3.4.2. Constants
+
+
+ Tj = 79cc4519 when 0 < = j < = 15
+ Tj = 7a879d8a when 16 < = j < = 63
+
+3.4.3. Boolean function
+
+
+ FFj(X;Y;Z) = X XOR Y XOR Z when 0 < = j < = 15
+ = (X AND Y) OR (X AND Z) OR (Y AND Z) when 16 < = j < = 63
+
+ GGj(X;Y;Z) = X XOR Y XOR Z when 0 < = j < = 15
+ = (X AND Y) OR (NOT X AND Z) when 16 < = j < = 63
+
+ The X, Y, Z in the fomular are words!GBP
+
+3.4.4. Permutation function
+
+
+ P0(X) = X XOR (X <<< 9) XOR (X <<< 17) ## ROLL, not SHIFT
+ P1(X) = X XOR (X <<< 15) XOR (X <<< 23) ## ROLL, not SHIFT
+
+ The X in the fomular are a word.
+
+----------
+
+Each ROLL converted to Java expression:
+
+ROLL 9 : ((x << 9) | (x >>> (32-9))))
+ROLL 17 : ((x << 17) | (x >>> (32-17)))
+ROLL 15 : ((x << 15) | (x >>> (32-15)))
+ROLL 23 : ((x << 23) | (x >>> (32-23)))
+
+ */
+
+ private int P0(final int x)
+ {
+ final int r9 = ((x << 9) | (x >>> (32 - 9)));
+ final int r17 = ((x << 17) | (x >>> (32 - 17)));
+ return (x ^ r9 ^ r17);
+ }
+
+ private int P1(final int x)
+ {
+ final int r15 = ((x << 15) | (x >>> (32 - 15)));
+ final int r23 = ((x << 23) | (x >>> (32 - 23)));
+ return (x ^ r15 ^ r23);
+ }
+
+ private int FF0(final int x, final int y, final int z)
+ {
+ return (x ^ y ^ z);
+ }
+
+ private int FF1(final int x, final int y, final int z)
+ {
+ return ((x & y) | (x & z) | (y & z));
+ }
+
+ private int GG0(final int x, final int y, final int z)
+ {
+ return (x ^ y ^ z);
+ }
+
+ private int GG1(final int x, final int y, final int z)
+ {
+ return ((x & y) | ((~x) & z));
+ }
+
+
+ protected void processBlock()
+ {
+ for (int j = 0; j < 16; ++j)
+ {
+ this.W[j] = this.inwords[j];
+ }
+ for (int j = 16; j < 68; ++j)
+ {
+ int wj3 = this.W[j - 3];
+ int r15 = ((wj3 << 15) | (wj3 >>> (32 - 15)));
+ int wj13 = this.W[j - 13];
+ int r7 = ((wj13 << 7) | (wj13 >>> (32 - 7)));
+ this.W[j] = P1(this.W[j - 16] ^ this.W[j - 9] ^ r15) ^ r7 ^ this.W[j - 6];
+ }
+ for (int j = 0; j < 64; ++j)
+ {
+ this.W1[j] = this.W[j] ^ this.W[j + 4];
+ }
+
+ int A = this.V[0];
+ int B = this.V[1];
+ int C = this.V[2];
+ int D = this.V[3];
+ int E = this.V[4];
+ int F = this.V[5];
+ int G = this.V[6];
+ int H = this.V[7];
+
+
+ for (int j = 0; j < 16; ++j)
+ {
+ int a12 = ((A << 12) | (A >>> (32 - 12)));
+ int s1_ = a12 + E + T[j];
+ int SS1 = ((s1_ << 7) | (s1_ >>> (32 - 7)));
+ int SS2 = SS1 ^ a12;
+ int TT1 = FF0(A, B, C) + D + SS2 + this.W1[j];
+ int TT2 = GG0(E, F, G) + H + SS1 + this.W[j];
+ D = C;
+ C = ((B << 9) | (B >>> (32 - 9)));
+ B = A;
+ A = TT1;
+ H = G;
+ G = ((F << 19) | (F >>> (32 - 19)));
+ F = E;
+ E = P0(TT2);
+ }
+
+ // Different FF,GG functions on rounds 16..63
+ for (int j = 16; j < 64; ++j)
+ {
+ int a12 = ((A << 12) | (A >>> (32 - 12)));
+ int s1_ = a12 + E + T[j];
+ int SS1 = ((s1_ << 7) | (s1_ >>> (32 - 7)));
+ int SS2 = SS1 ^ a12;
+ int TT1 = FF1(A, B, C) + D + SS2 + this.W1[j];
+ int TT2 = GG1(E, F, G) + H + SS1 + this.W[j];
+ D = C;
+ C = ((B << 9) | (B >>> (32 - 9)));
+ B = A;
+ A = TT1;
+ H = G;
+ G = ((F << 19) | (F >>> (32 - 19)));
+ F = E;
+ E = P0(TT2);
+ }
+
+ this.V[0] ^= A;
+ this.V[1] ^= B;
+ this.V[2] ^= C;
+ this.V[3] ^= D;
+ this.V[4] ^= E;
+ this.V[5] ^= F;
+ this.V[6] ^= G;
+ this.V[7] ^= H;
+
+ this.xOff = 0;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SkeinDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SkeinDigest.java
new file mode 100644
index 0000000..06eaabd
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SkeinDigest.java
@@ -0,0 +1,116 @@
+package org.bouncycastle.crypto.digests;
+
+import org.bouncycastle.crypto.ExtendedDigest;
+import org.bouncycastle.crypto.engines.ThreefishEngine;
+import org.bouncycastle.crypto.params.SkeinParameters;
+import org.bouncycastle.util.Memoable;
+
+/**
+ * Implementation of the Skein parameterised hash function in 256, 512 and 1024 bit block sizes,
+ * based on the {@link ThreefishEngine Threefish} tweakable block cipher.
+ * <p/>
+ * This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+ * competition in October 2010.
+ * <p/>
+ * Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+ * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+ * <p/>
+ *
+ * @see SkeinEngine
+ * @see SkeinParameters
+ */
+public class SkeinDigest
+ implements ExtendedDigest, Memoable
+{
+ /**
+ * 256 bit block size - Skein-256
+ */
+ public static final int SKEIN_256 = SkeinEngine.SKEIN_256;
+ /**
+ * 512 bit block size - Skein-512
+ */
+ public static final int SKEIN_512 = SkeinEngine.SKEIN_512;
+ /**
+ * 1024 bit block size - Skein-1024
+ */
+ public static final int SKEIN_1024 = SkeinEngine.SKEIN_1024;
+
+ private SkeinEngine engine;
+
+ /**
+ * Constructs a Skein digest with an internal state size and output size.
+ *
+ * @param stateSizeBits the internal state size in bits - one of {@link #SKEIN_256}, {@link #SKEIN_512} or
+ * {@link #SKEIN_1024}.
+ * @param digestSizeBits the output/digest size to produce in bits, which must be an integral number of
+ * bytes.
+ */
+ public SkeinDigest(int stateSizeBits, int digestSizeBits)
+ {
+ this.engine = new SkeinEngine(stateSizeBits, digestSizeBits);
+ init(null);
+ }
+
+ public SkeinDigest(SkeinDigest digest)
+ {
+ this.engine = new SkeinEngine(digest.engine);
+ }
+
+ public void reset(Memoable other)
+ {
+ SkeinDigest d = (SkeinDigest)other;
+ engine.reset(d.engine);
+ }
+
+ public Memoable copy()
+ {
+ return new SkeinDigest(this);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Skein-" + (engine.getBlockSize() * 8) + "-" + (engine.getOutputSize() * 8);
+ }
+
+ public int getDigestSize()
+ {
+ return engine.getOutputSize();
+ }
+
+ public int getByteLength()
+ {
+ return engine.getBlockSize();
+ }
+
+ /**
+ * Optionally initialises the Skein digest with the provided parameters.<br>
+ * See {@link SkeinParameters} for details on the parameterisation of the Skein hash function.
+ *
+ * @param params the parameters to apply to this engine, or <code>null</code> to use no parameters.
+ */
+ public void init(SkeinParameters params)
+ {
+ engine.init(params);
+ }
+
+ public void reset()
+ {
+ engine.reset();
+ }
+
+ public void update(byte in)
+ {
+ engine.update(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ engine.update(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ return engine.doFinal(out, outOff);
+ }
+
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SkeinEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SkeinEngine.java
new file mode 100644
index 0000000..bca524e
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SkeinEngine.java
@@ -0,0 +1,817 @@
+package org.bouncycastle.crypto.digests;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.engines.ThreefishEngine;
+import org.bouncycastle.crypto.macs.SkeinMac;
+import org.bouncycastle.crypto.params.SkeinParameters;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Memoable;
+
+/**
+ * Implementation of the Skein family of parameterised hash functions in 256, 512 and 1024 bit block
+ * sizes, based on the {@link ThreefishEngine Threefish} tweakable block cipher.
+ * <p/>
+ * This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+ * competition in October 2010.
+ * <p/>
+ * Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+ * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+ * <p/>
+ * This implementation is the basis for {@link SkeinDigest} and {@link SkeinMac}, implementing the
+ * parameter based configuration system that allows Skein to be adapted to multiple applications. <br>
+ * Initialising the engine with {@link SkeinParameters} allows standard and arbitrary parameters to
+ * be applied during the Skein hash function.
+ * <p/>
+ * Implemented:
+ * <ul>
+ * <li>256, 512 and 1024 bit internal states.</li>
+ * <li>Full 96 bit input length.</li>
+ * <li>Parameters defined in the Skein specification, and arbitrary other pre and post message
+ * parameters.</li>
+ * <li>Arbitrary output size in 1 byte intervals.</li>
+ * </ul>
+ * <p/>
+ * Not implemented:
+ * <ul>
+ * <li>Sub-byte length input (bit padding).</li>
+ * <li>Tree hashing.</li>
+ * </ul>
+ *
+ * @see SkeinParameters
+ */
+public class SkeinEngine
+ implements Memoable
+{
+ /**
+ * 256 bit block size - Skein 256
+ */
+ public static final int SKEIN_256 = ThreefishEngine.BLOCKSIZE_256;
+ /**
+ * 512 bit block size - Skein 512
+ */
+ public static final int SKEIN_512 = ThreefishEngine.BLOCKSIZE_512;
+ /**
+ * 1024 bit block size - Skein 1024
+ */
+ public static final int SKEIN_1024 = ThreefishEngine.BLOCKSIZE_1024;
+
+ // Minimal at present, but more complex when tree hashing is implemented
+ private static class Configuration
+ {
+ private byte[] bytes = new byte[32];
+
+ public Configuration(long outputSizeBits)
+ {
+ // 0..3 = ASCII SHA3
+ bytes[0] = (byte)'S';
+ bytes[1] = (byte)'H';
+ bytes[2] = (byte)'A';
+ bytes[3] = (byte)'3';
+
+ // 4..5 = version number in LSB order
+ bytes[4] = 1;
+ bytes[5] = 0;
+
+ // 8..15 = output length
+ ThreefishEngine.wordToBytes(outputSizeBits, bytes, 8);
+ }
+
+ public byte[] getBytes()
+ {
+ return bytes;
+ }
+
+ }
+
+ public static class Parameter
+ {
+ private int type;
+ private byte[] value;
+
+ public Parameter(int type, byte[] value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public int getType()
+ {
+ return type;
+ }
+
+ public byte[] getValue()
+ {
+ return value;
+ }
+
+ }
+
+ /**
+ * The parameter type for the Skein key.
+ */
+ private static final int PARAM_TYPE_KEY = 0;
+
+ /**
+ * The parameter type for the Skein configuration block.
+ */
+ private static final int PARAM_TYPE_CONFIG = 4;
+
+ /**
+ * The parameter type for the message.
+ */
+ private static final int PARAM_TYPE_MESSAGE = 48;
+
+ /**
+ * The parameter type for the output transformation.
+ */
+ private static final int PARAM_TYPE_OUTPUT = 63;
+
+ /**
+ * Precalculated UBI(CFG) states for common state/output combinations without key or other
+ * pre-message params.
+ */
+ private static final Hashtable INITIAL_STATES = new Hashtable();
+
+ static
+ {
+ // From Appendix C of the Skein 1.3 NIST submission
+ initialState(SKEIN_256, 128, new long[]{
+ 0xe1111906964d7260L,
+ 0x883daaa77c8d811cL,
+ 0x10080df491960f7aL,
+ 0xccf7dde5b45bc1c2L});
+
+ initialState(SKEIN_256, 160, new long[]{
+ 0x1420231472825e98L,
+ 0x2ac4e9a25a77e590L,
+ 0xd47a58568838d63eL,
+ 0x2dd2e4968586ab7dL});
+
+ initialState(SKEIN_256, 224, new long[]{
+ 0xc6098a8c9ae5ea0bL,
+ 0x876d568608c5191cL,
+ 0x99cb88d7d7f53884L,
+ 0x384bddb1aeddb5deL});
+
+ initialState(SKEIN_256, 256, new long[]{
+ 0xfc9da860d048b449L,
+ 0x2fca66479fa7d833L,
+ 0xb33bc3896656840fL,
+ 0x6a54e920fde8da69L});
+
+ initialState(SKEIN_512, 128, new long[]{
+ 0xa8bc7bf36fbf9f52L,
+ 0x1e9872cebd1af0aaL,
+ 0x309b1790b32190d3L,
+ 0xbcfbb8543f94805cL,
+ 0x0da61bcd6e31b11bL,
+ 0x1a18ebead46a32e3L,
+ 0xa2cc5b18ce84aa82L,
+ 0x6982ab289d46982dL});
+
+ initialState(SKEIN_512, 160, new long[]{
+ 0x28b81a2ae013bd91L,
+ 0xc2f11668b5bdf78fL,
+ 0x1760d8f3f6a56f12L,
+ 0x4fb747588239904fL,
+ 0x21ede07f7eaf5056L,
+ 0xd908922e63ed70b8L,
+ 0xb8ec76ffeccb52faL,
+ 0x01a47bb8a3f27a6eL});
+
+ initialState(SKEIN_512, 224, new long[]{
+ 0xccd0616248677224L,
+ 0xcba65cf3a92339efL,
+ 0x8ccd69d652ff4b64L,
+ 0x398aed7b3ab890b4L,
+ 0x0f59d1b1457d2bd0L,
+ 0x6776fe6575d4eb3dL,
+ 0x99fbc70e997413e9L,
+ 0x9e2cfccfe1c41ef7L});
+
+ initialState(SKEIN_512, 384, new long[]{
+ 0xa3f6c6bf3a75ef5fL,
+ 0xb0fef9ccfd84faa4L,
+ 0x9d77dd663d770cfeL,
+ 0xd798cbf3b468fddaL,
+ 0x1bc4a6668a0e4465L,
+ 0x7ed7d434e5807407L,
+ 0x548fc1acd4ec44d6L,
+ 0x266e17546aa18ff8L});
+
+ initialState(SKEIN_512, 512, new long[]{
+ 0x4903adff749c51ceL,
+ 0x0d95de399746df03L,
+ 0x8fd1934127c79bceL,
+ 0x9a255629ff352cb1L,
+ 0x5db62599df6ca7b0L,
+ 0xeabe394ca9d5c3f4L,
+ 0x991112c71a75b523L,
+ 0xae18a40b660fcc33L});
+ }
+
+ private static void initialState(int blockSize, int outputSize, long[] state)
+ {
+ INITIAL_STATES.put(variantIdentifier(blockSize / 8, outputSize / 8), state);
+ }
+
+ private static Integer variantIdentifier(int blockSizeBytes, int outputSizeBytes)
+ {
+ return new Integer((outputSizeBytes << 16) | blockSizeBytes);
+ }
+
+ private static class UbiTweak
+ {
+ /**
+ * Point at which position might overflow long, so switch to add with carry logic
+ */
+ private static final long LOW_RANGE = Long.MAX_VALUE - Integer.MAX_VALUE;
+
+ /**
+ * Bit 127 = final
+ */
+ private static final long T1_FINAL = 1L << 63;
+
+ /**
+ * Bit 126 = first
+ */
+ private static final long T1_FIRST = 1L << 62;
+
+ /**
+ * UBI uses a 128 bit tweak
+ */
+ private long tweak[] = new long[2];
+
+ /**
+ * Whether 64 bit position exceeded
+ */
+ private boolean extendedPosition;
+
+ public UbiTweak()
+ {
+ reset();
+ }
+
+ public void reset(UbiTweak tweak)
+ {
+ this.tweak = Arrays.clone(tweak.tweak, this.tweak);
+ this.extendedPosition = tweak.extendedPosition;
+ }
+
+ public void reset()
+ {
+ tweak[0] = 0;
+ tweak[1] = 0;
+ extendedPosition = false;
+ setFirst(true);
+ }
+
+ public void setType(int type)
+ {
+ // Bits 120..125 = type
+ tweak[1] = (tweak[1] & 0xFFFFFFC000000000L) | ((type & 0x3FL) << 56);
+ }
+
+ public int getType()
+ {
+ return (int)((tweak[1] >>> 56) & 0x3FL);
+ }
+
+ public void setFirst(boolean first)
+ {
+ if (first)
+ {
+ tweak[1] |= T1_FIRST;
+ }
+ else
+ {
+ tweak[1] &= ~T1_FIRST;
+ }
+ }
+
+ public boolean isFirst()
+ {
+ return ((tweak[1] & T1_FIRST) != 0);
+ }
+
+ public void setFinal(boolean last)
+ {
+ if (last)
+ {
+ tweak[1] |= T1_FINAL;
+ }
+ else
+ {
+ tweak[1] &= ~T1_FINAL;
+ }
+ }
+
+ public boolean isFinal()
+ {
+ return ((tweak[1] & T1_FINAL) != 0);
+ }
+
+ /**
+ * Advances the position in the tweak by the specified value.
+ */
+ public void advancePosition(int advance)
+ {
+ // Bits 0..95 = position
+ if (extendedPosition)
+ {
+ long[] parts = new long[3];
+ parts[0] = tweak[0] & 0xFFFFFFFFL;
+ parts[1] = (tweak[0] >>> 32) & 0xFFFFFFFFL;
+ parts[2] = tweak[1] & 0xFFFFFFFFL;
+
+ long carry = advance;
+ for (int i = 0; i < parts.length; i++)
+ {
+ carry += parts[i];
+ parts[i] = carry;
+ carry >>>= 32;
+ }
+ tweak[0] = ((parts[1] & 0xFFFFFFFFL) << 32) | (parts[0] & 0xFFFFFFFFL);
+ tweak[1] = (tweak[1] & 0xFFFFFFFF00000000L) | (parts[2] & 0xFFFFFFFFL);
+ }
+ else
+ {
+ long position = tweak[0];
+ position += advance;
+ tweak[0] = position;
+ if (position > LOW_RANGE)
+ {
+ extendedPosition = true;
+ }
+ }
+ }
+
+ public long[] getWords()
+ {
+ return tweak;
+ }
+
+ public String toString()
+ {
+ return getType() + " first: " + isFirst() + ", final: " + isFinal();
+ }
+
+ }
+
+ /**
+ * The Unique Block Iteration chaining mode.
+ */
+ // TODO: This might be better as methods...
+ private class UBI
+ {
+ private final UbiTweak tweak = new UbiTweak();
+
+ /**
+ * Buffer for the current block of message data
+ */
+ private byte[] currentBlock;
+
+ /**
+ * Offset into the current message block
+ */
+ private int currentOffset;
+
+ /**
+ * Buffer for message words for feedback into encrypted block
+ */
+ private long[] message;
+
+ public UBI(int blockSize)
+ {
+ currentBlock = new byte[blockSize];
+ message = new long[currentBlock.length / 8];
+ }
+
+ public void reset(UBI ubi)
+ {
+ currentBlock = Arrays.clone(ubi.currentBlock, currentBlock);
+ currentOffset = ubi.currentOffset;
+ message = Arrays.clone(ubi.message, this.message);
+ tweak.reset(ubi.tweak);
+ }
+
+ public void reset(int type)
+ {
+ tweak.reset();
+ tweak.setType(type);
+ currentOffset = 0;
+ }
+
+ public void update(byte[] value, int offset, int len, long[] output)
+ {
+ /*
+ * Buffer complete blocks for the underlying Threefish cipher, only flushing when there
+ * are subsequent bytes (last block must be processed in doFinal() with final=true set).
+ */
+ int copied = 0;
+ while (len > copied)
+ {
+ if (currentOffset == currentBlock.length)
+ {
+ processBlock(output);
+ tweak.setFirst(false);
+ currentOffset = 0;
+ }
+
+ int toCopy = Math.min((len - copied), currentBlock.length - currentOffset);
+ System.arraycopy(value, offset + copied, currentBlock, currentOffset, toCopy);
+ copied += toCopy;
+ currentOffset += toCopy;
+ tweak.advancePosition(toCopy);
+ }
+ }
+
+ private void processBlock(long[] output)
+ {
+ threefish.init(true, chain, tweak.getWords());
+ for (int i = 0; i < message.length; i++)
+ {
+ message[i] = ThreefishEngine.bytesToWord(currentBlock, i * 8);
+ }
+
+ threefish.processBlock(message, output);
+
+ for (int i = 0; i < output.length; i++)
+ {
+ output[i] ^= message[i];
+ }
+ }
+
+ public void doFinal(long[] output)
+ {
+ // Pad remainder of current block with zeroes
+ for (int i = currentOffset; i < currentBlock.length; i++)
+ {
+ currentBlock[i] = 0;
+ }
+
+ tweak.setFinal(true);
+ processBlock(output);
+ }
+
+ }
+
+ /**
+ * Underlying Threefish tweakable block cipher
+ */
+ final ThreefishEngine threefish;
+
+ /**
+ * Size of the digest output, in bytes
+ */
+ private final int outputSizeBytes;
+
+ /**
+ * The current chaining/state value
+ */
+ long[] chain;
+
+ /**
+ * The initial state value
+ */
+ private long[] initialState;
+
+ /**
+ * The (optional) key parameter
+ */
+ private byte[] key;
+
+ /**
+ * Parameters to apply prior to the message
+ */
+ private Parameter[] preMessageParameters;
+
+ /**
+ * Parameters to apply after the message, but prior to output
+ */
+ private Parameter[] postMessageParameters;
+
+ /**
+ * The current UBI operation
+ */
+ private final UBI ubi;
+
+ /**
+ * Buffer for single byte update method
+ */
+ private final byte[] singleByte = new byte[1];
+
+ /**
+ * Constructs a Skein engine.
+ *
+ * @param blockSizeBits the internal state size in bits - one of {@link #SKEIN_256}, {@link #SKEIN_512} or
+ * {@link #SKEIN_1024}.
+ * @param outputSizeBits the output/digest size to produce in bits, which must be an integral number of
+ * bytes.
+ */
+ public SkeinEngine(int blockSizeBits, int outputSizeBits)
+ {
+ if (outputSizeBits % 8 != 0)
+ {
+ throw new IllegalArgumentException("Output size must be a multiple of 8 bits. :" + outputSizeBits);
+ }
+ // TODO: Prevent digest sizes > block size?
+ this.outputSizeBytes = outputSizeBits / 8;
+
+ this.threefish = new ThreefishEngine(blockSizeBits);
+ this.ubi = new UBI(threefish.getBlockSize());
+ }
+
+ /**
+ * Creates a SkeinEngine as an exact copy of an existing instance.
+ */
+ public SkeinEngine(SkeinEngine engine)
+ {
+ this(engine.getBlockSize() * 8, engine.getOutputSize() * 8);
+ copyIn(engine);
+ }
+
+ private void copyIn(SkeinEngine engine)
+ {
+ this.ubi.reset(engine.ubi);
+ this.chain = Arrays.clone(engine.chain, this.chain);
+ this.initialState = Arrays.clone(engine.initialState, this.initialState);
+ this.key = Arrays.clone(engine.key, this.key);
+ this.preMessageParameters = clone(engine.preMessageParameters, this.preMessageParameters);
+ this.postMessageParameters = clone(engine.postMessageParameters, this.postMessageParameters);
+ }
+
+ private static Parameter[] clone(Parameter[] data, Parameter[] existing)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ if ((existing == null) || (existing.length != data.length))
+ {
+ existing = new Parameter[data.length];
+ }
+ System.arraycopy(data, 0, existing, 0, existing.length);
+ return existing;
+ }
+
+ public Memoable copy()
+ {
+ return new SkeinEngine(this);
+ }
+
+ public void reset(Memoable other)
+ {
+ SkeinEngine s = (SkeinEngine)other;
+ if ((getBlockSize() != s.getBlockSize()) || (outputSizeBytes != s.outputSizeBytes))
+ {
+ throw new IllegalArgumentException("Incompatible parameters in provided SkeinEngine.");
+ }
+ copyIn(s);
+ }
+
+ public int getOutputSize()
+ {
+ return outputSizeBytes;
+ }
+
+ public int getBlockSize()
+ {
+ return threefish.getBlockSize();
+ }
+
+ /**
+ * Initialises the Skein engine with the provided parameters. See {@link SkeinParameters} for
+ * details on the parameterisation of the Skein hash function.
+ *
+ * @param params the parameters to apply to this engine, or <code>null</code> to use no parameters.
+ */
+ public void init(SkeinParameters params)
+ {
+ this.chain = null;
+ this.key = null;
+ this.preMessageParameters = null;
+ this.postMessageParameters = null;
+
+ if (params != null)
+ {
+ byte[] key = params.getKey();
+ if (key.length < 16)
+ {
+ throw new IllegalArgumentException("Skein key must be at least 128 bits.");
+ }
+ initParams(params.getParameters());
+ }
+ createInitialState();
+
+ // Initialise message block
+ ubiInit(PARAM_TYPE_MESSAGE);
+ }
+
+ private void initParams(Hashtable parameters)
+ {
+ Enumeration keys = parameters.keys();
+ final Vector pre = new Vector();
+ final Vector post = new Vector();
+
+ while (keys.hasMoreElements())
+ {
+ Integer type = (Integer)keys.nextElement();
+ byte[] value = (byte[])parameters.get(type);
+
+ if (type.intValue() == PARAM_TYPE_KEY)
+ {
+ this.key = value;
+ }
+ else if (type.intValue() < PARAM_TYPE_MESSAGE)
+ {
+ pre.addElement(new Parameter(type.intValue(), value));
+ }
+ else
+ {
+ post.addElement(new Parameter(type.intValue(), value));
+ }
+ }
+ preMessageParameters = new Parameter[pre.size()];
+ pre.copyInto(preMessageParameters);
+ sort(preMessageParameters);
+
+ postMessageParameters = new Parameter[post.size()];
+ post.copyInto(postMessageParameters);
+ sort(postMessageParameters);
+ }
+
+ private static void sort(Parameter[] params)
+ {
+ if (params == null)
+ {
+ return;
+ }
+ // Insertion sort, for Java 1.1 compatibility
+ for (int i = 1; i < params.length; i++)
+ {
+ Parameter param = params[i];
+ int hole = i;
+ while (hole > 0 && param.getType() < params[hole - 1].getType())
+ {
+ params[hole] = params[hole - 1];
+ hole = hole - 1;
+ }
+ params[hole] = param;
+ }
+ }
+
+ /**
+ * Calculate the initial (pre message block) chaining state.
+ */
+ private void createInitialState()
+ {
+ long[] precalc = (long[])INITIAL_STATES.get(variantIdentifier(getBlockSize(), getOutputSize()));
+ if ((key == null) && (precalc != null))
+ {
+ // Precalculated UBI(CFG)
+ chain = Arrays.clone(precalc);
+ }
+ else
+ {
+ // Blank initial state
+ chain = new long[getBlockSize() / 8];
+
+ // Process key block
+ if (key != null)
+ {
+ ubiComplete(SkeinParameters.PARAM_TYPE_KEY, key);
+ }
+
+ // Process configuration block
+ ubiComplete(PARAM_TYPE_CONFIG, new Configuration(outputSizeBytes * 8).getBytes());
+ }
+
+ // Process additional pre-message parameters
+ if (preMessageParameters != null)
+ {
+ for (int i = 0; i < preMessageParameters.length; i++)
+ {
+ Parameter param = preMessageParameters[i];
+ ubiComplete(param.getType(), param.getValue());
+ }
+ }
+ initialState = Arrays.clone(chain);
+ }
+
+ /**
+ * Reset the engine to the initial state (with the key and any pre-message parameters , ready to
+ * accept message input.
+ */
+ public void reset()
+ {
+ System.arraycopy(initialState, 0, chain, 0, chain.length);
+
+ ubiInit(PARAM_TYPE_MESSAGE);
+ }
+
+ private void ubiComplete(int type, byte[] value)
+ {
+ ubiInit(type);
+ this.ubi.update(value, 0, value.length, chain);
+ ubiFinal();
+ }
+
+ private void ubiInit(int type)
+ {
+ this.ubi.reset(type);
+ }
+
+ private void ubiFinal()
+ {
+ ubi.doFinal(chain);
+ }
+
+ private void checkInitialised()
+ {
+ if (this.ubi == null)
+ {
+ throw new IllegalArgumentException("Skein engine is not initialised.");
+ }
+ }
+
+ public void update(byte in)
+ {
+ singleByte[0] = in;
+ update(singleByte, 0, 1);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ checkInitialised();
+ ubi.update(in, inOff, len, chain);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ checkInitialised();
+ if (out.length < (outOff + outputSizeBytes))
+ {
+ throw new DataLengthException("Output buffer is too short to hold output of " + outputSizeBytes + " bytes");
+ }
+
+ // Finalise message block
+ ubiFinal();
+
+ // Process additional post-message parameters
+ if (postMessageParameters != null)
+ {
+ for (int i = 0; i < postMessageParameters.length; i++)
+ {
+ Parameter param = postMessageParameters[i];
+ ubiComplete(param.getType(), param.getValue());
+ }
+ }
+
+ // Perform the output transform
+ final int blockSize = getBlockSize();
+ final int blocksRequired = ((outputSizeBytes + blockSize - 1) / blockSize);
+ for (int i = 0; i < blocksRequired; i++)
+ {
+ final int toWrite = Math.min(blockSize, outputSizeBytes - (i * blockSize));
+ output(i, out, outOff + (i * blockSize), toWrite);
+ }
+
+ reset();
+
+ return outputSizeBytes;
+ }
+
+ private void output(long outputSequence, byte[] out, int outOff, int outputBytes)
+ {
+ byte[] currentBytes = new byte[8];
+ ThreefishEngine.wordToBytes(outputSequence, currentBytes, 0);
+
+ // Output is a sequence of UBI invocations all of which use and preserve the pre-output
+ // state
+ long[] outputWords = new long[chain.length];
+ ubiInit(PARAM_TYPE_OUTPUT);
+ this.ubi.update(currentBytes, 0, currentBytes.length, outputWords);
+ ubi.doFinal(outputWords);
+
+ final int wordsRequired = ((outputBytes + 8 - 1) / 8);
+ for (int i = 0; i < wordsRequired; i++)
+ {
+ int toWrite = Math.min(8, outputBytes - (i * 8));
+ if (toWrite == 8)
+ {
+ ThreefishEngine.wordToBytes(outputWords[i], out, outOff + (i * 8));
+ }
+ else
+ {
+ ThreefishEngine.wordToBytes(outputWords[i], currentBytes, 0);
+ System.arraycopy(currentBytes, 0, out, outOff + (i * 8), toWrite);
+ }
+ }
+ }
+
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/digests/package.html
deleted file mode 100644
index 0a0d95c..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Message digest classes.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalDecryptor.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalDecryptor.java
index c8c548e..19c0beb 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalDecryptor.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalDecryptor.java
@@ -43,6 +43,6 @@ public class ECElGamalDecryptor
ECPoint tmp = pair.getX().multiply(key.getD());
- return pair.getY().add(tmp.negate());
+ return pair.getY().add(tmp.negate()).normalize();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java
index e5569a8..2a0b78d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECElGamalEncryptor.java
@@ -6,7 +6,6 @@ import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECPoint;
/**
@@ -69,6 +68,6 @@ public class ECElGamalEncryptor
ECPoint gamma = g.multiply(k);
ECPoint phi = key.getQ().multiply(k).add(point);
- return new ECPair(gamma, phi);
+ return new ECPair(gamma.normalize(), phi.normalize());
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java
new file mode 100644
index 0000000..e35e077
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECFixedTransform.java
@@ -0,0 +1,71 @@
+package org.bouncycastle.crypto.ec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.math.ec.ECPoint;
+
+/**
+ * this transforms the original randomness used for an ElGamal encryption by a fixed value.
+ */
+public class ECFixedTransform
+ implements ECPairFactorTransform
+{
+ private ECPublicKeyParameters key;
+
+ private BigInteger k;
+
+ public ECFixedTransform(BigInteger k)
+ {
+ this.k = k;
+ }
+
+ /**
+ * initialise the underlying EC ElGamal engine.
+ *
+ * @param param the necessary EC key parameters.
+ */
+ public void init(
+ CipherParameters param)
+ {
+ if (!(param instanceof ECPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("ECPublicKeyParameters are required for fixed transform.");
+ }
+
+ this.key = (ECPublicKeyParameters)param;
+ }
+
+ /**
+ * Transform an existing cipher test pair using the ElGamal algorithm. Note: it is assumed this
+ * transform has been initialised with the same public key that was used to create the original
+ * cipher text.
+ *
+ * @param cipherText the EC point to process.
+ * @return returns a new ECPair representing the result of the process.
+ */
+ public ECPair transform(ECPair cipherText)
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("ECFixedTransform not initialised");
+ }
+
+ ECPoint g = key.getParameters().getG();
+ ECPoint gamma = g.multiply(k);
+ ECPoint phi = key.getQ().multiply(k).add(cipherText.getY());
+
+ return new ECPair(cipherText.getX().add(gamma).normalize(), phi.normalize());
+ }
+
+ /**
+ * Return the last transform value used by the transform
+ *
+ * @return a BigInteger representing k value.
+ */
+ public BigInteger getTransformValue()
+ {
+ return k;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java
index 32ba070..74016c1 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewPublicKeyTransform.java
@@ -69,6 +69,6 @@ public class ECNewPublicKeyTransform
ECPoint gamma = g.multiply(k);
ECPoint phi = key.getQ().multiply(k).add(cipherText.getY());
- return new ECPair(gamma, phi);
+ return new ECPair(gamma.normalize(), phi.normalize());
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java
index b037984..b293759 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECNewRandomnessTransform.java
@@ -12,11 +12,13 @@ import org.bouncycastle.math.ec.ECPoint;
* this transforms the original randomness used for an ElGamal encryption.
*/
public class ECNewRandomnessTransform
- implements ECPairTransform
+ implements ECPairFactorTransform
{
private ECPublicKeyParameters key;
private SecureRandom random;
+ private BigInteger lastK;
+
/**
* initialise the underlying EC ElGamal engine.
*
@@ -71,6 +73,18 @@ public class ECNewRandomnessTransform
ECPoint gamma = g.multiply(k);
ECPoint phi = key.getQ().multiply(k).add(cipherText.getY());
- return new ECPair(cipherText.getX().add(gamma), phi);
+ lastK = k;
+
+ return new ECPair(cipherText.getX().add(gamma).normalize(), phi.normalize());
+ }
+
+ /**
+ * Return the last random value generated for a transform
+ *
+ * @return a BigInteger representing the last random value.
+ */
+ public BigInteger getTransformValue()
+ {
+ return lastK;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECPair.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECPair.java
index d910f3c..ea3b4b9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECPair.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECPair.java
@@ -23,16 +23,18 @@ public class ECPair
return y;
}
- public byte[] getEncoded()
+ public boolean equals(ECPair other)
{
- byte[] xEnc = x.getEncoded();
- byte[] yEnc = y.getEncoded();
-
- byte[] full = new byte[xEnc.length + yEnc.length];
+ return other.getX().equals(getX()) && other.getY().equals(getY());
+ }
- System.arraycopy(xEnc, 0, full, 0, xEnc.length);
- System.arraycopy(yEnc, 0, full, xEnc.length, yEnc.length);
+ public boolean equals(Object other)
+ {
+ return other instanceof ECPair ? equals((ECPair)other) : false;
+ }
- return full;
+ public int hashCode()
+ {
+ return x.hashCode() + 37 * y.hashCode();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECPairFactorTransform.java b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECPairFactorTransform.java
new file mode 100644
index 0000000..be48551
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/ec/ECPairFactorTransform.java
@@ -0,0 +1,14 @@
+package org.bouncycastle.crypto.ec;
+
+import java.math.BigInteger;
+
+public interface ECPairFactorTransform
+ extends ECPairTransform
+{
+ /**
+ * Return the last value used to calculated a transform.
+ *
+ * @return a BigInteger representing the last transform value used.
+ */
+ BigInteger getTransformValue();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/ec/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/ec/package.html
deleted file mode 100644
index d50edcf..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/ec/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Lightweight EC point operations, such as EC ElGamal and randomness transforms.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/package.html
deleted file mode 100644
index fc56f63..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Block encodings for asymmetric ciphers.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/ChaChaEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/ChaChaEngine.java
new file mode 100644
index 0000000..2d1de39
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/ChaChaEngine.java
@@ -0,0 +1,186 @@
+package org.bouncycastle.crypto.engines;
+
+import org.bouncycastle.crypto.util.Pack;
+
+/**
+ * Implementation of Daniel J. Bernstein's ChaCha stream cipher.
+ */
+public class ChaChaEngine extends Salsa20Engine
+{
+
+ /**
+ * Creates a 20 rounds ChaCha engine.
+ */
+ public ChaChaEngine()
+ {
+ super();
+ }
+
+ /**
+ * Creates a ChaCha engine with a specific number of rounds.
+ * @param rounds the number of rounds (must be an even number).
+ */
+ public ChaChaEngine(int rounds)
+ {
+ super(rounds);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "ChaCha" + rounds;
+ }
+
+ protected void advanceCounter()
+ {
+ if (++engineState[12] == 0)
+ {
+ ++engineState[13];
+ }
+ }
+
+ protected void resetCounter()
+ {
+ engineState[12] = engineState[13] = 0;
+ }
+
+ protected void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ if ((keyBytes.length != 16) && (keyBytes.length != 32))
+ {
+ throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key");
+ }
+
+ int offset = 0;
+ byte[] constants;
+
+ // Key
+ engineState[4] = Pack.littleEndianToInt(keyBytes, 0);
+ engineState[5] = Pack.littleEndianToInt(keyBytes, 4);
+ engineState[6] = Pack.littleEndianToInt(keyBytes, 8);
+ engineState[7] = Pack.littleEndianToInt(keyBytes, 12);
+
+ if (keyBytes.length == 32)
+ {
+ constants = sigma;
+ offset = 16;
+ } else
+ {
+ constants = tau;
+ }
+
+ engineState[8] = Pack.littleEndianToInt(keyBytes, offset);
+ engineState[9] = Pack.littleEndianToInt(keyBytes, offset + 4);
+ engineState[10] = Pack.littleEndianToInt(keyBytes, offset + 8);
+ engineState[11] = Pack.littleEndianToInt(keyBytes, offset + 12);
+
+ engineState[0] = Pack.littleEndianToInt(constants, 0);
+ engineState[1] = Pack.littleEndianToInt(constants, 4);
+ engineState[2] = Pack.littleEndianToInt(constants, 8);
+ engineState[3] = Pack.littleEndianToInt(constants, 12);
+
+ // Counter
+ engineState[12] = engineState[13] = 0;
+
+ // IV
+ engineState[14] = Pack.littleEndianToInt(ivBytes, 0);
+ engineState[15] = Pack.littleEndianToInt(ivBytes, 4);
+ }
+
+ protected void generateKeyStream(byte[] output)
+ {
+ chachaCore(rounds, engineState, x);
+ Pack.intToLittleEndian(x, output, 0);
+ }
+
+ /**
+ * ChacCha function
+ *
+ * @param input input data
+ *
+ * @return keystream
+ */
+ public static void chachaCore(int rounds, int[] input, int[] x)
+ {
+ if (input.length != 16) {
+ throw new IllegalArgumentException();
+ }
+ if (x.length != 16) {
+ throw new IllegalArgumentException();
+ }
+ if (rounds % 2 != 0) {
+ throw new IllegalArgumentException("Number of rounds must be even");
+ }
+
+ int x00 = input[ 0];
+ int x01 = input[ 1];
+ int x02 = input[ 2];
+ int x03 = input[ 3];
+ int x04 = input[ 4];
+ int x05 = input[ 5];
+ int x06 = input[ 6];
+ int x07 = input[ 7];
+ int x08 = input[ 8];
+ int x09 = input[ 9];
+ int x10 = input[10];
+ int x11 = input[11];
+ int x12 = input[12];
+ int x13 = input[13];
+ int x14 = input[14];
+ int x15 = input[15];
+
+ for (int i = rounds; i > 0; i -= 2)
+ {
+ x00 += x04; x12 = rotl(x12 ^ x00, 16);
+ x08 += x12; x04 = rotl(x04 ^ x08, 12);
+ x00 += x04; x12 = rotl(x12 ^ x00, 8);
+ x08 += x12; x04 = rotl(x04 ^ x08, 7);
+ x01 += x05; x13 = rotl(x13 ^ x01, 16);
+ x09 += x13; x05 = rotl(x05 ^ x09, 12);
+ x01 += x05; x13 = rotl(x13 ^ x01, 8);
+ x09 += x13; x05 = rotl(x05 ^ x09, 7);
+ x02 += x06; x14 = rotl(x14 ^ x02, 16);
+ x10 += x14; x06 = rotl(x06 ^ x10, 12);
+ x02 += x06; x14 = rotl(x14 ^ x02, 8);
+ x10 += x14; x06 = rotl(x06 ^ x10, 7);
+ x03 += x07; x15 = rotl(x15 ^ x03, 16);
+ x11 += x15; x07 = rotl(x07 ^ x11, 12);
+ x03 += x07; x15 = rotl(x15 ^ x03, 8);
+ x11 += x15; x07 = rotl(x07 ^ x11, 7);
+ x00 += x05; x15 = rotl(x15 ^ x00, 16);
+ x10 += x15; x05 = rotl(x05 ^ x10, 12);
+ x00 += x05; x15 = rotl(x15 ^ x00, 8);
+ x10 += x15; x05 = rotl(x05 ^ x10, 7);
+ x01 += x06; x12 = rotl(x12 ^ x01, 16);
+ x11 += x12; x06 = rotl(x06 ^ x11, 12);
+ x01 += x06; x12 = rotl(x12 ^ x01, 8);
+ x11 += x12; x06 = rotl(x06 ^ x11, 7);
+ x02 += x07; x13 = rotl(x13 ^ x02, 16);
+ x08 += x13; x07 = rotl(x07 ^ x08, 12);
+ x02 += x07; x13 = rotl(x13 ^ x02, 8);
+ x08 += x13; x07 = rotl(x07 ^ x08, 7);
+ x03 += x04; x14 = rotl(x14 ^ x03, 16);
+ x09 += x14; x04 = rotl(x04 ^ x09, 12);
+ x03 += x04; x14 = rotl(x14 ^ x03, 8);
+ x09 += x14; x04 = rotl(x04 ^ x09, 7);
+
+ }
+
+ x[ 0] = x00 + input[ 0];
+ x[ 1] = x01 + input[ 1];
+ x[ 2] = x02 + input[ 2];
+ x[ 3] = x03 + input[ 3];
+ x[ 4] = x04 + input[ 4];
+ x[ 5] = x05 + input[ 5];
+ x[ 6] = x06 + input[ 6];
+ x[ 7] = x07 + input[ 7];
+ x[ 8] = x08 + input[ 8];
+ x[ 9] = x09 + input[ 9];
+ x[10] = x10 + input[10];
+ x[11] = x11 + input[11];
+ x[12] = x12 + input[12];
+ x[13] = x13 + input[13];
+ x[14] = x14 + input[14];
+ x[15] = x15 + input[15];
+ }
+
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/Grain128Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/Grain128Engine.java
index 6b3da1c..89271f0 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/Grain128Engine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/Grain128Engine.java
@@ -89,8 +89,7 @@ public class Grain128Engine
System.arraycopy(iv, 0, workingIV, 0, iv.length);
System.arraycopy(key.getKey(), 0, workingKey, 0, key.getKey().length);
- setKey(workingKey, workingIV);
- initGrain();
+ reset();
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/Grainv1Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/Grainv1Engine.java
index c3baaec..782a93c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/Grainv1Engine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/Grainv1Engine.java
@@ -89,8 +89,7 @@ public class Grainv1Engine
System.arraycopy(iv, 0, workingIV, 0, iv.length);
System.arraycopy(key.getKey(), 0, workingKey, 0, key.getKey().length);
- setKey(workingKey, workingIV);
- initGrain();
+ reset();
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/HC128Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/HC128Engine.java
index 69da0f0..015e49e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/HC128Engine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/HC128Engine.java
@@ -118,6 +118,7 @@ public class HC128Engine
"The key must be 128 bits long");
}
+ idx = 0;
cnt = 0;
int[] w = new int[1280];
@@ -246,7 +247,6 @@ public class HC128Engine
public void reset()
{
- idx = 0;
init();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/HC256Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/HC256Engine.java
index 538d244..8bd7e9d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/HC256Engine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/HC256Engine.java
@@ -99,6 +99,7 @@ public class HC256Engine
iv = newIV;
}
+ idx = 0;
cnt = 0;
int[] w = new int[2560];
@@ -226,7 +227,6 @@ public class HC256Engine
public void reset()
{
- idx = 0;
init();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/NullEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/NullEngine.java
index 95a395a..1ad2c9d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/NullEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/NullEngine.java
@@ -12,14 +12,25 @@ import org.bouncycastle.crypto.OutputLengthException;
public class NullEngine implements BlockCipher
{
private boolean initialised;
- protected static final int BLOCK_SIZE = 1;
-
+ protected static final int DEFAULT_BLOCK_SIZE = 1;
+ private final int blockSize;
+
/**
- * Standard constructor.
+ * Constructs a null engine with a block size of 1 byte.
*/
public NullEngine()
{
- super();
+ this(DEFAULT_BLOCK_SIZE);
+ }
+
+ /**
+ * Constructs a null engine with a specific block size.
+ *
+ * @param blockSize the block size in bytes.
+ */
+ public NullEngine(int blockSize)
+ {
+ this.blockSize = blockSize;
}
/* (non-Javadoc)
@@ -44,7 +55,7 @@ public class NullEngine implements BlockCipher
*/
public int getBlockSize()
{
- return BLOCK_SIZE;
+ return blockSize;
}
/* (non-Javadoc)
@@ -57,22 +68,22 @@ public class NullEngine implements BlockCipher
{
throw new IllegalStateException("Null engine not initialised");
}
- if ((inOff + BLOCK_SIZE) > in.length)
- {
- throw new DataLengthException("input buffer too short");
- }
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < blockSize; ++i)
+ {
+ out[outOff + i] = in[inOff + i];
+ }
- if ((outOff + BLOCK_SIZE) > out.length)
- {
- throw new OutputLengthException("output buffer too short");
- }
-
- for (int i = 0; i < BLOCK_SIZE; ++i)
- {
- out[outOff + i] = in[inOff + i];
- }
-
- return BLOCK_SIZE;
+ return blockSize;
}
/* (non-Javadoc)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
index 540bd25..cfd86fb 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
@@ -85,7 +85,7 @@ public class RFC3394WrapEngine
byte[] buf = new byte[8 + iv.length];
System.arraycopy(iv, 0, block, 0, iv.length);
- System.arraycopy(in, 0, block, iv.length, inLen);
+ System.arraycopy(in, inOff, block, iv.length, inLen);
engine.init(true, param);
@@ -137,8 +137,8 @@ public class RFC3394WrapEngine
byte[] a = new byte[iv.length];
byte[] buf = new byte[8 + iv.length];
- System.arraycopy(in, 0, a, 0, iv.length);
- System.arraycopy(in, iv.length, block, 0, inLen - iv.length);
+ System.arraycopy(in, inOff, a, 0, iv.length);
+ System.arraycopy(in, inOff + iv.length, block, 0, inLen - iv.length);
engine.init(false, param);
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 e7fb943..c9765bf 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java
@@ -1,5 +1,8 @@
package org.bouncycastle.crypto.engines;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
@@ -8,16 +11,13 @@ import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.util.BigIntegers;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
/**
* this does your basic RSA algorithm with blinding
*/
public class RSABlindedEngine
implements AsymmetricBlockCipher
{
- private static BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
private RSACoreEngine core = new RSACoreEngine();
private RSAKeyParameters key;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java
index 6d4210d..2d6140d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/Salsa20Engine.java
@@ -13,27 +13,28 @@ import org.bouncycastle.util.Strings;
/**
* Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
*/
-
public class Salsa20Engine
implements StreamCipher
{
+ public final static int DEFAULT_ROUNDS = 20;
+
/** Constants */
private final static int STATE_SIZE = 16; // 16, 32 bit ints = 64 bytes
- private final static byte[]
+ protected final static byte[]
sigma = Strings.toByteArray("expand 32-byte k"),
tau = Strings.toByteArray("expand 16-byte k");
+ protected int rounds;
+
/*
* variables to hold the state of the engine
* during encryption and decryption
*/
private int index = 0;
- private int[] engineState = new int[STATE_SIZE]; // state
- private int[] x = new int[STATE_SIZE] ; // internal buffer
- private byte[] keyStream = new byte[STATE_SIZE * 4], // expanded state, 64 bytes
- workingKey = null,
- workingIV = null;
+ protected int[] engineState = new int[STATE_SIZE]; // state
+ protected int[] x = new int[STATE_SIZE] ; // internal buffer
+ private byte[] keyStream = new byte[STATE_SIZE * 4]; // expanded state, 64 bytes
private boolean initialised = false;
/*
@@ -42,6 +43,28 @@ public class Salsa20Engine
private int cW0, cW1, cW2;
/**
+ * Creates a 20 round Salsa20 engine.
+ */
+ public Salsa20Engine()
+ {
+ this(DEFAULT_ROUNDS);
+ }
+
+ /**
+ * Creates a Salsa20 engine with a specific number of rounds.
+ * @param rounds the number of rounds (must be an even number).
+ */
+ public Salsa20Engine(int rounds)
+ {
+ if (rounds <= 0 || (rounds & 1) != 0)
+ {
+ throw new IllegalArgumentException("'rounds' must be a positive, even number");
+ }
+
+ this.rounds = rounds;
+ }
+
+ /**
* initialise a Salsa20 cipher.
*
* @param forEncryption whether or not we are for encryption.
@@ -61,34 +84,43 @@ public class Salsa20Engine
if (!(params instanceof ParametersWithIV))
{
- throw new IllegalArgumentException("Salsa20 Init parameters must include an IV");
+ throw new IllegalArgumentException(getAlgorithmName() + " Init parameters must include an IV");
}
ParametersWithIV ivParams = (ParametersWithIV) params;
byte[] iv = ivParams.getIV();
-
- if (iv == null || iv.length != 8)
+ if (iv == null || iv.length != getNonceSize())
{
- throw new IllegalArgumentException("Salsa20 requires exactly 8 bytes of IV");
+ throw new IllegalArgumentException(getAlgorithmName() + " requires exactly " + getNonceSize()
+ + " bytes of IV");
}
if (!(ivParams.getParameters() instanceof KeyParameter))
{
- throw new IllegalArgumentException("Salsa20 Init parameters must include a key");
+ throw new IllegalArgumentException(getAlgorithmName() + " Init parameters must include a key");
}
KeyParameter key = (KeyParameter) ivParams.getParameters();
- workingKey = key.getKey();
- workingIV = iv;
+ setKey(key.getKey(), iv);
+ reset();
+ initialised = true;
+ }
- setKey(workingKey, workingIV);
+ protected int getNonceSize()
+ {
+ return 8;
}
public String getAlgorithmName()
{
- return "Salsa20";
+ String name = "Salsa20";
+ if (rounds != DEFAULT_ROUNDS)
+ {
+ name += "/" + rounds;
+ }
+ return name;
}
public byte returnByte(byte in)
@@ -101,11 +133,7 @@ public class Salsa20Engine
if (index == 0)
{
generateKeyStream(keyStream);
-
- if (++engineState[8] == 0)
- {
- ++engineState[9];
- }
+ advanceCounter();
}
byte out = (byte)(keyStream[index]^in);
@@ -114,6 +142,14 @@ public class Salsa20Engine
return out;
}
+ protected void advanceCounter()
+ {
+ if (++engineState[8] == 0)
+ {
+ ++engineState[9];
+ }
+ }
+
public void processBytes(
byte[] in,
int inOff,
@@ -123,7 +159,7 @@ public class Salsa20Engine
{
if (!initialised)
{
- throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ throw new IllegalStateException(getAlgorithmName() + " not initialised");
}
if ((inOff + len) > in.length)
@@ -146,11 +182,7 @@ public class Salsa20Engine
if (index == 0)
{
generateKeyStream(keyStream);
-
- if (++engineState[8] == 0)
- {
- ++engineState[9];
- }
+ advanceCounter();
}
out[i+outOff] = (byte)(keyStream[index]^in[i+inOff]);
@@ -160,28 +192,32 @@ public class Salsa20Engine
public void reset()
{
- setKey(workingKey, workingIV);
+ index = 0;
+ resetLimitCounter();
+ resetCounter();
}
- // Private implementation
-
- private void setKey(byte[] keyBytes, byte[] ivBytes)
+ protected void resetCounter()
{
- workingKey = keyBytes;
- workingIV = ivBytes;
+ engineState[8] = engineState[9] = 0;
+ }
- index = 0;
- resetCounter();
+ protected void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ if ((keyBytes.length != 16) && (keyBytes.length != 32)) {
+ throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key");
+ }
+
int offset = 0;
byte[] constants;
// Key
- engineState[1] = Pack.littleEndianToInt(workingKey, 0);
- engineState[2] = Pack.littleEndianToInt(workingKey, 4);
- engineState[3] = Pack.littleEndianToInt(workingKey, 8);
- engineState[4] = Pack.littleEndianToInt(workingKey, 12);
+ engineState[1] = Pack.littleEndianToInt(keyBytes, 0);
+ engineState[2] = Pack.littleEndianToInt(keyBytes, 4);
+ engineState[3] = Pack.littleEndianToInt(keyBytes, 8);
+ engineState[4] = Pack.littleEndianToInt(keyBytes, 12);
- if (workingKey.length == 32)
+ if (keyBytes.length == 32)
{
constants = sigma;
offset = 16;
@@ -191,26 +227,25 @@ public class Salsa20Engine
constants = tau;
}
- engineState[11] = Pack.littleEndianToInt(workingKey, offset);
- engineState[12] = Pack.littleEndianToInt(workingKey, offset+4);
- engineState[13] = Pack.littleEndianToInt(workingKey, offset+8);
- engineState[14] = Pack.littleEndianToInt(workingKey, offset+12);
+ engineState[11] = Pack.littleEndianToInt(keyBytes, offset);
+ engineState[12] = Pack.littleEndianToInt(keyBytes, offset+4);
+ engineState[13] = Pack.littleEndianToInt(keyBytes, offset+8);
+ engineState[14] = Pack.littleEndianToInt(keyBytes, offset+12);
+
engineState[0 ] = Pack.littleEndianToInt(constants, 0);
engineState[5 ] = Pack.littleEndianToInt(constants, 4);
engineState[10] = Pack.littleEndianToInt(constants, 8);
engineState[15] = Pack.littleEndianToInt(constants, 12);
// IV
- engineState[6] = Pack.littleEndianToInt(workingIV, 0);
- engineState[7] = Pack.littleEndianToInt(workingIV, 4);
- engineState[8] = engineState[9] = 0;
-
- initialised = true;
+ engineState[6] = Pack.littleEndianToInt(ivBytes, 0);
+ engineState[7] = Pack.littleEndianToInt(ivBytes, 4);
+ resetCounter();
}
- private void generateKeyStream(byte[] output)
+ protected void generateKeyStream(byte[] output)
{
- salsaCore(20, engineState, x);
+ salsaCore(rounds, engineState, x);
Pack.intToLittleEndian(x, output, 0);
}
@@ -223,50 +258,86 @@ public class Salsa20Engine
*/
public static void salsaCore(int rounds, int[] input, int[] x)
{
- // TODO Exception if rounds odd?
+ if (input.length != 16) {
+ throw new IllegalArgumentException();
+ }
+ if (x.length != 16) {
+ throw new IllegalArgumentException();
+ }
+ if (rounds % 2 != 0) {
+ throw new IllegalArgumentException("Number of rounds must be even");
+ }
- System.arraycopy(input, 0, x, 0, input.length);
+ int x00 = input[ 0];
+ int x01 = input[ 1];
+ int x02 = input[ 2];
+ int x03 = input[ 3];
+ int x04 = input[ 4];
+ int x05 = input[ 5];
+ int x06 = input[ 6];
+ int x07 = input[ 7];
+ int x08 = input[ 8];
+ int x09 = input[ 9];
+ int x10 = input[10];
+ int x11 = input[11];
+ int x12 = input[12];
+ int x13 = input[13];
+ int x14 = input[14];
+ int x15 = input[15];
for (int i = rounds; i > 0; i -= 2)
{
- x[ 4] ^= rotl((x[ 0]+x[12]), 7);
- x[ 8] ^= rotl((x[ 4]+x[ 0]), 9);
- x[12] ^= rotl((x[ 8]+x[ 4]),13);
- x[ 0] ^= rotl((x[12]+x[ 8]),18);
- x[ 9] ^= rotl((x[ 5]+x[ 1]), 7);
- x[13] ^= rotl((x[ 9]+x[ 5]), 9);
- x[ 1] ^= rotl((x[13]+x[ 9]),13);
- x[ 5] ^= rotl((x[ 1]+x[13]),18);
- x[14] ^= rotl((x[10]+x[ 6]), 7);
- x[ 2] ^= rotl((x[14]+x[10]), 9);
- x[ 6] ^= rotl((x[ 2]+x[14]),13);
- x[10] ^= rotl((x[ 6]+x[ 2]),18);
- x[ 3] ^= rotl((x[15]+x[11]), 7);
- x[ 7] ^= rotl((x[ 3]+x[15]), 9);
- x[11] ^= rotl((x[ 7]+x[ 3]),13);
- x[15] ^= rotl((x[11]+x[ 7]),18);
- x[ 1] ^= rotl((x[ 0]+x[ 3]), 7);
- x[ 2] ^= rotl((x[ 1]+x[ 0]), 9);
- x[ 3] ^= rotl((x[ 2]+x[ 1]),13);
- x[ 0] ^= rotl((x[ 3]+x[ 2]),18);
- x[ 6] ^= rotl((x[ 5]+x[ 4]), 7);
- x[ 7] ^= rotl((x[ 6]+x[ 5]), 9);
- x[ 4] ^= rotl((x[ 7]+x[ 6]),13);
- x[ 5] ^= rotl((x[ 4]+x[ 7]),18);
- x[11] ^= rotl((x[10]+x[ 9]), 7);
- x[ 8] ^= rotl((x[11]+x[10]), 9);
- x[ 9] ^= rotl((x[ 8]+x[11]),13);
- x[10] ^= rotl((x[ 9]+x[ 8]),18);
- x[12] ^= rotl((x[15]+x[14]), 7);
- x[13] ^= rotl((x[12]+x[15]), 9);
- x[14] ^= rotl((x[13]+x[12]),13);
- x[15] ^= rotl((x[14]+x[13]),18);
+ x04 ^= rotl((x00+x12), 7);
+ x08 ^= rotl((x04+x00), 9);
+ x12 ^= rotl((x08+x04),13);
+ x00 ^= rotl((x12+x08),18);
+ x09 ^= rotl((x05+x01), 7);
+ x13 ^= rotl((x09+x05), 9);
+ x01 ^= rotl((x13+x09),13);
+ x05 ^= rotl((x01+x13),18);
+ x14 ^= rotl((x10+x06), 7);
+ x02 ^= rotl((x14+x10), 9);
+ x06 ^= rotl((x02+x14),13);
+ x10 ^= rotl((x06+x02),18);
+ x03 ^= rotl((x15+x11), 7);
+ x07 ^= rotl((x03+x15), 9);
+ x11 ^= rotl((x07+x03),13);
+ x15 ^= rotl((x11+x07),18);
+
+ x01 ^= rotl((x00+x03), 7);
+ x02 ^= rotl((x01+x00), 9);
+ x03 ^= rotl((x02+x01),13);
+ x00 ^= rotl((x03+x02),18);
+ x06 ^= rotl((x05+x04), 7);
+ x07 ^= rotl((x06+x05), 9);
+ x04 ^= rotl((x07+x06),13);
+ x05 ^= rotl((x04+x07),18);
+ x11 ^= rotl((x10+x09), 7);
+ x08 ^= rotl((x11+x10), 9);
+ x09 ^= rotl((x08+x11),13);
+ x10 ^= rotl((x09+x08),18);
+ x12 ^= rotl((x15+x14), 7);
+ x13 ^= rotl((x12+x15), 9);
+ x14 ^= rotl((x13+x12),13);
+ x15 ^= rotl((x14+x13),18);
}
- for (int i = 0; i < STATE_SIZE; ++i)
- {
- x[i] += input[i];
- }
+ x[ 0] = x00 + input[ 0];
+ x[ 1] = x01 + input[ 1];
+ x[ 2] = x02 + input[ 2];
+ x[ 3] = x03 + input[ 3];
+ x[ 4] = x04 + input[ 4];
+ x[ 5] = x05 + input[ 5];
+ x[ 6] = x06 + input[ 6];
+ x[ 7] = x07 + input[ 7];
+ x[ 8] = x08 + input[ 8];
+ x[ 9] = x09 + input[ 9];
+ x[10] = x10 + input[10];
+ x[11] = x11 + input[11];
+ x[12] = x12 + input[12];
+ x[13] = x13 + input[13];
+ x[14] = x14 + input[14];
+ x[15] = x15 + input[15];
}
/**
@@ -277,12 +348,12 @@ public class Salsa20Engine
*
* @return rotated x
*/
- private static int rotl(int x, int y)
+ protected static int rotl(int x, int y)
{
return (x << y) | (x >>> -y);
}
- private void resetCounter()
+ private void resetLimitCounter()
{
cW0 = 0;
cW1 = 0;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/Shacal2Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/Shacal2Engine.java
new file mode 100644
index 0000000..b59205d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/Shacal2Engine.java
@@ -0,0 +1,201 @@
+package org.bouncycastle.crypto.engines;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.OutputLengthException;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * Block cipher Shacal2, designed by Helena Handschuh and David Naccache,
+ * based on hash function SHA-256,
+ * using SHA-256-Initialization-Values as data and SHA-256-Data as key.
+ * <p>
+ * A description of Shacal can be found at:
+ * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.3.4066
+ * Best known cryptanalytic (Wikipedia 11.2013):
+ * Related-key rectangle attack on 44-rounds (Jiqiang Lu, Jongsung Kim).
+ * Comments are related to SHA-256-Naming as described in FIPS PUB 180-2
+ * </p>
+ */
+public class Shacal2Engine
+ implements BlockCipher
+{
+ private final static int[] K = { // SHA-256-Constants
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+
+ private static final int BLOCK_SIZE = 32;
+ private boolean forEncryption = false;
+ private static final int ROUNDS = 64;
+
+ private int[] workingKey = null; // expanded key: corresponds to the message block W in FIPS PUB 180-2
+
+ public Shacal2Engine()
+ {
+ }
+
+ public void reset()
+ {
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Shacal2";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public void init(boolean _forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("only simple KeyParameter expected.");
+ }
+ this.forEncryption = _forEncryption;
+ workingKey = new int[64];
+ setKey( ((KeyParameter)params).getKey() );
+ }
+
+ public void setKey(byte[] kb)
+ {
+ if (kb.length == 0 || kb.length > 64 || kb.length < 16 || kb.length % 8 != 0)
+ {
+ throw new IllegalArgumentException("Shacal2-key must be 16 - 64 bytes and multiple of 8");
+ }
+
+ bytes2ints(kb, workingKey, 0, 0);
+
+ for ( int i = 16; i < 64; i++)
+ { // Key-Expansion, implicitly Zero-Padding for 16 > i > kb.length/4
+ workingKey[i] =
+ ( (workingKey[i-2] >>> 17 | workingKey[i-2] << -17) // corresponds to ROTL n(x) of FIPS PUB 180-2
+ ^ (workingKey[i-2] >>> 19 | workingKey[i-2] << -19)
+ ^ (workingKey[i-2] >>> 10) ) // corresponds to sigma1(x)-Function of FIPS PUB 180-2
+ + workingKey[i-7]
+ + ( (workingKey[i-15] >>> 7 | workingKey[i-15] << -7)
+ ^ (workingKey[i-15] >>> 18 | workingKey[i-15] << -18)
+ ^ (workingKey[i-15] >>> 3) ) // corresponds to sigma0(x)-Function of FIPS PUB 180-2
+ + workingKey[i-16];
+ }
+ }
+
+ public void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ int[] block = new int[BLOCK_SIZE / 4];// corresponds to working variables a,b,c,d,e,f,g,h of FIPS PUB 180-2
+ bytes2ints(in, block, inOffset, 0);
+
+ for (int i = 0; i < ROUNDS; i++)
+ {
+ int tmp =
+ (((block[4] >>> 6) | (block[4] << -6))
+ ^ ((block[4] >>> 11) | (block[4] << -11))
+ ^ ((block[4] >>> 25) | (block[4] << -25)))
+ + ((block[4] & block[5]) ^ ((~block[4]) & block[6]))
+ + block[7] + K[i] + workingKey[i]; // corresponds to T1 of FIPS PUB 180-2
+ block[7] = block[6];
+ block[6] = block[5];
+ block[5] = block[4];
+ block[4] = block[3] + tmp;
+ block[3] = block[2];
+ block[2] = block[1];
+ block[1] = block[0];
+ block[0] = tmp
+ + (((block[0] >>> 2) | (block[0] << -2))
+ ^ ((block[0] >>> 13) | (block[0] << -13))
+ ^ ((block[0] >>> 22) | (block[0] << -22)))
+ + ((block[0] & block[2]) ^ (block[0] & block[3]) ^ (block[2] & block[3]));
+ //corresponds to T2 of FIPS PUB 180-2, block[1] and block[2] replaced
+ }
+ ints2bytes(block, out, outOffset);
+ }
+
+ public void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ int[] block = new int[BLOCK_SIZE / 4];
+ bytes2ints(in, block, inOffset, 0);
+ for (int i = ROUNDS - 1; i >-1; i--)
+ {
+ int tmp = block[0] - (((block[1] >>> 2) | (block[1] << -2))
+ ^ ((block[1] >>> 13) | (block[1] << -13))
+ ^ ((block[1] >>> 22) | (block[1] << -22)))
+ - ((block[1] & block[2]) ^ (block[1] & block[3]) ^ (block[2] & block[3])); // T2
+ block[0] = block[1];
+ block[1] = block[2];
+ block[2] = block[3];
+ block[3] = block[4] - tmp;
+ block[4] = block[5];
+ block[5] = block[6];
+ block[6] = block[7];
+ block[7] = tmp - K[i] - workingKey[i]
+ - (((block[4] >>> 6) | (block[4] << -6))
+ ^ ((block[4] >>> 11) | (block[4] << -11))
+ ^ ((block[4] >>> 25) | (block[4] << -25)))
+ - ((block[4] & block[5]) ^ ((~block[4]) & block[6])); // T1
+ }
+ ints2bytes(block, out, outOffset);
+ }
+
+ public int processBlock(byte[] in, int inOffset, byte[] out, int outOffset)
+ throws DataLengthException, IllegalStateException
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("Shacal2 not initialised");
+ }
+
+ if ((inOffset + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOffset + BLOCK_SIZE) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ encryptBlock(in, inOffset, out, outOffset);
+ }
+ else
+ {
+ decryptBlock(in, inOffset, out, outOffset);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ private void bytes2ints(byte[] bytes, int[] block, int bytesPos, int blockPos)
+ {
+ for (int i = blockPos; i < bytes.length / 4; i++)
+ {
+ block[i] = ((bytes[bytesPos++] & 0xFF) << 24)
+ | ((bytes[bytesPos++] & 0xFF) << 16)
+ | ((bytes[bytesPos++] & 0xFF) << 8)
+ | (bytes[bytesPos++] & 0xFF);
+ }
+ }
+
+ private void ints2bytes(int[] block, byte[] out, int pos)
+ {
+ for (int i = 0; i < block.length; i++)
+ {
+ out[pos++] = (byte)(block[i] >>> 24);
+ out[pos++] = (byte)(block[i] >>> 16);
+ out[pos++] = (byte)(block[i] >>> 8);
+ out[pos++] = (byte)block[i];
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/TEAEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/TEAEngine.java
index b09f189..ac65443 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/TEAEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/TEAEngine.java
@@ -105,6 +105,11 @@ public class TEAEngine
private void setKey(
byte[] key)
{
+ if (key.length != 16)
+ {
+ throw new IllegalArgumentException("Key size must be 128 bits.");
+ }
+
_a = bytesToInt(key, 0);
_b = bytesToInt(key, 4);
_c = bytesToInt(key, 8);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/ThreefishEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/ThreefishEngine.java
new file mode 100644
index 0000000..74bccfe
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/ThreefishEngine.java
@@ -0,0 +1,1494 @@
+package org.bouncycastle.crypto.engines;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.TweakableBlockCipherParameters;
+
+/**
+ * Implementation of the Threefish tweakable large block cipher in 256, 512 and 1024 bit block
+ * sizes.
+ * <p/>
+ * This is the 1.3 version of Threefish defined in the Skein hash function submission to the NIST
+ * SHA-3 competition in October 2010.
+ * <p/>
+ * Threefish was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+ * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+ * <p/>
+ * This implementation inlines all round functions, unrolls 8 rounds, and uses 1.2k of static tables
+ * to speed up key schedule injection. <br>
+ * 2 x block size state is retained by each cipher instance.
+ */
+public class ThreefishEngine
+ implements BlockCipher
+{
+ /**
+ * 256 bit block size - Threefish-256
+ */
+ public static final int BLOCKSIZE_256 = 256;
+ /**
+ * 512 bit block size - Threefish-512
+ */
+ public static final int BLOCKSIZE_512 = 512;
+ /**
+ * 1024 bit block size - Threefish-1024
+ */
+ public static final int BLOCKSIZE_1024 = 1024;
+
+ /**
+ * Size of the tweak in bytes (always 128 bit/16 bytes)
+ */
+ private static final int TWEAK_SIZE_BYTES = 16;
+ private static final int TWEAK_SIZE_WORDS = TWEAK_SIZE_BYTES / 8;
+
+ /**
+ * Rounds in Threefish-256
+ */
+ private static final int ROUNDS_256 = 72;
+ /**
+ * Rounds in Threefish-512
+ */
+ private static final int ROUNDS_512 = 72;
+ /**
+ * Rounds in Threefish-1024
+ */
+ private static final int ROUNDS_1024 = 80;
+
+ /**
+ * Max rounds of any of the variants
+ */
+ private static final int MAX_ROUNDS = ROUNDS_1024;
+
+ /**
+ * Key schedule parity constant
+ */
+ private static final long C_240 = 0x1BD11BDAA9FC1A22L;
+
+ /* Pre-calculated modulo arithmetic tables for key schedule lookups */
+ private static int[] MOD9 = new int[MAX_ROUNDS];
+ private static int[] MOD17 = new int[MOD9.length];
+ private static int[] MOD5 = new int[MOD9.length];
+ private static int[] MOD3 = new int[MOD9.length];
+
+ static
+ {
+ for (int i = 0; i < MOD9.length; i++)
+ {
+ MOD17[i] = i % 17;
+ MOD9[i] = i % 9;
+ MOD5[i] = i % 5;
+ MOD3[i] = i % 3;
+ }
+ }
+
+ /**
+ * Block size in bytes
+ */
+ private int blocksizeBytes;
+
+ /**
+ * Block size in 64 bit words
+ */
+ private int blocksizeWords;
+
+ /**
+ * Buffer for byte oriented processBytes to call internal word API
+ */
+ private long[] currentBlock;
+
+ /**
+ * Tweak bytes (2 byte t1,t2, calculated t3 and repeat of t1,t2 for modulo free lookup
+ */
+ private long[] t = new long[5];
+
+ /**
+ * Key schedule words
+ */
+ private long[] kw;
+
+ /**
+ * The internal cipher implementation (varies by blocksize)
+ */
+ private ThreefishCipher cipher;
+
+ private boolean forEncryption;
+
+ /**
+ * Constructs a new Threefish cipher, with a specified block size.
+ *
+ * @param blocksizeBits the block size in bits, one of {@link #BLOCKSIZE_256}, {@link #BLOCKSIZE_512},
+ * {@link #BLOCKSIZE_1024}.
+ */
+ public ThreefishEngine(final int blocksizeBits)
+ {
+ this.blocksizeBytes = (blocksizeBits / 8);
+ this.blocksizeWords = (this.blocksizeBytes / 8);
+ this.currentBlock = new long[blocksizeWords];
+
+ /*
+ * Provide room for original key words, extended key word and repeat of key words for modulo
+ * free lookup of key schedule words.
+ */
+ this.kw = new long[2 * blocksizeWords + 1];
+
+ switch (blocksizeBits)
+ {
+ case BLOCKSIZE_256:
+ cipher = new Threefish256Cipher(kw, t);
+ break;
+ case BLOCKSIZE_512:
+ cipher = new Threefish512Cipher(kw, t);
+ break;
+ case BLOCKSIZE_1024:
+ cipher = new Threefish1024Cipher(kw, t);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Invalid blocksize - Threefish is defined with block size of 256, 512, or 1024 bits");
+ }
+ }
+
+ /**
+ * Initialise the engine.
+ *
+ * @param params an instance of {@link TweakableBlockCipherParameters}, or {@link KeyParameter} (to
+ * use a 0 tweak)
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ final byte[] keyBytes;
+ final byte[] tweakBytes;
+
+ if (params instanceof TweakableBlockCipherParameters)
+ {
+ TweakableBlockCipherParameters tParams = (TweakableBlockCipherParameters)params;
+ keyBytes = tParams.getKey().getKey();
+ tweakBytes = tParams.getTweak();
+ }
+ else if (params instanceof KeyParameter)
+ {
+ keyBytes = ((KeyParameter)params).getKey();
+ tweakBytes = null;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid parameter passed to Threefish init - "
+ + params.getClass().getName());
+ }
+
+ long[] keyWords = null;
+ long[] tweakWords = null;
+
+ if (keyBytes != null)
+ {
+ if (keyBytes.length != this.blocksizeBytes)
+ {
+ throw new IllegalArgumentException("Threefish key must be same size as block (" + blocksizeBytes
+ + " bytes)");
+ }
+ keyWords = new long[blocksizeWords];
+ for (int i = 0; i < keyWords.length; i++)
+ {
+ keyWords[i] = bytesToWord(keyBytes, i * 8);
+ }
+ }
+ if (tweakBytes != null)
+ {
+ if (tweakBytes.length != TWEAK_SIZE_BYTES)
+ {
+ throw new IllegalArgumentException("Threefish tweak must be " + TWEAK_SIZE_BYTES + " bytes");
+ }
+ tweakWords = new long[]{bytesToWord(tweakBytes, 0), bytesToWord(tweakBytes, 8)};
+ }
+ init(forEncryption, keyWords, tweakWords);
+ }
+
+ /**
+ * Initialise the engine, specifying the key and tweak directly.
+ *
+ * @param forEncryption the cipher mode.
+ * @param key the words of the key, or <code>null</code> to use the current key.
+ * @param tweak the 2 word (128 bit) tweak, or <code>null</code> to use the current tweak.
+ */
+ public void init(boolean forEncryption, final long[] key, final long[] tweak)
+ {
+ this.forEncryption = forEncryption;
+ if (key != null)
+ {
+ setKey(key);
+ }
+ if (tweak != null)
+ {
+ setTweak(tweak);
+ }
+ }
+
+ private void setKey(long[] key)
+ {
+ if (key.length != this.blocksizeWords)
+ {
+ throw new IllegalArgumentException("Threefish key must be same size as block (" + blocksizeWords
+ + " words)");
+ }
+
+ /*
+ * Full subkey schedule is deferred to execution to avoid per cipher overhead (10k for 512,
+ * 20k for 1024).
+ *
+ * Key and tweak word sequences are repeated, and static MOD17/MOD9/MOD5/MOD3 calculations
+ * used, to avoid expensive mod computations during cipher operation.
+ */
+
+ long knw = C_240;
+ for (int i = 0; i < blocksizeWords; i++)
+ {
+ kw[i] = key[i];
+ knw = knw ^ kw[i];
+ }
+ kw[blocksizeWords] = knw;
+ System.arraycopy(kw, 0, kw, blocksizeWords + 1, blocksizeWords);
+ }
+
+ private void setTweak(long[] tweak)
+ {
+ if (tweak.length != TWEAK_SIZE_WORDS)
+ {
+ throw new IllegalArgumentException("Tweak must be " + TWEAK_SIZE_WORDS + " words.");
+ }
+
+ /*
+ * Tweak schedule partially repeated to avoid mod computations during cipher operation
+ */
+ t[0] = tweak[0];
+ t[1] = tweak[1];
+ t[2] = t[0] ^ t[1];
+ t[3] = t[0];
+ t[4] = t[1];
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Threefish-" + (blocksizeBytes * 8);
+ }
+
+ public int getBlockSize()
+ {
+ return blocksizeBytes;
+ }
+
+ public void reset()
+ {
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException,
+ IllegalStateException
+ {
+ if ((outOff + blocksizeBytes) > out.length)
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+
+ if ((inOff + blocksizeBytes) > in.length)
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+
+ for (int i = 0; i < blocksizeBytes; i += 8)
+ {
+ currentBlock[i >> 3] = bytesToWord(in, inOff + i);
+ }
+ processBlock(this.currentBlock, this.currentBlock);
+ for (int i = 0; i < blocksizeBytes; i += 8)
+ {
+ wordToBytes(this.currentBlock[i >> 3], out, outOff + i);
+ }
+
+ return blocksizeBytes;
+ }
+
+ /**
+ * Process a block of data represented as 64 bit words.
+ *
+ * @param in a block sized buffer of words to process.
+ * @param out a block sized buffer of words to receive the output of the operation.
+ * @return the number of 8 byte words processed (which will be the same as the block size).
+ * @throws DataLengthException if either the input or output is not block sized.
+ * @throws IllegalStateException if this engine is not initialised.
+ */
+ public int processBlock(long[] in, long[] out)
+ throws DataLengthException, IllegalStateException
+ {
+ if (kw[blocksizeWords] == 0)
+ {
+ throw new IllegalStateException("Threefish engine not initialised");
+ }
+
+ if (in.length != blocksizeWords)
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+ if (out.length != blocksizeWords)
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ cipher.encryptBlock(in, out);
+ }
+ else
+ {
+ cipher.decryptBlock(in, out);
+ }
+
+ return blocksizeWords;
+ }
+
+ /**
+ * Read a single 64 bit word from input in LSB first order.
+ */
+ // At least package protected for efficient access from inner class
+ public static long bytesToWord(final byte[] bytes, final int off)
+ {
+ if ((off + 8) > bytes.length)
+ {
+ // Help the JIT avoid index checks
+ throw new IllegalArgumentException();
+ }
+
+ long word = 0;
+ int index = off;
+
+ word = (bytes[index++] & 0xffL);
+ word |= (bytes[index++] & 0xffL) << 8;
+ word |= (bytes[index++] & 0xffL) << 16;
+ word |= (bytes[index++] & 0xffL) << 24;
+ word |= (bytes[index++] & 0xffL) << 32;
+ word |= (bytes[index++] & 0xffL) << 40;
+ word |= (bytes[index++] & 0xffL) << 48;
+ word |= (bytes[index++] & 0xffL) << 56;
+
+ return word;
+ }
+
+ /**
+ * Write a 64 bit word to output in LSB first order.
+ */
+ // At least package protected for efficient access from inner class
+ public static void wordToBytes(final long word, final byte[] bytes, final int off)
+ {
+ if ((off + 8) > bytes.length)
+ {
+ // Help the JIT avoid index checks
+ throw new IllegalArgumentException();
+ }
+ int index = off;
+
+ bytes[index++] = (byte)word;
+ bytes[index++] = (byte)(word >> 8);
+ bytes[index++] = (byte)(word >> 16);
+ bytes[index++] = (byte)(word >> 24);
+ bytes[index++] = (byte)(word >> 32);
+ bytes[index++] = (byte)(word >> 40);
+ bytes[index++] = (byte)(word >> 48);
+ bytes[index++] = (byte)(word >> 56);
+ }
+
+ /**
+ * Rotate left + xor part of the mix operation.
+ */
+ // Package protected for efficient access from inner class
+ static long rotlXor(long x, int n, long xor)
+ {
+ return ((x << n) | (x >>> -n)) ^ xor;
+ }
+
+ /**
+ * Rotate xor + rotate right part of the unmix operation.
+ */
+ // Package protected for efficient access from inner class
+ static long xorRotr(long x, int n, long xor)
+ {
+ long xored = x ^ xor;
+ return (xored >>> n) | (xored << -n);
+ }
+
+ private static abstract class ThreefishCipher
+ {
+ /**
+ * The extended + repeated tweak words
+ */
+ protected final long[] t;
+ /**
+ * The extended + repeated key words
+ */
+ protected final long[] kw;
+
+ protected ThreefishCipher(final long[] kw, final long[] t)
+ {
+ this.kw = kw;
+ this.t = t;
+ }
+
+ abstract void encryptBlock(long[] block, long[] out);
+
+ abstract void decryptBlock(long[] block, long[] out);
+
+ }
+
+ private static final class Threefish256Cipher
+ extends ThreefishCipher
+ {
+ /**
+ * Mix rotation constants defined in Skein 1.3 specification
+ */
+ private static final int ROTATION_0_0 = 14, ROTATION_0_1 = 16;
+ private static final int ROTATION_1_0 = 52, ROTATION_1_1 = 57;
+ private static final int ROTATION_2_0 = 23, ROTATION_2_1 = 40;
+ private static final int ROTATION_3_0 = 5, ROTATION_3_1 = 37;
+
+ private static final int ROTATION_4_0 = 25, ROTATION_4_1 = 33;
+ private static final int ROTATION_5_0 = 46, ROTATION_5_1 = 12;
+ private static final int ROTATION_6_0 = 58, ROTATION_6_1 = 22;
+ private static final int ROTATION_7_0 = 32, ROTATION_7_1 = 32;
+
+ public Threefish256Cipher(long[] kw, long[] t)
+ {
+ super(kw, t);
+ }
+
+ void encryptBlock(long[] block, long[] out)
+ {
+ final long[] kw = this.kw;
+ final long[] t = this.t;
+ final int[] mod5 = MOD5;
+ final int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.length != 9)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (t.length != 5)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /*
+ * Read 4 words of plaintext data, not using arrays for cipher state
+ */
+ long b0 = block[0];
+ long b1 = block[1];
+ long b2 = block[2];
+ long b3 = block[3];
+
+ /*
+ * First subkey injection.
+ */
+ b0 += kw[0];
+ b1 += kw[1] + t[0];
+ b2 += kw[2] + t[1];
+ b3 += kw[3];
+
+ /*
+ * Rounds loop, unrolled to 8 rounds per iteration.
+ *
+ * Unrolling to multiples of 4 avoids the mod 4 check for key injection, and allows
+ * inlining of the permutations, which cycle every of 2 rounds (avoiding array
+ * index/lookup).
+ *
+ * Unrolling to multiples of 8 avoids the mod 8 rotation constant lookup, and allows
+ * inlining constant rotation values (avoiding array index/lookup).
+ */
+
+ for (int d = 1; d < (ROUNDS_256 / 4); d += 2)
+ {
+ final int dm5 = mod5[d];
+ final int dm3 = mod3[d];
+
+ /*
+ * 4 rounds of mix and permute.
+ *
+ * Permute schedule has a 2 round cycle, so permutes are inlined in the mix
+ * operations in each 4 round block.
+ */
+ b1 = rotlXor(b1, ROTATION_0_0, b0 += b1);
+ b3 = rotlXor(b3, ROTATION_0_1, b2 += b3);
+
+ b3 = rotlXor(b3, ROTATION_1_0, b0 += b3);
+ b1 = rotlXor(b1, ROTATION_1_1, b2 += b1);
+
+ b1 = rotlXor(b1, ROTATION_2_0, b0 += b1);
+ b3 = rotlXor(b3, ROTATION_2_1, b2 += b3);
+
+ b3 = rotlXor(b3, ROTATION_3_0, b0 += b3);
+ b1 = rotlXor(b1, ROTATION_3_1, b2 += b1);
+
+ /*
+ * Subkey injection for first 4 rounds.
+ */
+ b0 += kw[dm5];
+ b1 += kw[dm5 + 1] + t[dm3];
+ b2 += kw[dm5 + 2] + t[dm3 + 1];
+ b3 += kw[dm5 + 3] + d;
+
+ /*
+ * 4 more rounds of mix/permute
+ */
+ b1 = rotlXor(b1, ROTATION_4_0, b0 += b1);
+ b3 = rotlXor(b3, ROTATION_4_1, b2 += b3);
+
+ b3 = rotlXor(b3, ROTATION_5_0, b0 += b3);
+ b1 = rotlXor(b1, ROTATION_5_1, b2 += b1);
+
+ b1 = rotlXor(b1, ROTATION_6_0, b0 += b1);
+ b3 = rotlXor(b3, ROTATION_6_1, b2 += b3);
+
+ b3 = rotlXor(b3, ROTATION_7_0, b0 += b3);
+ b1 = rotlXor(b1, ROTATION_7_1, b2 += b1);
+
+ /*
+ * Subkey injection for next 4 rounds.
+ */
+ b0 += kw[dm5 + 1];
+ b1 += kw[dm5 + 2] + t[dm3 + 1];
+ b2 += kw[dm5 + 3] + t[dm3 + 2];
+ b3 += kw[dm5 + 4] + d + 1;
+ }
+
+ /*
+ * Output cipher state.
+ */
+ out[0] = b0;
+ out[1] = b1;
+ out[2] = b2;
+ out[3] = b3;
+ }
+
+ void decryptBlock(long[] block, long[] state)
+ {
+ final long[] kw = this.kw;
+ final long[] t = this.t;
+ final int[] mod5 = MOD5;
+ final int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.length != 9)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (t.length != 5)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ long b0 = block[0];
+ long b1 = block[1];
+ long b2 = block[2];
+ long b3 = block[3];
+
+ for (int d = (ROUNDS_256 / 4) - 1; d >= 1; d -= 2)
+ {
+ final int dm5 = mod5[d];
+ final int dm3 = mod3[d];
+
+ /* Reverse key injection for second 4 rounds */
+ b0 -= kw[dm5 + 1];
+ b1 -= kw[dm5 + 2] + t[dm3 + 1];
+ b2 -= kw[dm5 + 3] + t[dm3 + 2];
+ b3 -= kw[dm5 + 4] + d + 1;
+
+ /* Reverse second 4 mix/permute rounds */
+
+ b3 = xorRotr(b3, ROTATION_7_0, b0);
+ b0 -= b3;
+ b1 = xorRotr(b1, ROTATION_7_1, b2);
+ b2 -= b1;
+
+ b1 = xorRotr(b1, ROTATION_6_0, b0);
+ b0 -= b1;
+ b3 = xorRotr(b3, ROTATION_6_1, b2);
+ b2 -= b3;
+
+ b3 = xorRotr(b3, ROTATION_5_0, b0);
+ b0 -= b3;
+ b1 = xorRotr(b1, ROTATION_5_1, b2);
+ b2 -= b1;
+
+ b1 = xorRotr(b1, ROTATION_4_0, b0);
+ b0 -= b1;
+ b3 = xorRotr(b3, ROTATION_4_1, b2);
+ b2 -= b3;
+
+ /* Reverse key injection for first 4 rounds */
+ b0 -= kw[dm5];
+ b1 -= kw[dm5 + 1] + t[dm3];
+ b2 -= kw[dm5 + 2] + t[dm3 + 1];
+ b3 -= kw[dm5 + 3] + d;
+
+ /* Reverse first 4 mix/permute rounds */
+ b3 = xorRotr(b3, ROTATION_3_0, b0);
+ b0 -= b3;
+ b1 = xorRotr(b1, ROTATION_3_1, b2);
+ b2 -= b1;
+
+ b1 = xorRotr(b1, ROTATION_2_0, b0);
+ b0 -= b1;
+ b3 = xorRotr(b3, ROTATION_2_1, b2);
+ b2 -= b3;
+
+ b3 = xorRotr(b3, ROTATION_1_0, b0);
+ b0 -= b3;
+ b1 = xorRotr(b1, ROTATION_1_1, b2);
+ b2 -= b1;
+
+ b1 = xorRotr(b1, ROTATION_0_0, b0);
+ b0 -= b1;
+ b3 = xorRotr(b3, ROTATION_0_1, b2);
+ b2 -= b3;
+ }
+
+ /*
+ * First subkey uninjection.
+ */
+ b0 -= kw[0];
+ b1 -= kw[1] + t[0];
+ b2 -= kw[2] + t[1];
+ b3 -= kw[3];
+
+ /*
+ * Output cipher state.
+ */
+ state[0] = b0;
+ state[1] = b1;
+ state[2] = b2;
+ state[3] = b3;
+ }
+
+ }
+
+ private static final class Threefish512Cipher
+ extends ThreefishCipher
+ {
+ /**
+ * Mix rotation constants defined in Skein 1.3 specification
+ */
+ private static final int ROTATION_0_0 = 46, ROTATION_0_1 = 36, ROTATION_0_2 = 19, ROTATION_0_3 = 37;
+ private static final int ROTATION_1_0 = 33, ROTATION_1_1 = 27, ROTATION_1_2 = 14, ROTATION_1_3 = 42;
+ private static final int ROTATION_2_0 = 17, ROTATION_2_1 = 49, ROTATION_2_2 = 36, ROTATION_2_3 = 39;
+ private static final int ROTATION_3_0 = 44, ROTATION_3_1 = 9, ROTATION_3_2 = 54, ROTATION_3_3 = 56;
+
+ private static final int ROTATION_4_0 = 39, ROTATION_4_1 = 30, ROTATION_4_2 = 34, ROTATION_4_3 = 24;
+ private static final int ROTATION_5_0 = 13, ROTATION_5_1 = 50, ROTATION_5_2 = 10, ROTATION_5_3 = 17;
+ private static final int ROTATION_6_0 = 25, ROTATION_6_1 = 29, ROTATION_6_2 = 39, ROTATION_6_3 = 43;
+ private static final int ROTATION_7_0 = 8, ROTATION_7_1 = 35, ROTATION_7_2 = 56, ROTATION_7_3 = 22;
+
+ protected Threefish512Cipher(long[] kw, long[] t)
+ {
+ super(kw, t);
+ }
+
+ public void encryptBlock(long[] block, long[] out)
+ {
+ final long[] kw = this.kw;
+ final long[] t = this.t;
+ final int[] mod9 = MOD9;
+ final int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.length != 17)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (t.length != 5)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /*
+ * Read 8 words of plaintext data, not using arrays for cipher state
+ */
+ long b0 = block[0];
+ long b1 = block[1];
+ long b2 = block[2];
+ long b3 = block[3];
+ long b4 = block[4];
+ long b5 = block[5];
+ long b6 = block[6];
+ long b7 = block[7];
+
+ /*
+ * First subkey injection.
+ */
+ b0 += kw[0];
+ b1 += kw[1];
+ b2 += kw[2];
+ b3 += kw[3];
+ b4 += kw[4];
+ b5 += kw[5] + t[0];
+ b6 += kw[6] + t[1];
+ b7 += kw[7];
+
+ /*
+ * Rounds loop, unrolled to 8 rounds per iteration.
+ *
+ * Unrolling to multiples of 4 avoids the mod 4 check for key injection, and allows
+ * inlining of the permutations, which cycle every of 4 rounds (avoiding array
+ * index/lookup).
+ *
+ * Unrolling to multiples of 8 avoids the mod 8 rotation constant lookup, and allows
+ * inlining constant rotation values (avoiding array index/lookup).
+ */
+
+ for (int d = 1; d < (ROUNDS_512 / 4); d += 2)
+ {
+ final int dm9 = mod9[d];
+ final int dm3 = mod3[d];
+
+ /*
+ * 4 rounds of mix and permute.
+ *
+ * Permute schedule has a 4 round cycle, so permutes are inlined in the mix
+ * operations in each 4 round block.
+ */
+ b1 = rotlXor(b1, ROTATION_0_0, b0 += b1);
+ b3 = rotlXor(b3, ROTATION_0_1, b2 += b3);
+ b5 = rotlXor(b5, ROTATION_0_2, b4 += b5);
+ b7 = rotlXor(b7, ROTATION_0_3, b6 += b7);
+
+ b1 = rotlXor(b1, ROTATION_1_0, b2 += b1);
+ b7 = rotlXor(b7, ROTATION_1_1, b4 += b7);
+ b5 = rotlXor(b5, ROTATION_1_2, b6 += b5);
+ b3 = rotlXor(b3, ROTATION_1_3, b0 += b3);
+
+ b1 = rotlXor(b1, ROTATION_2_0, b4 += b1);
+ b3 = rotlXor(b3, ROTATION_2_1, b6 += b3);
+ b5 = rotlXor(b5, ROTATION_2_2, b0 += b5);
+ b7 = rotlXor(b7, ROTATION_2_3, b2 += b7);
+
+ b1 = rotlXor(b1, ROTATION_3_0, b6 += b1);
+ b7 = rotlXor(b7, ROTATION_3_1, b0 += b7);
+ b5 = rotlXor(b5, ROTATION_3_2, b2 += b5);
+ b3 = rotlXor(b3, ROTATION_3_3, b4 += b3);
+
+ /*
+ * Subkey injection for first 4 rounds.
+ */
+ b0 += kw[dm9];
+ b1 += kw[dm9 + 1];
+ b2 += kw[dm9 + 2];
+ b3 += kw[dm9 + 3];
+ b4 += kw[dm9 + 4];
+ b5 += kw[dm9 + 5] + t[dm3];
+ b6 += kw[dm9 + 6] + t[dm3 + 1];
+ b7 += kw[dm9 + 7] + d;
+
+ /*
+ * 4 more rounds of mix/permute
+ */
+ b1 = rotlXor(b1, ROTATION_4_0, b0 += b1);
+ b3 = rotlXor(b3, ROTATION_4_1, b2 += b3);
+ b5 = rotlXor(b5, ROTATION_4_2, b4 += b5);
+ b7 = rotlXor(b7, ROTATION_4_3, b6 += b7);
+
+ b1 = rotlXor(b1, ROTATION_5_0, b2 += b1);
+ b7 = rotlXor(b7, ROTATION_5_1, b4 += b7);
+ b5 = rotlXor(b5, ROTATION_5_2, b6 += b5);
+ b3 = rotlXor(b3, ROTATION_5_3, b0 += b3);
+
+ b1 = rotlXor(b1, ROTATION_6_0, b4 += b1);
+ b3 = rotlXor(b3, ROTATION_6_1, b6 += b3);
+ b5 = rotlXor(b5, ROTATION_6_2, b0 += b5);
+ b7 = rotlXor(b7, ROTATION_6_3, b2 += b7);
+
+ b1 = rotlXor(b1, ROTATION_7_0, b6 += b1);
+ b7 = rotlXor(b7, ROTATION_7_1, b0 += b7);
+ b5 = rotlXor(b5, ROTATION_7_2, b2 += b5);
+ b3 = rotlXor(b3, ROTATION_7_3, b4 += b3);
+
+ /*
+ * Subkey injection for next 4 rounds.
+ */
+ b0 += kw[dm9 + 1];
+ b1 += kw[dm9 + 2];
+ b2 += kw[dm9 + 3];
+ b3 += kw[dm9 + 4];
+ b4 += kw[dm9 + 5];
+ b5 += kw[dm9 + 6] + t[dm3 + 1];
+ b6 += kw[dm9 + 7] + t[dm3 + 2];
+ b7 += kw[dm9 + 8] + d + 1;
+ }
+
+ /*
+ * Output cipher state.
+ */
+ out[0] = b0;
+ out[1] = b1;
+ out[2] = b2;
+ out[3] = b3;
+ out[4] = b4;
+ out[5] = b5;
+ out[6] = b6;
+ out[7] = b7;
+ }
+
+ public void decryptBlock(long[] block, long[] state)
+ {
+ final long[] kw = this.kw;
+ final long[] t = this.t;
+ final int[] mod9 = MOD9;
+ final int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.length != 17)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (t.length != 5)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ long b0 = block[0];
+ long b1 = block[1];
+ long b2 = block[2];
+ long b3 = block[3];
+ long b4 = block[4];
+ long b5 = block[5];
+ long b6 = block[6];
+ long b7 = block[7];
+
+ for (int d = (ROUNDS_512 / 4) - 1; d >= 1; d -= 2)
+ {
+ final int dm9 = mod9[d];
+ final int dm3 = mod3[d];
+
+ /* Reverse key injection for second 4 rounds */
+ b0 -= kw[dm9 + 1];
+ b1 -= kw[dm9 + 2];
+ b2 -= kw[dm9 + 3];
+ b3 -= kw[dm9 + 4];
+ b4 -= kw[dm9 + 5];
+ b5 -= kw[dm9 + 6] + t[dm3 + 1];
+ b6 -= kw[dm9 + 7] + t[dm3 + 2];
+ b7 -= kw[dm9 + 8] + d + 1;
+
+ /* Reverse second 4 mix/permute rounds */
+
+ b1 = xorRotr(b1, ROTATION_7_0, b6);
+ b6 -= b1;
+ b7 = xorRotr(b7, ROTATION_7_1, b0);
+ b0 -= b7;
+ b5 = xorRotr(b5, ROTATION_7_2, b2);
+ b2 -= b5;
+ b3 = xorRotr(b3, ROTATION_7_3, b4);
+ b4 -= b3;
+
+ b1 = xorRotr(b1, ROTATION_6_0, b4);
+ b4 -= b1;
+ b3 = xorRotr(b3, ROTATION_6_1, b6);
+ b6 -= b3;
+ b5 = xorRotr(b5, ROTATION_6_2, b0);
+ b0 -= b5;
+ b7 = xorRotr(b7, ROTATION_6_3, b2);
+ b2 -= b7;
+
+ b1 = xorRotr(b1, ROTATION_5_0, b2);
+ b2 -= b1;
+ b7 = xorRotr(b7, ROTATION_5_1, b4);
+ b4 -= b7;
+ b5 = xorRotr(b5, ROTATION_5_2, b6);
+ b6 -= b5;
+ b3 = xorRotr(b3, ROTATION_5_3, b0);
+ b0 -= b3;
+
+ b1 = xorRotr(b1, ROTATION_4_0, b0);
+ b0 -= b1;
+ b3 = xorRotr(b3, ROTATION_4_1, b2);
+ b2 -= b3;
+ b5 = xorRotr(b5, ROTATION_4_2, b4);
+ b4 -= b5;
+ b7 = xorRotr(b7, ROTATION_4_3, b6);
+ b6 -= b7;
+
+ /* Reverse key injection for first 4 rounds */
+ b0 -= kw[dm9];
+ b1 -= kw[dm9 + 1];
+ b2 -= kw[dm9 + 2];
+ b3 -= kw[dm9 + 3];
+ b4 -= kw[dm9 + 4];
+ b5 -= kw[dm9 + 5] + t[dm3];
+ b6 -= kw[dm9 + 6] + t[dm3 + 1];
+ b7 -= kw[dm9 + 7] + d;
+
+ /* Reverse first 4 mix/permute rounds */
+ b1 = xorRotr(b1, ROTATION_3_0, b6);
+ b6 -= b1;
+ b7 = xorRotr(b7, ROTATION_3_1, b0);
+ b0 -= b7;
+ b5 = xorRotr(b5, ROTATION_3_2, b2);
+ b2 -= b5;
+ b3 = xorRotr(b3, ROTATION_3_3, b4);
+ b4 -= b3;
+
+ b1 = xorRotr(b1, ROTATION_2_0, b4);
+ b4 -= b1;
+ b3 = xorRotr(b3, ROTATION_2_1, b6);
+ b6 -= b3;
+ b5 = xorRotr(b5, ROTATION_2_2, b0);
+ b0 -= b5;
+ b7 = xorRotr(b7, ROTATION_2_3, b2);
+ b2 -= b7;
+
+ b1 = xorRotr(b1, ROTATION_1_0, b2);
+ b2 -= b1;
+ b7 = xorRotr(b7, ROTATION_1_1, b4);
+ b4 -= b7;
+ b5 = xorRotr(b5, ROTATION_1_2, b6);
+ b6 -= b5;
+ b3 = xorRotr(b3, ROTATION_1_3, b0);
+ b0 -= b3;
+
+ b1 = xorRotr(b1, ROTATION_0_0, b0);
+ b0 -= b1;
+ b3 = xorRotr(b3, ROTATION_0_1, b2);
+ b2 -= b3;
+ b5 = xorRotr(b5, ROTATION_0_2, b4);
+ b4 -= b5;
+ b7 = xorRotr(b7, ROTATION_0_3, b6);
+ b6 -= b7;
+ }
+
+ /*
+ * First subkey uninjection.
+ */
+ b0 -= kw[0];
+ b1 -= kw[1];
+ b2 -= kw[2];
+ b3 -= kw[3];
+ b4 -= kw[4];
+ b5 -= kw[5] + t[0];
+ b6 -= kw[6] + t[1];
+ b7 -= kw[7];
+
+ /*
+ * Output cipher state.
+ */
+ state[0] = b0;
+ state[1] = b1;
+ state[2] = b2;
+ state[3] = b3;
+ state[4] = b4;
+ state[5] = b5;
+ state[6] = b6;
+ state[7] = b7;
+ }
+ }
+
+ private static final class Threefish1024Cipher
+ extends ThreefishCipher
+ {
+ /**
+ * Mix rotation constants defined in Skein 1.3 specification
+ */
+ private static final int ROTATION_0_0 = 24, ROTATION_0_1 = 13, ROTATION_0_2 = 8, ROTATION_0_3 = 47;
+ private static final int ROTATION_0_4 = 8, ROTATION_0_5 = 17, ROTATION_0_6 = 22, ROTATION_0_7 = 37;
+ private static final int ROTATION_1_0 = 38, ROTATION_1_1 = 19, ROTATION_1_2 = 10, ROTATION_1_3 = 55;
+ private static final int ROTATION_1_4 = 49, ROTATION_1_5 = 18, ROTATION_1_6 = 23, ROTATION_1_7 = 52;
+ private static final int ROTATION_2_0 = 33, ROTATION_2_1 = 4, ROTATION_2_2 = 51, ROTATION_2_3 = 13;
+ private static final int ROTATION_2_4 = 34, ROTATION_2_5 = 41, ROTATION_2_6 = 59, ROTATION_2_7 = 17;
+ private static final int ROTATION_3_0 = 5, ROTATION_3_1 = 20, ROTATION_3_2 = 48, ROTATION_3_3 = 41;
+ private static final int ROTATION_3_4 = 47, ROTATION_3_5 = 28, ROTATION_3_6 = 16, ROTATION_3_7 = 25;
+
+ private static final int ROTATION_4_0 = 41, ROTATION_4_1 = 9, ROTATION_4_2 = 37, ROTATION_4_3 = 31;
+ private static final int ROTATION_4_4 = 12, ROTATION_4_5 = 47, ROTATION_4_6 = 44, ROTATION_4_7 = 30;
+ private static final int ROTATION_5_0 = 16, ROTATION_5_1 = 34, ROTATION_5_2 = 56, ROTATION_5_3 = 51;
+ private static final int ROTATION_5_4 = 4, ROTATION_5_5 = 53, ROTATION_5_6 = 42, ROTATION_5_7 = 41;
+ private static final int ROTATION_6_0 = 31, ROTATION_6_1 = 44, ROTATION_6_2 = 47, ROTATION_6_3 = 46;
+ private static final int ROTATION_6_4 = 19, ROTATION_6_5 = 42, ROTATION_6_6 = 44, ROTATION_6_7 = 25;
+ private static final int ROTATION_7_0 = 9, ROTATION_7_1 = 48, ROTATION_7_2 = 35, ROTATION_7_3 = 52;
+ private static final int ROTATION_7_4 = 23, ROTATION_7_5 = 31, ROTATION_7_6 = 37, ROTATION_7_7 = 20;
+
+ public Threefish1024Cipher(long[] kw, long[] t)
+ {
+ super(kw, t);
+ }
+
+ void encryptBlock(long[] block, long[] out)
+ {
+ final long[] kw = this.kw;
+ final long[] t = this.t;
+ final int[] mod17 = MOD17;
+ final int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.length != 33)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (t.length != 5)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ /*
+ * Read 16 words of plaintext data, not using arrays for cipher state
+ */
+ long b0 = block[0];
+ long b1 = block[1];
+ long b2 = block[2];
+ long b3 = block[3];
+ long b4 = block[4];
+ long b5 = block[5];
+ long b6 = block[6];
+ long b7 = block[7];
+ long b8 = block[8];
+ long b9 = block[9];
+ long b10 = block[10];
+ long b11 = block[11];
+ long b12 = block[12];
+ long b13 = block[13];
+ long b14 = block[14];
+ long b15 = block[15];
+
+ /*
+ * First subkey injection.
+ */
+ b0 += kw[0];
+ b1 += kw[1];
+ b2 += kw[2];
+ b3 += kw[3];
+ b4 += kw[4];
+ b5 += kw[5];
+ b6 += kw[6];
+ b7 += kw[7];
+ b8 += kw[8];
+ b9 += kw[9];
+ b10 += kw[10];
+ b11 += kw[11];
+ b12 += kw[12];
+ b13 += kw[13] + t[0];
+ b14 += kw[14] + t[1];
+ b15 += kw[15];
+
+ /*
+ * Rounds loop, unrolled to 8 rounds per iteration.
+ *
+ * Unrolling to multiples of 4 avoids the mod 4 check for key injection, and allows
+ * inlining of the permutations, which cycle every of 4 rounds (avoiding array
+ * index/lookup).
+ *
+ * Unrolling to multiples of 8 avoids the mod 8 rotation constant lookup, and allows
+ * inlining constant rotation values (avoiding array index/lookup).
+ */
+
+ for (int d = 1; d < (ROUNDS_1024 / 4); d += 2)
+ {
+ final int dm17 = mod17[d];
+ final int dm3 = mod3[d];
+
+ /*
+ * 4 rounds of mix and permute.
+ *
+ * Permute schedule has a 4 round cycle, so permutes are inlined in the mix
+ * operations in each 4 round block.
+ */
+ b1 = rotlXor(b1, ROTATION_0_0, b0 += b1);
+ b3 = rotlXor(b3, ROTATION_0_1, b2 += b3);
+ b5 = rotlXor(b5, ROTATION_0_2, b4 += b5);
+ b7 = rotlXor(b7, ROTATION_0_3, b6 += b7);
+ b9 = rotlXor(b9, ROTATION_0_4, b8 += b9);
+ b11 = rotlXor(b11, ROTATION_0_5, b10 += b11);
+ b13 = rotlXor(b13, ROTATION_0_6, b12 += b13);
+ b15 = rotlXor(b15, ROTATION_0_7, b14 += b15);
+
+ b9 = rotlXor(b9, ROTATION_1_0, b0 += b9);
+ b13 = rotlXor(b13, ROTATION_1_1, b2 += b13);
+ b11 = rotlXor(b11, ROTATION_1_2, b6 += b11);
+ b15 = rotlXor(b15, ROTATION_1_3, b4 += b15);
+ b7 = rotlXor(b7, ROTATION_1_4, b10 += b7);
+ b3 = rotlXor(b3, ROTATION_1_5, b12 += b3);
+ b5 = rotlXor(b5, ROTATION_1_6, b14 += b5);
+ b1 = rotlXor(b1, ROTATION_1_7, b8 += b1);
+
+ b7 = rotlXor(b7, ROTATION_2_0, b0 += b7);
+ b5 = rotlXor(b5, ROTATION_2_1, b2 += b5);
+ b3 = rotlXor(b3, ROTATION_2_2, b4 += b3);
+ b1 = rotlXor(b1, ROTATION_2_3, b6 += b1);
+ b15 = rotlXor(b15, ROTATION_2_4, b12 += b15);
+ b13 = rotlXor(b13, ROTATION_2_5, b14 += b13);
+ b11 = rotlXor(b11, ROTATION_2_6, b8 += b11);
+ b9 = rotlXor(b9, ROTATION_2_7, b10 += b9);
+
+ b15 = rotlXor(b15, ROTATION_3_0, b0 += b15);
+ b11 = rotlXor(b11, ROTATION_3_1, b2 += b11);
+ b13 = rotlXor(b13, ROTATION_3_2, b6 += b13);
+ b9 = rotlXor(b9, ROTATION_3_3, b4 += b9);
+ b1 = rotlXor(b1, ROTATION_3_4, b14 += b1);
+ b5 = rotlXor(b5, ROTATION_3_5, b8 += b5);
+ b3 = rotlXor(b3, ROTATION_3_6, b10 += b3);
+ b7 = rotlXor(b7, ROTATION_3_7, b12 += b7);
+
+ /*
+ * Subkey injection for first 4 rounds.
+ */
+ b0 += kw[dm17];
+ b1 += kw[dm17 + 1];
+ b2 += kw[dm17 + 2];
+ b3 += kw[dm17 + 3];
+ b4 += kw[dm17 + 4];
+ b5 += kw[dm17 + 5];
+ b6 += kw[dm17 + 6];
+ b7 += kw[dm17 + 7];
+ b8 += kw[dm17 + 8];
+ b9 += kw[dm17 + 9];
+ b10 += kw[dm17 + 10];
+ b11 += kw[dm17 + 11];
+ b12 += kw[dm17 + 12];
+ b13 += kw[dm17 + 13] + t[dm3];
+ b14 += kw[dm17 + 14] + t[dm3 + 1];
+ b15 += kw[dm17 + 15] + d;
+
+ /*
+ * 4 more rounds of mix/permute
+ */
+ b1 = rotlXor(b1, ROTATION_4_0, b0 += b1);
+ b3 = rotlXor(b3, ROTATION_4_1, b2 += b3);
+ b5 = rotlXor(b5, ROTATION_4_2, b4 += b5);
+ b7 = rotlXor(b7, ROTATION_4_3, b6 += b7);
+ b9 = rotlXor(b9, ROTATION_4_4, b8 += b9);
+ b11 = rotlXor(b11, ROTATION_4_5, b10 += b11);
+ b13 = rotlXor(b13, ROTATION_4_6, b12 += b13);
+ b15 = rotlXor(b15, ROTATION_4_7, b14 += b15);
+
+ b9 = rotlXor(b9, ROTATION_5_0, b0 += b9);
+ b13 = rotlXor(b13, ROTATION_5_1, b2 += b13);
+ b11 = rotlXor(b11, ROTATION_5_2, b6 += b11);
+ b15 = rotlXor(b15, ROTATION_5_3, b4 += b15);
+ b7 = rotlXor(b7, ROTATION_5_4, b10 += b7);
+ b3 = rotlXor(b3, ROTATION_5_5, b12 += b3);
+ b5 = rotlXor(b5, ROTATION_5_6, b14 += b5);
+ b1 = rotlXor(b1, ROTATION_5_7, b8 += b1);
+
+ b7 = rotlXor(b7, ROTATION_6_0, b0 += b7);
+ b5 = rotlXor(b5, ROTATION_6_1, b2 += b5);
+ b3 = rotlXor(b3, ROTATION_6_2, b4 += b3);
+ b1 = rotlXor(b1, ROTATION_6_3, b6 += b1);
+ b15 = rotlXor(b15, ROTATION_6_4, b12 += b15);
+ b13 = rotlXor(b13, ROTATION_6_5, b14 += b13);
+ b11 = rotlXor(b11, ROTATION_6_6, b8 += b11);
+ b9 = rotlXor(b9, ROTATION_6_7, b10 += b9);
+
+ b15 = rotlXor(b15, ROTATION_7_0, b0 += b15);
+ b11 = rotlXor(b11, ROTATION_7_1, b2 += b11);
+ b13 = rotlXor(b13, ROTATION_7_2, b6 += b13);
+ b9 = rotlXor(b9, ROTATION_7_3, b4 += b9);
+ b1 = rotlXor(b1, ROTATION_7_4, b14 += b1);
+ b5 = rotlXor(b5, ROTATION_7_5, b8 += b5);
+ b3 = rotlXor(b3, ROTATION_7_6, b10 += b3);
+ b7 = rotlXor(b7, ROTATION_7_7, b12 += b7);
+
+ /*
+ * Subkey injection for next 4 rounds.
+ */
+ b0 += kw[dm17 + 1];
+ b1 += kw[dm17 + 2];
+ b2 += kw[dm17 + 3];
+ b3 += kw[dm17 + 4];
+ b4 += kw[dm17 + 5];
+ b5 += kw[dm17 + 6];
+ b6 += kw[dm17 + 7];
+ b7 += kw[dm17 + 8];
+ b8 += kw[dm17 + 9];
+ b9 += kw[dm17 + 10];
+ b10 += kw[dm17 + 11];
+ b11 += kw[dm17 + 12];
+ b12 += kw[dm17 + 13];
+ b13 += kw[dm17 + 14] + t[dm3 + 1];
+ b14 += kw[dm17 + 15] + t[dm3 + 2];
+ b15 += kw[dm17 + 16] + d + 1;
+
+ }
+
+ /*
+ * Output cipher state.
+ */
+ out[0] = b0;
+ out[1] = b1;
+ out[2] = b2;
+ out[3] = b3;
+ out[4] = b4;
+ out[5] = b5;
+ out[6] = b6;
+ out[7] = b7;
+ out[8] = b8;
+ out[9] = b9;
+ out[10] = b10;
+ out[11] = b11;
+ out[12] = b12;
+ out[13] = b13;
+ out[14] = b14;
+ out[15] = b15;
+ }
+
+ void decryptBlock(long[] block, long[] state)
+ {
+ final long[] kw = this.kw;
+ final long[] t = this.t;
+ final int[] mod17 = MOD17;
+ final int[] mod3 = MOD3;
+
+ /* Help the JIT avoid index bounds checks */
+ if (kw.length != 33)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (t.length != 5)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ long b0 = block[0];
+ long b1 = block[1];
+ long b2 = block[2];
+ long b3 = block[3];
+ long b4 = block[4];
+ long b5 = block[5];
+ long b6 = block[6];
+ long b7 = block[7];
+ long b8 = block[8];
+ long b9 = block[9];
+ long b10 = block[10];
+ long b11 = block[11];
+ long b12 = block[12];
+ long b13 = block[13];
+ long b14 = block[14];
+ long b15 = block[15];
+
+ for (int d = (ROUNDS_1024 / 4) - 1; d >= 1; d -= 2)
+ {
+ final int dm17 = mod17[d];
+ final int dm3 = mod3[d];
+
+ /* Reverse key injection for second 4 rounds */
+ b0 -= kw[dm17 + 1];
+ b1 -= kw[dm17 + 2];
+ b2 -= kw[dm17 + 3];
+ b3 -= kw[dm17 + 4];
+ b4 -= kw[dm17 + 5];
+ b5 -= kw[dm17 + 6];
+ b6 -= kw[dm17 + 7];
+ b7 -= kw[dm17 + 8];
+ b8 -= kw[dm17 + 9];
+ b9 -= kw[dm17 + 10];
+ b10 -= kw[dm17 + 11];
+ b11 -= kw[dm17 + 12];
+ b12 -= kw[dm17 + 13];
+ b13 -= kw[dm17 + 14] + t[dm3 + 1];
+ b14 -= kw[dm17 + 15] + t[dm3 + 2];
+ b15 -= kw[dm17 + 16] + d + 1;
+
+ /* Reverse second 4 mix/permute rounds */
+ b15 = xorRotr(b15, ROTATION_7_0, b0);
+ b0 -= b15;
+ b11 = xorRotr(b11, ROTATION_7_1, b2);
+ b2 -= b11;
+ b13 = xorRotr(b13, ROTATION_7_2, b6);
+ b6 -= b13;
+ b9 = xorRotr(b9, ROTATION_7_3, b4);
+ b4 -= b9;
+ b1 = xorRotr(b1, ROTATION_7_4, b14);
+ b14 -= b1;
+ b5 = xorRotr(b5, ROTATION_7_5, b8);
+ b8 -= b5;
+ b3 = xorRotr(b3, ROTATION_7_6, b10);
+ b10 -= b3;
+ b7 = xorRotr(b7, ROTATION_7_7, b12);
+ b12 -= b7;
+
+ b7 = xorRotr(b7, ROTATION_6_0, b0);
+ b0 -= b7;
+ b5 = xorRotr(b5, ROTATION_6_1, b2);
+ b2 -= b5;
+ b3 = xorRotr(b3, ROTATION_6_2, b4);
+ b4 -= b3;
+ b1 = xorRotr(b1, ROTATION_6_3, b6);
+ b6 -= b1;
+ b15 = xorRotr(b15, ROTATION_6_4, b12);
+ b12 -= b15;
+ b13 = xorRotr(b13, ROTATION_6_5, b14);
+ b14 -= b13;
+ b11 = xorRotr(b11, ROTATION_6_6, b8);
+ b8 -= b11;
+ b9 = xorRotr(b9, ROTATION_6_7, b10);
+ b10 -= b9;
+
+ b9 = xorRotr(b9, ROTATION_5_0, b0);
+ b0 -= b9;
+ b13 = xorRotr(b13, ROTATION_5_1, b2);
+ b2 -= b13;
+ b11 = xorRotr(b11, ROTATION_5_2, b6);
+ b6 -= b11;
+ b15 = xorRotr(b15, ROTATION_5_3, b4);
+ b4 -= b15;
+ b7 = xorRotr(b7, ROTATION_5_4, b10);
+ b10 -= b7;
+ b3 = xorRotr(b3, ROTATION_5_5, b12);
+ b12 -= b3;
+ b5 = xorRotr(b5, ROTATION_5_6, b14);
+ b14 -= b5;
+ b1 = xorRotr(b1, ROTATION_5_7, b8);
+ b8 -= b1;
+
+ b1 = xorRotr(b1, ROTATION_4_0, b0);
+ b0 -= b1;
+ b3 = xorRotr(b3, ROTATION_4_1, b2);
+ b2 -= b3;
+ b5 = xorRotr(b5, ROTATION_4_2, b4);
+ b4 -= b5;
+ b7 = xorRotr(b7, ROTATION_4_3, b6);
+ b6 -= b7;
+ b9 = xorRotr(b9, ROTATION_4_4, b8);
+ b8 -= b9;
+ b11 = xorRotr(b11, ROTATION_4_5, b10);
+ b10 -= b11;
+ b13 = xorRotr(b13, ROTATION_4_6, b12);
+ b12 -= b13;
+ b15 = xorRotr(b15, ROTATION_4_7, b14);
+ b14 -= b15;
+
+ /* Reverse key injection for first 4 rounds */
+ b0 -= kw[dm17];
+ b1 -= kw[dm17 + 1];
+ b2 -= kw[dm17 + 2];
+ b3 -= kw[dm17 + 3];
+ b4 -= kw[dm17 + 4];
+ b5 -= kw[dm17 + 5];
+ b6 -= kw[dm17 + 6];
+ b7 -= kw[dm17 + 7];
+ b8 -= kw[dm17 + 8];
+ b9 -= kw[dm17 + 9];
+ b10 -= kw[dm17 + 10];
+ b11 -= kw[dm17 + 11];
+ b12 -= kw[dm17 + 12];
+ b13 -= kw[dm17 + 13] + t[dm3];
+ b14 -= kw[dm17 + 14] + t[dm3 + 1];
+ b15 -= kw[dm17 + 15] + d;
+
+ /* Reverse first 4 mix/permute rounds */
+ b15 = xorRotr(b15, ROTATION_3_0, b0);
+ b0 -= b15;
+ b11 = xorRotr(b11, ROTATION_3_1, b2);
+ b2 -= b11;
+ b13 = xorRotr(b13, ROTATION_3_2, b6);
+ b6 -= b13;
+ b9 = xorRotr(b9, ROTATION_3_3, b4);
+ b4 -= b9;
+ b1 = xorRotr(b1, ROTATION_3_4, b14);
+ b14 -= b1;
+ b5 = xorRotr(b5, ROTATION_3_5, b8);
+ b8 -= b5;
+ b3 = xorRotr(b3, ROTATION_3_6, b10);
+ b10 -= b3;
+ b7 = xorRotr(b7, ROTATION_3_7, b12);
+ b12 -= b7;
+
+ b7 = xorRotr(b7, ROTATION_2_0, b0);
+ b0 -= b7;
+ b5 = xorRotr(b5, ROTATION_2_1, b2);
+ b2 -= b5;
+ b3 = xorRotr(b3, ROTATION_2_2, b4);
+ b4 -= b3;
+ b1 = xorRotr(b1, ROTATION_2_3, b6);
+ b6 -= b1;
+ b15 = xorRotr(b15, ROTATION_2_4, b12);
+ b12 -= b15;
+ b13 = xorRotr(b13, ROTATION_2_5, b14);
+ b14 -= b13;
+ b11 = xorRotr(b11, ROTATION_2_6, b8);
+ b8 -= b11;
+ b9 = xorRotr(b9, ROTATION_2_7, b10);
+ b10 -= b9;
+
+ b9 = xorRotr(b9, ROTATION_1_0, b0);
+ b0 -= b9;
+ b13 = xorRotr(b13, ROTATION_1_1, b2);
+ b2 -= b13;
+ b11 = xorRotr(b11, ROTATION_1_2, b6);
+ b6 -= b11;
+ b15 = xorRotr(b15, ROTATION_1_3, b4);
+ b4 -= b15;
+ b7 = xorRotr(b7, ROTATION_1_4, b10);
+ b10 -= b7;
+ b3 = xorRotr(b3, ROTATION_1_5, b12);
+ b12 -= b3;
+ b5 = xorRotr(b5, ROTATION_1_6, b14);
+ b14 -= b5;
+ b1 = xorRotr(b1, ROTATION_1_7, b8);
+ b8 -= b1;
+
+ b1 = xorRotr(b1, ROTATION_0_0, b0);
+ b0 -= b1;
+ b3 = xorRotr(b3, ROTATION_0_1, b2);
+ b2 -= b3;
+ b5 = xorRotr(b5, ROTATION_0_2, b4);
+ b4 -= b5;
+ b7 = xorRotr(b7, ROTATION_0_3, b6);
+ b6 -= b7;
+ b9 = xorRotr(b9, ROTATION_0_4, b8);
+ b8 -= b9;
+ b11 = xorRotr(b11, ROTATION_0_5, b10);
+ b10 -= b11;
+ b13 = xorRotr(b13, ROTATION_0_6, b12);
+ b12 -= b13;
+ b15 = xorRotr(b15, ROTATION_0_7, b14);
+ b14 -= b15;
+ }
+
+ /*
+ * First subkey uninjection.
+ */
+ b0 -= kw[0];
+ b1 -= kw[1];
+ b2 -= kw[2];
+ b3 -= kw[3];
+ b4 -= kw[4];
+ b5 -= kw[5];
+ b6 -= kw[6];
+ b7 -= kw[7];
+ b8 -= kw[8];
+ b9 -= kw[9];
+ b10 -= kw[10];
+ b11 -= kw[11];
+ b12 -= kw[12];
+ b13 -= kw[13] + t[0];
+ b14 -= kw[14] + t[1];
+ b15 -= kw[15];
+
+ /*
+ * Output cipher state.
+ */
+ state[0] = b0;
+ state[1] = b1;
+ state[2] = b2;
+ state[3] = b3;
+ state[4] = b4;
+ state[5] = b5;
+ state[6] = b6;
+ state[7] = b7;
+ state[8] = b8;
+ state[9] = b9;
+ state[10] = b10;
+ state[11] = b11;
+ state[12] = b12;
+ state[13] = b13;
+ state[14] = b14;
+ state[15] = b15;
+ }
+
+ }
+
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/VMPCEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/VMPCEngine.java
index 0703fd6..f16f6d4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/VMPCEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/VMPCEngine.java
@@ -44,7 +44,6 @@ public class VMPCEngine implements StreamCipher
}
ParametersWithIV ivParams = (ParametersWithIV) params;
- KeyParameter key = (KeyParameter) ivParams.getParameters();
if (!(ivParams.getParameters() instanceof KeyParameter))
{
@@ -52,6 +51,8 @@ public class VMPCEngine implements StreamCipher
"VMPC init parameters must include a key");
}
+ KeyParameter key = (KeyParameter) ivParams.getParameters();
+
this.workingIV = ivParams.getIV();
if (workingIV == null || workingIV.length < 1 || workingIV.length > 768)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/XSalsa20Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/XSalsa20Engine.java
new file mode 100644
index 0000000..5b2181d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/XSalsa20Engine.java
@@ -0,0 +1,65 @@
+package org.bouncycastle.crypto.engines;
+
+import org.bouncycastle.crypto.util.Pack;
+
+/**
+ * Implementation of Daniel J. Bernstein's XSalsa20 stream cipher - Salsa20 with an extended nonce.
+ * <p>
+ * XSalsa20 requires a 256 bit key, and a 192 bit nonce.
+ */
+public class XSalsa20Engine extends Salsa20Engine
+{
+
+ public String getAlgorithmName()
+ {
+ return "XSalsa20";
+ }
+
+ protected int getNonceSize()
+ {
+ return 24;
+ }
+
+ /**
+ * XSalsa20 key generation: process 256 bit input key and 128 bits of the input nonce
+ * using a core Salsa20 function without input addition to produce 256 bit working key
+ * and use that with the remaining 64 bits of nonce to initialize a standard Salsa20 engine state.
+ */
+ protected void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ if (keyBytes.length != 32)
+ {
+ throw new IllegalArgumentException(getAlgorithmName() + " requires a 256 bit key");
+ }
+
+ // Set key for HSalsa20
+ super.setKey(keyBytes, ivBytes);
+
+ // Pack next 64 bits of IV into engine state instead of counter
+ engineState[8] = Pack.littleEndianToInt(ivBytes, 8);
+ engineState[9] = Pack.littleEndianToInt(ivBytes, 12);
+
+ // Process engine state to generate Salsa20 key
+ int[] hsalsa20Out = new int[engineState.length];
+ salsaCore(20, engineState, hsalsa20Out);
+
+ // Set new key, removing addition in last round of salsaCore
+ engineState[1] = hsalsa20Out[0] - engineState[0];
+ engineState[2] = hsalsa20Out[5] - engineState[5];
+ engineState[3] = hsalsa20Out[10] - engineState[10];
+ engineState[4] = hsalsa20Out[15] - engineState[15];
+
+ engineState[11] = hsalsa20Out[6] - engineState[6];
+ engineState[12] = hsalsa20Out[7] - engineState[7];
+ engineState[13] = hsalsa20Out[8] - engineState[8];
+ engineState[14] = hsalsa20Out[9] - engineState[9];
+
+ // Last 64 bits of input IV
+ engineState[6] = Pack.littleEndianToInt(ivBytes, 16);
+ engineState[7] = Pack.littleEndianToInt(ivBytes, 20);
+
+ // Counter reset
+ resetCounter();
+ }
+
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/XTEAEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/XTEAEngine.java
index f037da4..fb21bbc 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/XTEAEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/XTEAEngine.java
@@ -107,6 +107,11 @@ public class XTEAEngine
private void setKey(
byte[] key)
{
+ if (key.length != 16)
+ {
+ throw new IllegalArgumentException("Key size must be 128 bits.");
+ }
+
int i, j;
for (i = j = 0; i < 4; i++,j+=4)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/engines/package.html
deleted file mode 100644
index e945dac..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Basic cipher classes.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/examples/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/examples/package.html
deleted file mode 100644
index 390a540..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/examples/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Simple examples of light weight API usage.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
index 2ef8dd2..16c8b91 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
@@ -1,9 +1,9 @@
package org.bouncycastle.crypto.generators;
import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.DerivationParameters;
import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.DigestDerivationFunction;
import org.bouncycastle.crypto.params.ISO18033KDFParameters;
import org.bouncycastle.crypto.params.KDFParameters;
import org.bouncycastle.crypto.util.Pack;
@@ -13,7 +13,8 @@ import org.bouncycastle.crypto.util.Pack;
* 18033 <br>
* This implementation is based on ISO 18033/P1363a.
*/
-public class BaseKDFBytesGenerator implements DerivationFunction
+public class BaseKDFBytesGenerator
+ implements DigestDerivationFunction
{
private int counterStart;
private Digest digest;
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 749b0cc..f7a3df2 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
@@ -226,10 +226,10 @@ public class DSAParametersGenerator
int seedlen = N;
byte[] seed = new byte[seedlen / 8];
-// 3. n = ceiling(L ⁄ outlen) – 1.
+// 3. n = ceiling(L / outlen) - 1.
int n = (L - 1) / outlen;
-// 4. b = L – 1 – (n ∗ outlen).
+// 4. b = L - 1 - (n * outlen).
int b = (L - 1) % outlen;
byte[] output = new byte[d.getDigestSize()];
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 d77bd74..d5f5fc8 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
@@ -26,6 +26,11 @@ public class ECKeyPairGenerator
this.random = ecP.getRandom();
this.params = ecP.getDomainParameters();
+
+ if (this.random == null)
+ {
+ this.random = new SecureRandom();
+ }
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFCounterBytesGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFCounterBytesGenerator.java
new file mode 100644
index 0000000..306530e
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFCounterBytesGenerator.java
@@ -0,0 +1,152 @@
+package org.bouncycastle.crypto.generators;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.DerivationParameters;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.MacDerivationFunction;
+import org.bouncycastle.crypto.params.KDFCounterParameters;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * This KDF has been defined by the publicly available NIST SP 800-108 specification.
+ */
+public class KDFCounterBytesGenerator
+ implements MacDerivationFunction
+{
+
+ private static final BigInteger INTEGER_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ // please refer to the standard for the meaning of the variable names
+ // all field lengths are in bytes, not in bits as specified by the standard
+
+ // fields set by the constructor
+ private final Mac prf;
+ private final int h;
+
+ // fields set by init
+ private byte[] fixedInputData;
+ private int maxSizeExcl;
+ // ios is i defined as an octet string (the binary representation)
+ private byte[] ios;
+
+ // operational
+ private int generatedBytes;
+ // k is used as buffer for all K(i) values
+ private byte[] k;
+
+
+ public KDFCounterBytesGenerator(Mac prf)
+ {
+ this.prf = prf;
+ this.h = prf.getMacSize();
+ this.k = new byte[h];
+ }
+
+
+ public void init(DerivationParameters param)
+ {
+ if (!(param instanceof KDFCounterParameters))
+ {
+ throw new IllegalArgumentException("Wrong type of arguments given");
+ }
+
+ KDFCounterParameters kdfParams = (KDFCounterParameters)param;
+
+ // --- init mac based PRF ---
+
+ this.prf.init(new KeyParameter(kdfParams.getKI()));
+
+ // --- set arguments ---
+
+ this.fixedInputData = kdfParams.getFixedInputData();
+
+ int r = kdfParams.getR();
+ this.ios = new byte[r / 8];
+
+ BigInteger maxSize = TWO.pow(r).multiply(BigInteger.valueOf(h));
+ this.maxSizeExcl = maxSize.compareTo(INTEGER_MAX) == 1 ?
+ Integer.MAX_VALUE : maxSize.intValue();
+
+ // --- set operational state ---
+
+ generatedBytes = 0;
+ }
+
+
+ public Mac getMac()
+ {
+ return prf;
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+
+ int generatedBytesAfter = generatedBytes + len;
+ if (generatedBytesAfter < 0 || generatedBytesAfter >= maxSizeExcl)
+ {
+ throw new DataLengthException(
+ "Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
+ }
+
+ if (generatedBytes % h == 0)
+ {
+ generateNext();
+ }
+
+ // copy what is left in the currentT (1..hash
+ int toGenerate = len;
+ int posInK = generatedBytes % h;
+ int leftInK = h - generatedBytes % h;
+ int toCopy = Math.min(leftInK, toGenerate);
+ System.arraycopy(k, posInK, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+
+ while (toGenerate > 0)
+ {
+ generateNext();
+ toCopy = Math.min(h, toGenerate);
+ System.arraycopy(k, 0, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
+
+ return len;
+ }
+
+ private void generateNext()
+ {
+ int i = generatedBytes / h + 1;
+
+ // encode i into counter buffer
+ switch (ios.length)
+ {
+ case 4:
+ ios[0] = (byte)(i >>> 24);
+ // fall through
+ case 3:
+ ios[ios.length - 3] = (byte)(i >>> 16);
+ // fall through
+ case 2:
+ ios[ios.length - 2] = (byte)(i >>> 8);
+ // fall through
+ case 1:
+ ios[ios.length - 1] = (byte)i;
+ break;
+ default:
+ throw new IllegalStateException("Unsupported size of counter i");
+ }
+
+
+ // special case for K(0): K(0) is empty, so no update
+ prf.update(ios, 0, ios.length);
+ prf.update(fixedInputData, 0, fixedInputData.length);
+ prf.doFinal(k, 0);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java
new file mode 100644
index 0000000..6115a1a
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFDoublePipelineIterationBytesGenerator.java
@@ -0,0 +1,181 @@
+package org.bouncycastle.crypto.generators;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.DerivationParameters;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.MacDerivationFunction;
+import org.bouncycastle.crypto.params.KDFDoublePipelineIterationParameters;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * This KDF has been defined by the publicly available NIST SP 800-108 specification.
+ */
+public class KDFDoublePipelineIterationBytesGenerator
+ implements MacDerivationFunction
+{
+
+ private static final BigInteger INTEGER_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ // please refer to the standard for the meaning of the variable names
+ // all field lengths are in bytes, not in bits as specified by the standard
+
+ // fields set by the constructor
+ private final Mac prf;
+ private final int h;
+
+ // fields set by init
+ private byte[] fixedInputData;
+ private int maxSizeExcl;
+ // ios is i defined as an octet string (the binary representation)
+ private byte[] ios;
+ private boolean useCounter;
+
+ // operational
+ private int generatedBytes;
+ // k is used as buffer for all K(i) values
+ private byte[] a;
+ private byte[] k;
+
+
+ public KDFDoublePipelineIterationBytesGenerator(Mac prf)
+ {
+ this.prf = prf;
+ this.h = prf.getMacSize();
+ this.a = new byte[h];
+ this.k = new byte[h];
+ }
+
+ public void init(DerivationParameters params)
+ {
+ if (!(params instanceof KDFDoublePipelineIterationParameters))
+ {
+ throw new IllegalArgumentException("Wrong type of arguments given");
+ }
+
+ KDFDoublePipelineIterationParameters dpiParams = (KDFDoublePipelineIterationParameters)params;
+
+ // --- init mac based PRF ---
+
+ this.prf.init(new KeyParameter(dpiParams.getKI()));
+
+ // --- set arguments ---
+
+ this.fixedInputData = dpiParams.getFixedInputData();
+
+ int r = dpiParams.getR();
+ this.ios = new byte[r / 8];
+
+ if (dpiParams.useCounter())
+ {
+ // this is more conservative than the spec
+ BigInteger maxSize = TWO.pow(r).multiply(BigInteger.valueOf(h));
+ this.maxSizeExcl = maxSize.compareTo(INTEGER_MAX) == 1 ?
+ Integer.MAX_VALUE : maxSize.intValue();
+ }
+ else
+ {
+ this.maxSizeExcl = Integer.MAX_VALUE;
+ }
+
+ this.useCounter = dpiParams.useCounter();
+
+ // --- set operational state ---
+
+ generatedBytes = 0;
+ }
+
+ public Mac getMac()
+ {
+ return prf;
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+
+ int generatedBytesAfter = generatedBytes + len;
+ if (generatedBytesAfter < 0 || generatedBytesAfter >= maxSizeExcl)
+ {
+ throw new DataLengthException(
+ "Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
+ }
+
+ if (generatedBytes % h == 0)
+ {
+ generateNext();
+ }
+
+ // copy what is left in the currentT (1..hash
+ int toGenerate = len;
+ int posInK = generatedBytes % h;
+ int leftInK = h - generatedBytes % h;
+ int toCopy = Math.min(leftInK, toGenerate);
+ System.arraycopy(k, posInK, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+
+ while (toGenerate > 0)
+ {
+ generateNext();
+ toCopy = Math.min(h, toGenerate);
+ System.arraycopy(k, 0, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
+
+ return len;
+ }
+
+ private void generateNext()
+ {
+
+ if (generatedBytes == 0)
+ {
+ // --- step 4 ---
+ prf.update(fixedInputData, 0, fixedInputData.length);
+ prf.doFinal(a, 0);
+ }
+ else
+ {
+ // --- step 5a ---
+ prf.update(a, 0, a.length);
+ prf.doFinal(a, 0);
+ }
+
+ // --- step 5b ---
+ prf.update(a, 0, a.length);
+
+ if (useCounter)
+ {
+ int i = generatedBytes / h + 1;
+
+ // encode i into counter buffer
+ switch (ios.length)
+ {
+ case 4:
+ ios[0] = (byte)(i >>> 24);
+ // fall through
+ case 3:
+ ios[ios.length - 3] = (byte)(i >>> 16);
+ // fall through
+ case 2:
+ ios[ios.length - 2] = (byte)(i >>> 8);
+ // fall through
+ case 1:
+ ios[ios.length - 1] = (byte)i;
+ break;
+ default:
+ throw new IllegalStateException("Unsupported size of counter i");
+ }
+ prf.update(ios, 0, ios.length);
+ }
+
+ prf.update(fixedInputData, 0, fixedInputData.length);
+ prf.doFinal(k, 0);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java
new file mode 100644
index 0000000..6003037
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/KDFFeedbackBytesGenerator.java
@@ -0,0 +1,175 @@
+package org.bouncycastle.crypto.generators;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.DerivationParameters;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.MacDerivationFunction;
+import org.bouncycastle.crypto.params.KDFFeedbackParameters;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * This KDF has been defined by the publicly available NIST SP 800-108 specification.
+ */
+public class KDFFeedbackBytesGenerator
+ implements MacDerivationFunction
+{
+
+ private static final BigInteger INTEGER_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ // please refer to the standard for the meaning of the variable names
+ // all field lengths are in bytes, not in bits as specified by the standard
+
+ // fields set by the constructor
+ private final Mac prf;
+ private final int h;
+
+ // fields set by init
+ private byte[] fixedInputData;
+ private int maxSizeExcl;
+ // ios is i defined as an octet string (the binary representation)
+ private byte[] ios;
+ private byte[] iv;
+ private boolean useCounter;
+
+ // operational
+ private int generatedBytes;
+ // k is used as buffer for all K(i) values
+ private byte[] k;
+
+
+ public KDFFeedbackBytesGenerator(Mac prf)
+ {
+ this.prf = prf;
+ this.h = prf.getMacSize();
+ this.k = new byte[h];
+ }
+
+ public void init(DerivationParameters params)
+ {
+ if (!(params instanceof KDFFeedbackParameters))
+ {
+ throw new IllegalArgumentException("Wrong type of arguments given");
+ }
+
+ KDFFeedbackParameters feedbackParams = (KDFFeedbackParameters)params;
+
+ // --- init mac based PRF ---
+
+ this.prf.init(new KeyParameter(feedbackParams.getKI()));
+
+ // --- set arguments ---
+
+ this.fixedInputData = feedbackParams.getFixedInputData();
+
+ int r = feedbackParams.getR();
+ this.ios = new byte[r / 8];
+
+ if (feedbackParams.useCounter())
+ {
+ // this is more conservative than the spec
+ BigInteger maxSize = TWO.pow(r).multiply(BigInteger.valueOf(h));
+ this.maxSizeExcl = maxSize.compareTo(INTEGER_MAX) == 1 ?
+ Integer.MAX_VALUE : maxSize.intValue();
+ }
+ else
+ {
+ this.maxSizeExcl = Integer.MAX_VALUE;
+ }
+
+ this.iv = feedbackParams.getIV();
+ this.useCounter = feedbackParams.useCounter();
+
+ // --- set operational state ---
+
+ generatedBytes = 0;
+ }
+
+ public Mac getMac()
+ {
+ return prf;
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+
+ int generatedBytesAfter = generatedBytes + len;
+ if (generatedBytesAfter < 0 || generatedBytesAfter >= maxSizeExcl)
+ {
+ throw new DataLengthException(
+ "Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
+ }
+
+ if (generatedBytes % h == 0)
+ {
+ generateNext();
+ }
+
+ // copy what is left in the currentT (1..hash
+ int toGenerate = len;
+ int posInK = generatedBytes % h;
+ int leftInK = h - generatedBytes % h;
+ int toCopy = Math.min(leftInK, toGenerate);
+ System.arraycopy(k, posInK, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+
+ while (toGenerate > 0)
+ {
+ generateNext();
+ toCopy = Math.min(h, toGenerate);
+ System.arraycopy(k, 0, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
+
+ return len;
+ }
+
+ private void generateNext()
+ {
+
+ // TODO enable IV
+ if (generatedBytes == 0)
+ {
+ prf.update(iv, 0, iv.length);
+ }
+ else
+ {
+ prf.update(k, 0, k.length);
+ }
+
+ if (useCounter)
+ {
+ int i = generatedBytes / h + 1;
+
+ // encode i into counter buffer
+ switch (ios.length)
+ {
+ case 4:
+ ios[0] = (byte)(i >>> 24);
+ // fall through
+ case 3:
+ ios[ios.length - 3] = (byte)(i >>> 16);
+ // fall through
+ case 2:
+ ios[ios.length - 2] = (byte)(i >>> 8);
+ // fall through
+ case 1:
+ ios[ios.length - 1] = (byte)i;
+ break;
+ default:
+ throw new IllegalStateException("Unsupported size of counter i");
+ }
+ prf.update(ios, 0, ios.length);
+ }
+
+ prf.update(fixedInputData, 0, fixedInputData.length);
+ prf.doFinal(k, 0);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
index 640ead4..0954d48 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
@@ -58,7 +58,7 @@ public class PKCS5S2ParametersGenerator
hMac.doFinal(state, 0);
System.arraycopy(state, 0, out, outOff, state.length);
-
+
for (int count = 1; count < c; count++)
{
hMac.update(state, 0, state.length);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/Poly1305KeyGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/Poly1305KeyGenerator.java
new file mode 100644
index 0000000..9165973
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/Poly1305KeyGenerator.java
@@ -0,0 +1,117 @@
+package org.bouncycastle.crypto.generators;
+
+import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.KeyGenerationParameters;
+import org.bouncycastle.crypto.macs.Poly1305;
+
+/**
+ * Generates keys for the Poly1305 MAC.
+ * <p>
+ * Poly1305 keys are 256 bit keys consisting of a 128 bit secret key used for the underlying block
+ * cipher followed by a 128 bit {@code r} value used for the polynomial portion of the Mac. <br>
+ * The {@code r} value has a specific format with some bits required to be cleared, resulting in an
+ * effective 106 bit key. <br>
+ * A separately generated 256 bit key can be modified to fit the Poly1305 key format by using the
+ * {@link #clamp(byte[])} method to clear the required bits.
+ *
+ * @see Poly1305
+ */
+public class Poly1305KeyGenerator
+ extends CipherKeyGenerator
+{
+ private static final byte R_MASK_LOW_2 = (byte)0xFC;
+ private static final byte R_MASK_HIGH_4 = (byte)0x0F;
+
+ /**
+ * Initialises the key generator.<br>
+ * Poly1305 keys are always 256 bits, so the key length in the provided parameters is ignored.
+ */
+ public void init(KeyGenerationParameters param)
+ {
+ // Poly1305 keys are always 256 bits
+ super.init(new KeyGenerationParameters(param.getRandom(), 256));
+ }
+
+ /**
+ * Generates a 256 bit key in the format required for Poly1305 - e.g.
+ * <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
+ * as per {@link #clamp(byte[])}.
+ */
+ public byte[] generateKey()
+ {
+ final byte[] key = super.generateKey();
+ clamp(key);
+ return key;
+ }
+
+ /**
+ * Modifies an existing 32 byte key value to comply with the requirements of the Poly1305 key by
+ * clearing required bits in the <code>r</code> (second 16 bytes) portion of the key.<br>
+ * Specifically:
+ * <ul>
+ * <li>r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})</li>
+ * <li>r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252})</li>
+ * </ul>
+ *
+ * @param a 32 byte key value <code>k[0] ... k[15], r[0] ... r[15]</code>
+ */
+ public static void clamp(byte[] key)
+ {
+ /*
+ * Key is k[0] ... k[15], r[0] ... r[15] as per poly1305_aes_clamp in ref impl.
+ */
+ if (key.length != 32)
+ {
+ throw new IllegalArgumentException("Poly1305 key must be 256 bits.");
+ }
+
+ /*
+ * r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})
+ */
+ key[19] &= R_MASK_HIGH_4;
+ key[23] &= R_MASK_HIGH_4;
+ key[27] &= R_MASK_HIGH_4;
+ key[31] &= R_MASK_HIGH_4;
+
+ /*
+ * r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252}).
+ */
+ key[20] &= R_MASK_LOW_2;
+ key[24] &= R_MASK_LOW_2;
+ key[28] &= R_MASK_LOW_2;
+ }
+
+ /**
+ * Checks a 32 byte key for compliance with the Poly1305 key requirements, e.g.
+ * <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
+ * as per {@link #clamp(byte[])}.
+ *
+ * @throws IllegalArgumentException if the key is of the wrong length, or has invalid bits set
+ * in the <code>r</code> portion of the key.
+ */
+ public static void checkKey(byte[] key)
+ {
+ if (key.length != 32)
+ {
+ throw new IllegalArgumentException("Poly1305 key must be 256 bits.");
+ }
+
+ checkMask(key[19], R_MASK_HIGH_4);
+ checkMask(key[23], R_MASK_HIGH_4);
+ checkMask(key[27], R_MASK_HIGH_4);
+ checkMask(key[31], R_MASK_HIGH_4);
+
+ checkMask(key[20], R_MASK_LOW_2);
+ checkMask(key[24], R_MASK_LOW_2);
+ checkMask(key[28], R_MASK_LOW_2);
+ }
+
+ private static void checkMask(byte b, byte mask)
+ {
+ if ((b & (~mask)) != 0)
+ {
+ throw new IllegalArgumentException("Invalid format for r portion of Poly1305 key.");
+ }
+ }
+
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/generators/package.html
deleted file mode 100644
index 9d73ce3..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Generators for keys, key pairs and password based encryption algorithms.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java b/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java
index bb09a76..93b04e9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherInputStream.java
@@ -5,15 +5,15 @@ import java.io.IOException;
import java.io.InputStream;
import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.StreamCipher;
+import org.bouncycastle.crypto.modes.AEADBlockCipher;
/**
- * A CipherInputStream is composed of an InputStream and a BufferedBlockCipher so
- * that read() methods return data that are read in from the
- * underlying InputStream but have been additionally processed by the
- * Cipher. The Cipher must be fully initialized before being used by
- * a CipherInputStream.
- * <p>
+ * A CipherInputStream is composed of an InputStream and a cipher so that read() methods return data
+ * that are read in from the underlying InputStream but have been additionally processed by the
+ * Cipher. The cipher must be fully initialized before being used by a CipherInputStream.
+ * <p/>
* For example, if the Cipher is initialized for decryption, the
* CipherInputStream will attempt to read in data and decrypt them,
* before returning the decrypted data.
@@ -23,9 +23,10 @@ public class CipherInputStream
{
private BufferedBlockCipher bufferedBlockCipher;
private StreamCipher streamCipher;
+ private AEADBlockCipher aeadBlockCipher;
- private byte[] buf;
- private byte[] inBuf;
+ private final byte[] buf;
+ private final byte[] inBuf;
private int bufOff;
private int maxBuf;
@@ -62,95 +63,116 @@ public class CipherInputStream
}
/**
- * grab the next chunk of input from the underlying input stream
+ * Constructs a CipherInputStream from an InputStream and an AEADBlockCipher.
+ */
+ public CipherInputStream(InputStream is, AEADBlockCipher cipher)
+ {
+ super(is);
+
+ this.aeadBlockCipher = cipher;
+
+ buf = new byte[cipher.getOutputSize(INPUT_BUF_SIZE)];
+ inBuf = new byte[INPUT_BUF_SIZE];
+ }
+
+ /**
+ * Read data from underlying stream and process with cipher until end of stream or some data is
+ * available after cipher processing.
+ *
+ * @return -1 to indicate end of stream, or the number of bytes (> 0) available.
*/
private int nextChunk()
throws IOException
{
- int available = super.available();
-
- // must always try to read 1 byte!
- // some buggy InputStreams return < 0!
- if (available <= 0)
+ if (finalized)
{
- available = 1;
+ return -1;
}
- if (available > inBuf.length)
- {
- available = super.read(inBuf, 0, inBuf.length);
- }
- else
- {
- available = super.read(inBuf, 0, available);
- }
+ bufOff = 0;
+ maxBuf = 0;
- if (available < 0)
+ // Keep reading until EOF or cipher processing produces data
+ while (maxBuf == 0)
{
- if (finalized)
+ int read = in.read(inBuf);
+ if (read == -1)
{
- return -1;
+ finaliseCipher();
+ if (maxBuf == 0)
+ {
+ return -1;
+ }
+ return maxBuf;
}
try
{
if (bufferedBlockCipher != null)
{
- maxBuf = bufferedBlockCipher.doFinal(buf, 0);
+ maxBuf = bufferedBlockCipher.processBytes(inBuf, 0, read, buf, 0);
+ }
+ else if (aeadBlockCipher != null)
+ {
+ maxBuf = aeadBlockCipher.processBytes(inBuf, 0, read, buf, 0);
}
else
{
- maxBuf = 0; // a stream cipher
+ streamCipher.processBytes(inBuf, 0, read, buf, 0);
+ maxBuf = read;
}
}
catch (Exception e)
{
- throw new IOException("error processing stream: " + e.toString());
+ throw new IOException("Error processing stream " + e);
}
+ }
+ return maxBuf;
+ }
- bufOff = 0;
-
+ private void finaliseCipher()
+ throws IOException
+ {
+ try
+ {
finalized = true;
-
- if (bufOff == maxBuf)
+ if (bufferedBlockCipher != null)
{
- return -1;
+ maxBuf = bufferedBlockCipher.doFinal(buf, 0);
}
- }
- else
- {
- bufOff = 0;
-
- try
+ else if (aeadBlockCipher != null)
{
- if (bufferedBlockCipher != null)
- {
- maxBuf = bufferedBlockCipher.processBytes(inBuf, 0, available, buf, 0);
- }
- else
- {
- streamCipher.processBytes(inBuf, 0, available, buf, 0);
- maxBuf = available;
- }
+ maxBuf = aeadBlockCipher.doFinal(buf, 0);
}
- catch (Exception e)
+ else
{
- throw new IOException("error processing stream: " + e.toString());
- }
-
- if (maxBuf == 0) // not enough bytes read for first block...
- {
- return nextChunk();
+ maxBuf = 0; // a stream cipher
}
}
-
- return maxBuf;
+ catch (final InvalidCipherTextException e)
+ {
+ throw new InvalidCipherTextIOException("Error finalising cipher", e);
+ }
+ catch (Exception e)
+ {
+ throw new IOException("Error finalising cipher " + e);
+ }
}
+ /**
+ * Reads data from the underlying stream and processes it with the cipher until the cipher
+ * outputs data, and returns the next available byte.
+ * <p/>
+ * If the underlying stream is exhausted by this call, the cipher will be finalised.
+ *
+ * @throws IOException if there was an error closing the input stream.
+ * @throws InvalidCipherTextIOException if the data read from the stream was invalid ciphertext
+ * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails).
+ */
public int read()
throws IOException
{
- if (bufOff == maxBuf)
+ if (bufOff >= maxBuf)
{
if (nextChunk() < 0)
{
@@ -161,6 +183,19 @@ public class CipherInputStream
return buf[bufOff++] & 0xff;
}
+ /**
+ * Reads data from the underlying stream and processes it with the cipher until the cipher
+ * outputs data, and then returns up to <code>b.length</code> bytes in the provided array.
+ * <p/>
+ * If the underlying stream is exhausted by this call, the cipher will be finalised.
+ *
+ * @param b the buffer into which the data is read.
+ * @return the total number of bytes read into the buffer, or <code>-1</code> if there is no
+ * more data because the end of the stream has been reached.
+ * @throws IOException if there was an error closing the input stream.
+ * @throws InvalidCipherTextIOException if the data read from the stream was invalid ciphertext
+ * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails).
+ */
public int read(
byte[] b)
throws IOException
@@ -168,13 +203,28 @@ public class CipherInputStream
return read(b, 0, b.length);
}
+ /**
+ * Reads data from the underlying stream and processes it with the cipher until the cipher
+ * outputs data, and then returns up to <code>len</code> bytes in the provided array.
+ * <p/>
+ * If the underlying stream is exhausted by this call, the cipher will be finalised.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in the destination array <code>b</code>
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or <code>-1</code> if there is no
+ * more data because the end of the stream has been reached.
+ * @throws IOException if there was an error closing the input stream.
+ * @throws InvalidCipherTextIOException if the data read from the stream was invalid ciphertext
+ * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails).
+ */
public int read(
byte[] b,
int off,
int len)
throws IOException
{
- if (bufOff == maxBuf)
+ if (bufOff >= maxBuf)
{
if (nextChunk() < 0)
{
@@ -182,22 +232,10 @@ public class CipherInputStream
}
}
- int available = maxBuf - bufOff;
-
- if (len > available)
- {
- System.arraycopy(buf, bufOff, b, off, available);
- bufOff = maxBuf;
-
- return available;
- }
- else
- {
- System.arraycopy(buf, bufOff, b, off, len);
- bufOff += len;
-
- return len;
- }
+ int toSupply = Math.min(len, available());
+ System.arraycopy(buf, bufOff, b, off, toSupply);
+ bufOff += toSupply;
+ return toSupply;
}
public long skip(
@@ -209,36 +247,55 @@ public class CipherInputStream
return 0;
}
- int available = maxBuf - bufOff;
+ int skip = (int)Math.min(n, available());
+ bufOff += skip;
+ return skip;
+ }
- if (n > available)
- {
- bufOff = maxBuf;
+ public int available()
+ throws IOException
+ {
+ return maxBuf - bufOff;
+ }
- return available;
+ /**
+ * Closes the underlying input stream and finalises the processing of the data by the cipher.
+ *
+ * @throws IOException if there was an error closing the input stream.
+ * @throws InvalidCipherTextIOException if the data read from the stream was invalid ciphertext
+ * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails).
+ */
+ public void close()
+ throws IOException
+ {
+ try
+ {
+ in.close();
}
- else
+ finally
{
- bufOff += (int)n;
-
- return (int)n;
+ if (!finalized)
+ {
+ // Reset the cipher, discarding any data buffered in it
+ // Errors in cipher finalisation trump I/O error closing input
+ finaliseCipher();
+ }
}
+ maxBuf = bufOff = 0;
}
- public int available()
- throws IOException
+ public void mark(int readlimit)
{
- return maxBuf - bufOff;
}
- public void close()
+ public void reset()
throws IOException
{
- super.close();
}
public boolean markSupported()
{
return false;
}
+
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java b/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java
index 17a7b6d..9beb5b9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/io/CipherOutputStream.java
@@ -5,15 +5,27 @@ import java.io.IOException;
import java.io.OutputStream;
import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.StreamCipher;
+import org.bouncycastle.crypto.modes.AEADBlockCipher;
+/**
+ * A CipherOutputStream is composed of an OutputStream and a cipher so that write() methods process
+ * the written data with the cipher, and the output of the cipher is in turn written to the
+ * underlying OutputStream. The cipher must be fully initialized before being used by a
+ * CipherInputStream.
+ * <p/>
+ * For example, if the cipher is initialized for encryption, the CipherOutputStream will encrypt the
+ * data before writing the encrypted data to the underlying stream.
+ */
public class CipherOutputStream
extends FilterOutputStream
{
private BufferedBlockCipher bufferedBlockCipher;
private StreamCipher streamCipher;
+ private AEADBlockCipher aeadBlockCipher;
- private byte[] oneByte = new byte[1];
+ private final byte[] oneByte = new byte[1];
private byte[] buf;
/**
@@ -26,7 +38,6 @@ public class CipherOutputStream
{
super(os);
this.bufferedBlockCipher = cipher;
- this.buf = new byte[cipher.getBlockSize()];
}
/**
@@ -42,10 +53,19 @@ public class CipherOutputStream
}
/**
+ * Constructs a CipherOutputStream from an OutputStream and a AEADBlockCipher.
+ */
+ public CipherOutputStream(OutputStream os, AEADBlockCipher cipher)
+ {
+ super(os);
+ this.aeadBlockCipher = cipher;
+ }
+
+ /**
* Writes the specified byte to this output stream.
*
* @param b the <code>byte</code>.
- * @exception java.io.IOException if an I/O error occurs.
+ * @throws java.io.IOException if an I/O error occurs.
*/
public void write(
int b)
@@ -53,32 +73,27 @@ public class CipherOutputStream
{
oneByte[0] = (byte)b;
- if (bufferedBlockCipher != null)
+ if (streamCipher != null)
{
- int len = bufferedBlockCipher.processBytes(oneByte, 0, 1, buf, 0);
-
- if (len != 0)
- {
- out.write(buf, 0, len);
- }
+ out.write(streamCipher.returnByte((byte)b));
}
else
{
- out.write(streamCipher.returnByte((byte)b));
+ write(oneByte, 0, 1);
}
}
/**
* Writes <code>b.length</code> bytes from the specified byte array
* to this output stream.
- * <p>
+ * <p/>
* The <code>write</code> method of
* <code>CipherOutputStream</code> calls the <code>write</code>
* method of three arguments with the three arguments
* <code>b</code>, <code>0</code>, and <code>b.length</code>.
*
* @param b the data.
- * @exception java.io.IOException if an I/O error occurs.
+ * @throws java.io.IOException if an I/O error occurs.
* @see #write(byte[], int, int)
*/
public void write(
@@ -92,10 +107,10 @@ public class CipherOutputStream
* Writes <code>len</code> bytes from the specified byte array
* starting at offset <code>off</code> to this output stream.
*
- * @param b the data.
+ * @param b the data.
* @param off the start offset in the data.
* @param len the number of bytes to write.
- * @exception java.io.IOException if an I/O error occurs.
+ * @throws java.io.IOException if an I/O error occurs.
*/
public void write(
byte[] b,
@@ -103,10 +118,10 @@ public class CipherOutputStream
int len)
throws IOException
{
+ ensureCapacity(len);
+
if (bufferedBlockCipher != null)
{
- byte[] buf = new byte[bufferedBlockCipher.getOutputSize(len)];
-
int outLen = bufferedBlockCipher.processBytes(b, off, len, buf, 0);
if (outLen != 0)
@@ -114,10 +129,17 @@ public class CipherOutputStream
out.write(buf, 0, outLen);
}
}
- else
+ else if (aeadBlockCipher != null)
{
- byte[] buf = new byte[len];
+ int outLen = aeadBlockCipher.processBytes(b, off, len, buf, 0);
+ if (outLen != 0)
+ {
+ out.write(buf, 0, outLen);
+ }
+ }
+ else
+ {
streamCipher.processBytes(b, off, len, buf, 0);
out.write(buf, 0, len);
@@ -125,49 +147,78 @@ public class CipherOutputStream
}
/**
+ * Ensure the ciphertext buffer has space sufficient to accept an upcoming output.
+ *
+ * @param outputSize the size of the pending update.
+ */
+ private void ensureCapacity(int outputSize)
+ {
+ // This overestimates buffer on updates for AEAD/padded, but keeps it simple.
+ int bufLen;
+ if (bufferedBlockCipher != null)
+ {
+ bufLen = bufferedBlockCipher.getOutputSize(outputSize);
+ }
+ else if (aeadBlockCipher != null)
+ {
+ bufLen = aeadBlockCipher.getOutputSize(outputSize);
+ }
+ else
+ {
+ bufLen = outputSize;
+ }
+ if ((buf == null) || (buf.length < bufLen))
+ {
+ buf = new byte[bufLen];
+ }
+ }
+
+ /**
* Flushes this output stream by forcing any buffered output bytes
* that have already been processed by the encapsulated cipher object
* to be written out.
- *
- * <p>
+ * <p/>
+ * <p/>
* Any bytes buffered by the encapsulated cipher
* and waiting to be processed by it will not be written out. For example,
* if the encapsulated cipher is a block cipher, and the total number of
* bytes written using one of the <code>write</code> methods is less than
* the cipher's block size, no bytes will be written out.
*
- * @exception java.io.IOException if an I/O error occurs.
+ * @throws java.io.IOException if an I/O error occurs.
*/
public void flush()
throws IOException
{
- super.flush();
+ out.flush();
}
/**
* Closes this output stream and releases any system resources
* associated with this stream.
- * <p>
+ * <p/>
* This method invokes the <code>doFinal</code> method of the encapsulated
* cipher object, which causes any bytes buffered by the encapsulated
* cipher to be processed. The result is written out by calling the
* <code>flush</code> method of this output stream.
- * <p>
+ * <p/>
* This method resets the encapsulated cipher object to its initial state
* and calls the <code>close</code> method of the underlying output
* stream.
*
- * @exception java.io.IOException if an I/O error occurs.
+ * @throws java.io.IOException if an I/O error occurs.
+ * @throws InvalidCipherTextIOException if the data written to this stream was invalid ciphertext
+ * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails).
*/
public void close()
throws IOException
{
+ ensureCapacity(0);
+ IOException error = null;
try
{
if (bufferedBlockCipher != null)
{
- byte[] buf = new byte[bufferedBlockCipher.getOutputSize(0)];
-
int outLen = bufferedBlockCipher.doFinal(buf, 0);
if (outLen != 0)
@@ -175,14 +226,41 @@ public class CipherOutputStream
out.write(buf, 0, outLen);
}
}
+ else if (aeadBlockCipher != null)
+ {
+ int outLen = aeadBlockCipher.doFinal(buf, 0);
+
+ if (outLen != 0)
+ {
+ out.write(buf, 0, outLen);
+ }
+ }
+ }
+ catch (final InvalidCipherTextException e)
+ {
+ error = new InvalidCipherTextIOException("Error finalising cipher data", e);
}
catch (Exception e)
{
- throw new IOException("Error closing stream: " + e.toString());
+ error = new IOException("Error closing stream: " + e);
}
- flush();
-
- super.close();
+ try
+ {
+ flush();
+ out.close();
+ }
+ catch (IOException e)
+ {
+ // Invalid ciphertext takes precedence over close error
+ if (error == null)
+ {
+ error = e;
+ }
+ }
+ if (error != null)
+ {
+ throw error;
+ }
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/io/InvalidCipherTextIOException.java b/bcprov/src/main/java/org/bouncycastle/crypto/io/InvalidCipherTextIOException.java
new file mode 100644
index 0000000..b601d4c
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/io/InvalidCipherTextIOException.java
@@ -0,0 +1,28 @@
+package org.bouncycastle.crypto.io;
+
+import java.io.IOException;
+
+/**
+ * {@link IOException} wrapper around an exception indicating an invalid ciphertext, such as in
+ * authentication failure during finalisation of an AEAD cipher. For use in streams that need to
+ * expose invalid ciphertext errors.
+ */
+public class InvalidCipherTextIOException
+ extends IOException
+{
+ private static final long serialVersionUID = 1L;
+
+ private final Throwable cause;
+
+ public InvalidCipherTextIOException(String message, Throwable cause)
+ {
+ super(message);
+
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/io/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/io/package.html
deleted file mode 100644
index f2c9e40..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/io/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for doing "enhanced" I/O with Digests and MACs.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java b/bcprov/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java
index f4dfc6e..82ac20c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/kems/ECIESKeyEncapsulation.java
@@ -6,11 +6,13 @@ import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.KeyEncapsulation;
+import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.KDFParameters;
import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.BigIntegers;
@@ -106,33 +108,34 @@ public class ECIESKeyEncapsulation
throw new IllegalArgumentException("Public key required for encryption");
}
- BigInteger n = key.getParameters().getN();
- BigInteger h = key.getParameters().getH();
+ ECPublicKeyParameters ecPubKey = (ECPublicKeyParameters)key;
+ ECDomainParameters ecParams = ecPubKey.getParameters();
+ ECCurve curve = ecParams.getCurve();
+ BigInteger n = ecParams.getN();
+ BigInteger h = ecParams.getH();
// Generate the ephemeral key pair
BigInteger r = BigIntegers.createRandomInRange(ONE, n, rnd);
- ECPoint gTilde = key.getParameters().getG().multiply(r);
+
+ // Compute the static-ephemeral key agreement
+ BigInteger rPrime = CofactorMode ? r.multiply(h).mod(n) : r;
+
+ ECPoint[] ghTilde = new ECPoint[]{
+ ecParams.getG().multiply(r),
+ ecPubKey.getQ().multiply(rPrime)
+ };
+
+ // NOTE: More efficient than normalizing each individually
+ curve.normalizeAll(ghTilde);
+
+ ECPoint gTilde = ghTilde[0], hTilde = ghTilde[1];
// Encode the ephemeral public key
byte[] C = gTilde.getEncoded();
System.arraycopy(C, 0, out, outOff, C.length);
- // Compute the static-ephemeral key agreement
- BigInteger rPrime;
- if (CofactorMode)
- {
- rPrime = r.multiply(h).mod(n);
- }
- else
- {
- rPrime = r;
- }
-
- ECPoint hTilde = ((ECPublicKeyParameters)key).getQ().multiply(rPrime);
-
// Encode the shared secret value
- int PEHlen = (key.getParameters().getCurve().getFieldSize() + 7) / 8;
- byte[] PEH = BigIntegers.asUnsignedByteArray(PEHlen, hTilde.getX().toBigInteger());
+ byte[] PEH = hTilde.getAffineXCoord().getEncoded();
// Initialise the KDF
byte[] kdfInput;
@@ -186,40 +189,36 @@ public class ECIESKeyEncapsulation
throw new IllegalArgumentException("Private key required for encryption");
}
- BigInteger n = key.getParameters().getN();
- BigInteger h = key.getParameters().getH();
+ ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
+ ECDomainParameters ecParams = ecPrivKey.getParameters();
+ ECCurve curve = ecParams.getCurve();
+ BigInteger n = ecParams.getN();
+ BigInteger h = ecParams.getH();
// Decode the ephemeral public key
byte[] C = new byte[inLen];
System.arraycopy(in, inOff, C, 0, inLen);
- ECPoint gTilde = key.getParameters().getCurve().decodePoint(C);
+
+ // NOTE: Decoded points are already normalized (i.e in affine form)
+ ECPoint gTilde = curve.decodePoint(C);
// Compute the static-ephemeral key agreement
- ECPoint gHat;
+ ECPoint gHat = gTilde;
if ((CofactorMode) || (OldCofactorMode))
{
- gHat = gTilde.multiply(h);
- }
- else
- {
- gHat = gTilde;
+ gHat = gHat.multiply(h);
}
- BigInteger xHat;
+ BigInteger xHat = ecPrivKey.getD();
if (CofactorMode)
{
- xHat = ((ECPrivateKeyParameters)key).getD().multiply(h.modInverse(n)).mod(n);
- }
- else
- {
- xHat = ((ECPrivateKeyParameters)key).getD();
+ xHat = xHat.multiply(h.modInverse(n)).mod(n);
}
- ECPoint hTilde = gHat.multiply(xHat);
+ ECPoint hTilde = gHat.multiply(xHat).normalize();
// Encode the shared secret value
- int PEHlen = (key.getParameters().getCurve().getFieldSize() + 7) / 8;
- byte[] PEH = BigIntegers.asUnsignedByteArray(PEHlen, hTilde.getX().toBigInteger());
+ byte[] PEH = hTilde.getAffineXCoord().getEncoded();
// Initialise the KDF
byte[] kdfInput;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/kems/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/kems/package.html
deleted file mode 100644
index a5174b3..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/kems/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-The Key Encapsulation Mechanisms (KEMs) from ISO 18033-2.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java
index 8a3b5bb..1aa8ede 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java
@@ -5,6 +5,7 @@ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
+import org.bouncycastle.crypto.params.KeyParameter;
/**
* CMAC - as specified at www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
@@ -103,25 +104,36 @@ public class CMac implements Mac
return cipher.getAlgorithmName();
}
- private static byte[] doubleLu(byte[] in)
+ private static int shiftLeft(byte[] block, byte[] output)
{
- int FirstBit = (in[0] & 0xFF) >> 7;
- byte[] ret = new byte[in.length];
- for (int i = 0; i < in.length - 1; i++)
- {
- ret[i] = (byte)((in[i] << 1) + ((in[i + 1] & 0xFF) >> 7));
- }
- ret[in.length - 1] = (byte)(in[in.length - 1] << 1);
- if (FirstBit == 1)
+ int i = block.length;
+ int bit = 0;
+ while (--i >= 0)
{
- ret[in.length - 1] ^= in.length == 16 ? CONSTANT_128 : CONSTANT_64;
+ int b = block[i] & 0xff;
+ output[i] = (byte)((b << 1) | bit);
+ bit = (b >>> 7) & 1;
}
+ return bit;
+ }
+
+ private static byte[] doubleLu(byte[] in)
+ {
+ byte[] ret = new byte[in.length];
+ int carry = shiftLeft(in, ret);
+ int xor = 0xff & (in.length == 16 ? CONSTANT_128 : CONSTANT_64);
+
+ /*
+ * NOTE: This construction is an attempt at a constant-time implementation.
+ */
+ ret[in.length - 1] ^= (xor >>> ((1 - carry) << 3));
+
return ret;
}
public void init(CipherParameters params)
{
- if (params != null)
+ if (params instanceof KeyParameter)
{
cipher.init(true, params);
@@ -130,6 +142,10 @@ public class CMac implements Mac
cipher.processBlock(ZEROES, 0, L, 0);
Lu = doubleLu(L);
Lu2 = doubleLu(Lu);
+ } else if (params != null)
+ {
+ // CMAC mode does not permit IV to underlying CBC mode
+ throw new IllegalArgumentException("CMac mode only permits key to be set.");
}
reset();
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java
new file mode 100644
index 0000000..150eb61
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java
@@ -0,0 +1,279 @@
+package org.bouncycastle.crypto.macs;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.crypto.util.Pack;
+
+/**
+ * Poly1305 message authentication code, designed by D. J. Bernstein.
+ * <p>
+ * Poly1305 computes a 128-bit (16 bytes) authenticator, using a 128 bit nonce and a 256 bit key
+ * consisting of a 128 bit key applied to an underlying cipher, and a 128 bit key (with 106
+ * effective key bits) used in the authenticator.
+ * <p>
+ * The polynomial calculation in this implementation is adapted from the public domain <a
+ * href="https://github.com/floodyberry/poly1305-donna">poly1305-donna-unrolled</a> C implementation
+ * by Andrew M (@floodyberry).
+ * @see Poly1305KeyGenerator
+ */
+public class Poly1305
+ implements Mac
+{
+ private static final int BLOCK_SIZE = 16;
+
+ private final BlockCipher cipher;
+
+ private final byte[] singleByte = new byte[1];
+
+ // Initialised state
+
+ /** Polynomial key */
+ private int r0, r1, r2, r3, r4;
+
+ /** Precomputed 5 * r[1..4] */
+ private int s1, s2, s3, s4;
+
+ /** Encrypted nonce */
+ private int k0, k1, k2, k3;
+
+ // Accumulating state
+
+ /** Current block of buffered input */
+ private final byte[] currentBlock = new byte[BLOCK_SIZE];
+
+ /** Current offset in input buffer */
+ private int currentBlockOffset = 0;
+
+ /** Polynomial accumulator */
+ private int h0, h1, h2, h3, h4;
+
+ /**
+ * Constructs a Poly1305 MAC, using a 128 bit block cipher.
+ */
+ public Poly1305(final BlockCipher cipher)
+ {
+ if (cipher.getBlockSize() != BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException("Poly1305 requires a 128 bit block cipher.");
+ }
+ this.cipher = cipher;
+ }
+
+ /**
+ * Initialises the Poly1305 MAC.
+ *
+ * @param a {@link ParametersWithIV} containing a 128 bit nonce and a {@link KeyParameter} with
+ * a 256 bit key complying to the {@link Poly1305KeyGenerator Poly1305 key format}.
+ */
+ public void init(final CipherParameters params)
+ throws IllegalArgumentException
+ {
+ final byte[] nonce;
+ final byte[] key;
+ if ((params instanceof ParametersWithIV) && ((ParametersWithIV)params).getParameters() instanceof KeyParameter)
+ {
+ nonce = ((ParametersWithIV)params).getIV();
+ key = ((KeyParameter)((ParametersWithIV)params).getParameters()).getKey();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Poly1305 requires a key and and IV.");
+ }
+
+ setKey(key, nonce);
+ reset();
+ }
+
+ private void setKey(final byte[] key, final byte[] nonce)
+ {
+ if (nonce.length != BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException("Poly1305 requires a 128 bit IV.");
+ }
+ Poly1305KeyGenerator.checkKey(key);
+
+ // Extract r portion of key
+ int t0 = Pack.littleEndianToInt(key, BLOCK_SIZE + 0);
+ int t1 = Pack.littleEndianToInt(key, BLOCK_SIZE + 4);
+ int t2 = Pack.littleEndianToInt(key, BLOCK_SIZE + 8);
+ int t3 = Pack.littleEndianToInt(key, BLOCK_SIZE + 12);
+
+ r0 = t0 & 0x3ffffff; t0 >>>= 26; t0 |= t1 << 6;
+ r1 = t0 & 0x3ffff03; t1 >>>= 20; t1 |= t2 << 12;
+ r2 = t1 & 0x3ffc0ff; t2 >>>= 14; t2 |= t3 << 18;
+ r3 = t2 & 0x3f03fff; t3 >>>= 8;
+ r4 = t3 & 0x00fffff;
+
+ // Precompute multipliers
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ // Compute encrypted nonce
+ final byte[] cipherKey = new byte[BLOCK_SIZE];
+ System.arraycopy(key, 0, cipherKey, 0, cipherKey.length);
+
+ cipher.init(true, new KeyParameter(cipherKey));
+ cipher.processBlock(nonce, 0, cipherKey, 0);
+
+ k0 = Pack.littleEndianToInt(cipherKey, 0);
+ k1 = Pack.littleEndianToInt(cipherKey, 4);
+ k2 = Pack.littleEndianToInt(cipherKey, 8);
+ k3 = Pack.littleEndianToInt(cipherKey, 12);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Poly1305-" + cipher.getAlgorithmName();
+ }
+
+ public int getMacSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public void update(final byte in)
+ throws IllegalStateException
+ {
+ singleByte[0] = in;
+ update(singleByte, 0, 1);
+ }
+
+ public void update(final byte[] in, final int inOff, final int len)
+ throws DataLengthException,
+ IllegalStateException
+ {
+ int copied = 0;
+ while (len > copied)
+ {
+ if (currentBlockOffset == BLOCK_SIZE)
+ {
+ processBlock();
+ currentBlockOffset = 0;
+ }
+
+ int toCopy = Math.min((len - copied), BLOCK_SIZE - currentBlockOffset);
+ System.arraycopy(in, copied + inOff, currentBlock, currentBlockOffset, toCopy);
+ copied += toCopy;
+ currentBlockOffset += toCopy;
+ }
+
+ }
+
+ private void processBlock()
+ {
+ if (currentBlockOffset < BLOCK_SIZE)
+ {
+ currentBlock[currentBlockOffset] = 1;
+ for (int i = currentBlockOffset + 1; i < BLOCK_SIZE; i++)
+ {
+ currentBlock[i] = 0;
+ }
+ }
+
+ final long t0 = 0xffffffffL & Pack.littleEndianToInt(currentBlock, 0);
+ final long t1 = 0xffffffffL & Pack.littleEndianToInt(currentBlock, 4);
+ final long t2 = 0xffffffffL & Pack.littleEndianToInt(currentBlock, 8);
+ final long t3 = 0xffffffffL & Pack.littleEndianToInt(currentBlock, 12);
+
+ h0 += t0 & 0x3ffffff;
+ h1 += (((t1 << 32) | t0) >>> 26) & 0x3ffffff;
+ h2 += (((t2 << 32) | t1) >>> 20) & 0x3ffffff;
+ h3 += (((t3 << 32) | t2) >>> 14) & 0x3ffffff;
+ h4 += (t3 >>> 8);
+
+ if (currentBlockOffset == BLOCK_SIZE)
+ {
+ h4 += (1 << 24);
+ }
+
+ long tp0 = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1);
+ long tp1 = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2);
+ long tp2 = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3);
+ long tp3 = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4);
+ long tp4 = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0);
+
+ long b;
+ h0 = (int)tp0 & 0x3ffffff; b = (tp0 >>> 26);
+ tp1 += b; h1 = (int)tp1 & 0x3ffffff; b = ((tp1 >>> 26) & 0xffffffff);
+ tp2 += b; h2 = (int)tp2 & 0x3ffffff; b = ((tp2 >>> 26) & 0xffffffff);
+ tp3 += b; h3 = (int)tp3 & 0x3ffffff; b = (tp3 >>> 26);
+ tp4 += b; h4 = (int)tp4 & 0x3ffffff; b = (tp4 >>> 26);
+ h0 += b * 5;
+ }
+
+ public int doFinal(final byte[] out, final int outOff)
+ throws DataLengthException,
+ IllegalStateException
+ {
+ if (outOff + BLOCK_SIZE > out.length)
+ {
+ throw new DataLengthException("Output buffer is too short.");
+ }
+
+ if (currentBlockOffset > 0)
+ {
+ // Process padded final block
+ processBlock();
+ }
+
+ long f0, f1, f2, f3;
+
+ int b = h0 >>> 26;
+ h0 = h0 & 0x3ffffff;
+ h1 += b; b = h1 >>> 26; h1 = h1 & 0x3ffffff;
+ h2 += b; b = h2 >>> 26; h2 = h2 & 0x3ffffff;
+ h3 += b; b = h3 >>> 26; h3 = h3 & 0x3ffffff;
+ h4 += b; b = h4 >>> 26; h4 = h4 & 0x3ffffff;
+ h0 += b * 5;
+
+ int g0, g1, g2, g3, g4;
+ g0 = h0 + 5; b = g0 >>> 26; g0 &= 0x3ffffff;
+ g1 = h1 + b; b = g1 >>> 26; g1 &= 0x3ffffff;
+ g2 = h2 + b; b = g2 >>> 26; g2 &= 0x3ffffff;
+ g3 = h3 + b; b = g3 >>> 26; g3 &= 0x3ffffff;
+ g4 = h4 + b - (1 << 26);
+
+ b = (g4 >>> 31) - 1;
+ int nb = ~b;
+ h0 = (h0 & nb) | (g0 & b);
+ h1 = (h1 & nb) | (g1 & b);
+ h2 = (h2 & nb) | (g2 & b);
+ h3 = (h3 & nb) | (g3 & b);
+ h4 = (h4 & nb) | (g4 & b);
+
+ f0 = (((h0 ) | (h1 << 26)) & 0xffffffffl) + (0xffffffffL & k0);
+ f1 = (((h1 >>> 6 ) | (h2 << 20)) & 0xffffffffl) + (0xffffffffL & k1);
+ f2 = (((h2 >>> 12) | (h3 << 14)) & 0xffffffffl) + (0xffffffffL & k2);
+ f3 = (((h3 >>> 18) | (h4 << 8 )) & 0xffffffffl) + (0xffffffffL & k3);
+
+ Pack.intToLittleEndian((int)f0, out, outOff);
+ f1 += (f0 >>> 32);
+ Pack.intToLittleEndian((int)f1, out, outOff + 4);
+ f2 += (f1 >>> 32);
+ Pack.intToLittleEndian((int)f2, out, outOff + 8);
+ f3 += (f2 >>> 32);
+ Pack.intToLittleEndian((int)f3, out, outOff + 12);
+
+ reset();
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ currentBlockOffset = 0;
+
+ h0 = h1 = h2 = h3 = h4 = 0;
+ }
+
+ private static final long mul32x32_64(int i1, int i2)
+ {
+ return ((long)i1) * i2;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java
new file mode 100644
index 0000000..6097247
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java
@@ -0,0 +1,119 @@
+package org.bouncycastle.crypto.macs;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.digests.SkeinEngine;
+import org.bouncycastle.crypto.engines.ThreefishEngine;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.SkeinParameters;
+
+/**
+ * Implementation of the Skein parameterised MAC function in 256, 512 and 1024 bit block sizes,
+ * based on the {@link ThreefishEngine Threefish} tweakable block cipher.
+ * <p/>
+ * This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+ * competition in October 2010.
+ * <p/>
+ * Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+ * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+ * <p/>
+ *
+ * @see SkeinEngine
+ * @see SkeinParameters
+ */
+public class SkeinMac
+ implements Mac
+{
+ /**
+ * 256 bit block size - Skein MAC-256
+ */
+ public static final int SKEIN_256 = SkeinEngine.SKEIN_256;
+ /**
+ * 512 bit block size - Skein MAC-512
+ */
+ public static final int SKEIN_512 = SkeinEngine.SKEIN_512;
+ /**
+ * 1024 bit block size - Skein MAC-1024
+ */
+ public static final int SKEIN_1024 = SkeinEngine.SKEIN_1024;
+
+ private SkeinEngine engine;
+
+ /**
+ * Constructs a Skein MAC with an internal state size and output size.
+ *
+ * @param stateSizeBits the internal state size in bits - one of {@link #SKEIN_256}, {@link #SKEIN_512} or
+ * {@link #SKEIN_1024}.
+ * @param digestSizeBits the output/MAC size to produce in bits, which must be an integral number of bytes.
+ */
+ public SkeinMac(int stateSizeBits, int digestSizeBits)
+ {
+ this.engine = new SkeinEngine(stateSizeBits, digestSizeBits);
+ }
+
+ public SkeinMac(SkeinMac mac)
+ {
+ this.engine = new SkeinEngine(mac.engine);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Skein-MAC-" + (engine.getBlockSize() * 8) + "-" + (engine.getOutputSize() * 8);
+ }
+
+ /**
+ * Initialises the Skein digest with the provided parameters.<br>
+ * See {@link SkeinParameters} for details on the parameterisation of the Skein hash function.
+ *
+ * @param params an instance of {@link SkeinParameters} or {@link KeyParameter}.
+ */
+ public void init(CipherParameters params)
+ throws IllegalArgumentException
+ {
+ SkeinParameters skeinParameters;
+ if (params instanceof SkeinParameters)
+ {
+ skeinParameters = (SkeinParameters)params;
+ }
+ else if (params instanceof KeyParameter)
+ {
+ skeinParameters = new SkeinParameters.Builder().setKey(((KeyParameter)params).getKey()).build();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid parameter passed to Skein MAC init - "
+ + params.getClass().getName());
+ }
+ if (skeinParameters.getKey() == null)
+ {
+ throw new IllegalArgumentException("Skein MAC requires a key parameter.");
+ }
+ engine.init(skeinParameters);
+ }
+
+ public int getMacSize()
+ {
+ return engine.getOutputSize();
+ }
+
+ public void reset()
+ {
+ engine.reset();
+ }
+
+ public void update(byte in)
+ {
+ engine.update(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ engine.update(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ return engine.doFinal(out, outOff);
+ }
+
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/macs/package.html
deleted file mode 100644
index 0b1f86d..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/macs/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for creating MACs and HMACs.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
index 9a6e2e0..fef51fd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
@@ -29,8 +29,8 @@ public class CCMBlockCipher
private int macSize;
private CipherParameters keyParam;
private byte[] macBlock;
- private ByteArrayOutputStream associatedText = new ByteArrayOutputStream();
- private ByteArrayOutputStream data = new ByteArrayOutputStream();
+ private ExposedByteArrayOutputStream associatedText = new ExposedByteArrayOutputStream();
+ private ExposedByteArrayOutputStream data = new ExposedByteArrayOutputStream();
/**
* Basic constructor.
@@ -65,6 +65,7 @@ public class CCMBlockCipher
{
this.forEncryption = forEncryption;
+ CipherParameters cipherParameters;
if (params instanceof AEADParameters)
{
AEADParameters param = (AEADParameters)params;
@@ -72,7 +73,7 @@ public class CCMBlockCipher
nonce = param.getNonce();
initialAssociatedText = param.getAssociatedText();
macSize = param.getMacSize() / 8;
- keyParam = param.getKey();
+ cipherParameters = param.getKey();
}
else if (params instanceof ParametersWithIV)
{
@@ -81,17 +82,25 @@ public class CCMBlockCipher
nonce = param.getIV();
initialAssociatedText = null;
macSize = macBlock.length / 2;
- keyParam = param.getParameters();
+ cipherParameters = param.getParameters();
}
else
{
throw new IllegalArgumentException("invalid parameters passed to CCM");
}
+ // NOTE: Very basic support for key re-use, but no performance gain from it
+ if (cipherParameters != null)
+ {
+ keyParam = cipherParameters;
+ }
+
if (nonce == null || nonce.length < 7 || nonce.length > 13)
{
throw new IllegalArgumentException("nonce must have length from 7 to 13 octets");
}
+
+ reset();
}
public String getAlgorithmName()
@@ -129,14 +138,11 @@ public class CCMBlockCipher
public int doFinal(byte[] out, int outOff)
throws IllegalStateException, InvalidCipherTextException
{
- byte[] text = data.toByteArray();
- byte[] enc = processPacket(text, 0, text.length);
-
- System.arraycopy(enc, 0, out, outOff, enc.length);
+ int len = processPacket(data.getBuffer(), 0, data.size(), out, outOff);
reset();
- return enc.length;
+ return len;
}
public void reset()
@@ -178,9 +184,55 @@ public class CCMBlockCipher
return totalData < macSize ? 0 : totalData - macSize;
}
+ /**
+ * Process a packet of data for either CCM decryption or encryption.
+ *
+ * @param in data for processing.
+ * @param inOff offset at which data starts in the input array.
+ * @param inLen length of the data in the input array.
+ * @return a byte array containing the processed input..
+ * @throws IllegalStateException if the cipher is not appropriately set up.
+ * @throws InvalidCipherTextException if the input data is truncated or the mac check fails.
+ */
public byte[] processPacket(byte[] in, int inOff, int inLen)
throws IllegalStateException, InvalidCipherTextException
{
+ byte[] output;
+
+ if (forEncryption)
+ {
+ output = new byte[inLen + macSize];
+ }
+ else
+ {
+ if (inLen < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ output = new byte[inLen - macSize];
+ }
+
+ processPacket(in, inOff, inLen, output, 0);
+
+ return output;
+ }
+
+ /**
+ * Process a packet of data for either CCM decryption or encryption.
+ *
+ * @param in data for processing.
+ * @param inOff offset at which data starts in the input array.
+ * @param inLen length of the data in the input array.
+ * @param output output array.
+ * @param outOff offset into output array to start putting processed bytes.
+ * @return the number of bytes added to output.
+ * @throws IllegalStateException if the cipher is not appropriately set up.
+ * @throws InvalidCipherTextException if the input data is truncated or the mac check fails.
+ * @throws DataLengthException if output buffer too short.
+ */
+ public int processPacket(byte[] in, int inOff, int inLen, byte[] output, int outOff)
+ throws IllegalStateException, InvalidCipherTextException, DataLengthException
+ {
// TODO: handle null keyParam (e.g. via RepeatedKeySpec)
// Need to keep the CTR and CBC Mac parts around and reset
if (keyParam == null)
@@ -206,42 +258,52 @@ public class CCMBlockCipher
BlockCipher ctrCipher = new SICBlockCipher(cipher);
ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv));
- int index = inOff;
- int outOff = 0;
- byte[] output;
+ int outputLen;
+ int inIndex = inOff;
+ int outIndex = outOff;
if (forEncryption)
{
- output = new byte[inLen + macSize];
+ outputLen = inLen + macSize;
+ if (output.length < (outputLen + outOff))
+ {
+ throw new DataLengthException("Output buffer too short.");
+ }
calculateMac(in, inOff, inLen, macBlock);
ctrCipher.processBlock(macBlock, 0, macBlock, 0); // S0
- while (index < inLen - blockSize) // S1...
+ while (inIndex < (inOff + inLen - blockSize)) // S1...
{
- ctrCipher.processBlock(in, index, output, outOff);
- outOff += blockSize;
- index += blockSize;
+ ctrCipher.processBlock(in, inIndex, output, outIndex);
+ outIndex += blockSize;
+ inIndex += blockSize;
}
byte[] block = new byte[blockSize];
- System.arraycopy(in, index, block, 0, inLen - index);
+ System.arraycopy(in, inIndex, block, 0, inLen + inOff - inIndex);
ctrCipher.processBlock(block, 0, block, 0);
- System.arraycopy(block, 0, output, outOff, inLen - index);
+ System.arraycopy(block, 0, output, outIndex, inLen + inOff - inIndex);
- outOff += inLen - index;
-
- System.arraycopy(macBlock, 0, output, outOff, output.length - outOff);
+ System.arraycopy(macBlock, 0, output, outOff + inLen, macSize);
}
else
{
- output = new byte[inLen - macSize];
+ if (inLen < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ outputLen = inLen - macSize;
+ if (output.length < (outputLen + outOff))
+ {
+ throw new DataLengthException("Output buffer too short.");
+ }
- System.arraycopy(in, inOff + inLen - macSize, macBlock, 0, macSize);
+ System.arraycopy(in, inOff + outputLen, macBlock, 0, macSize);
ctrCipher.processBlock(macBlock, 0, macBlock, 0);
@@ -250,24 +312,24 @@ public class CCMBlockCipher
macBlock[i] = 0;
}
- while (outOff < output.length - blockSize)
+ while (inIndex < (inOff + outputLen - blockSize))
{
- ctrCipher.processBlock(in, index, output, outOff);
- outOff += blockSize;
- index += blockSize;
+ ctrCipher.processBlock(in, inIndex, output, outIndex);
+ outIndex += blockSize;
+ inIndex += blockSize;
}
byte[] block = new byte[blockSize];
- System.arraycopy(in, index, block, 0, output.length - outOff);
+ System.arraycopy(in, inIndex, block, 0, outputLen - (inIndex - inOff));
ctrCipher.processBlock(block, 0, block, 0);
- System.arraycopy(block, 0, output, outOff, output.length - outOff);
+ System.arraycopy(block, 0, output, outIndex, outputLen - (inIndex - inOff));
byte[] calculatedMacBlock = new byte[blockSize];
- calculateMac(output, 0, output.length, calculatedMacBlock);
+ calculateMac(output, outOff, outputLen, calculatedMacBlock);
if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock))
{
@@ -275,7 +337,7 @@ public class CCMBlockCipher
}
}
- return output;
+ return outputLen;
}
private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
@@ -344,8 +406,7 @@ public class CCMBlockCipher
}
if (associatedText.size() > 0)
{
- byte[] tmp = associatedText.toByteArray();
- cMac.update(tmp, 0, tmp.length);
+ cMac.update(associatedText.getBuffer(), 0, associatedText.size());
}
extra = (extra + textLength) % 16;
@@ -375,4 +436,17 @@ public class CCMBlockCipher
{
return getAssociatedTextLength() > 0;
}
+
+ private class ExposedByteArrayOutputStream
+ extends ByteArrayOutputStream
+ {
+ public ExposedByteArrayOutputStream()
+ {
+ }
+
+ public byte[] getBuffer()
+ {
+ return this.buf;
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
index d0fb9bb..a885169 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
@@ -4,6 +4,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.Arrays;
/**
* implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
@@ -246,6 +247,16 @@ public class CFBBlockCipher
}
/**
+ * Return the current state of the initialisation vector.
+ *
+ * @return current IV
+ */
+ public byte[] getCurrentIV()
+ {
+ return Arrays.clone(cfbV);
+ }
+
+ /**
* reset the chaining vector back to the IV and reset the underlying
* cipher.
*/
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 b8e5b61..5388b40 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
@@ -22,8 +22,9 @@ public class CTSBlockCipher
public CTSBlockCipher(
BlockCipher cipher)
{
- if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher))
+ if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher) || (cipher instanceof SICBlockCipher))
{
+ // TODO: This is broken - need to introduce marker interface to differentiate block cipher primitive from mode?
throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
}
@@ -72,7 +73,7 @@ public class CTSBlockCipher
}
/**
- * process a single byte, producing an output block if neccessary.
+ * process a single byte, producing an output block if necessary.
*
* @param in the input byte.
* @param out the space for any output that might be produced.
@@ -200,60 +201,81 @@ public class CTSBlockCipher
if (forEncryption)
{
- cipher.processBlock(buf, 0, block, 0);
-
if (bufOff < blockSize)
{
throw new DataLengthException("need at least one block of input for CTS");
}
- for (int i = bufOff; i != buf.length; i++)
- {
- buf[i] = block[i - blockSize];
- }
-
- for (int i = blockSize; i != bufOff; i++)
- {
- buf[i] ^= block[i - blockSize];
- }
+ cipher.processBlock(buf, 0, block, 0);
- if (cipher instanceof CBCBlockCipher)
+ if (bufOff > blockSize)
{
- BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
-
- c.processBlock(buf, blockSize, out, outOff);
+ for (int i = bufOff; i != buf.length; i++)
+ {
+ buf[i] = block[i - blockSize];
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ buf[i] ^= block[i - blockSize];
+ }
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, blockSize, out, outOff);
+ }
+ else
+ {
+ cipher.processBlock(buf, blockSize, out, outOff);
+ }
+
+ System.arraycopy(block, 0, out, outOff + blockSize, len);
}
else
{
- cipher.processBlock(buf, blockSize, out, outOff);
+ System.arraycopy(block, 0, out, outOff, blockSize);
}
-
- System.arraycopy(block, 0, out, outOff + blockSize, len);
}
else
{
+ if (bufOff < blockSize)
+ {
+ throw new DataLengthException("need at least one block of input for CTS");
+ }
+
byte[] lastBlock = new byte[blockSize];
- if (cipher instanceof CBCBlockCipher)
+ if (bufOff > blockSize)
{
- BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
-
- c.processBlock(buf, 0, block, 0);
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, 0, block, 0);
+ }
+ else
+ {
+ cipher.processBlock(buf, 0, block, 0);
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ }
+
+ System.arraycopy(buf, blockSize, block, 0, len);
+
+ cipher.processBlock(block, 0, out, outOff);
+ System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
}
else
{
cipher.processBlock(buf, 0, block, 0);
- }
- for (int i = blockSize; i != bufOff; i++)
- {
- lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ System.arraycopy(block, 0, out, outOff, blockSize);
}
-
- System.arraycopy(buf, blockSize, block, 0, len);
-
- cipher.processBlock(block, 0, out, outOff);
- System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
}
int offset = bufOff;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java
index 4999caa..8f74000 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java
@@ -123,16 +123,10 @@ public class EAXBlockCipher
mac.update(nonce, 0, nonce.length);
mac.doFinal(nonceMac, 0);
- tag[blockSize - 1] = hTAG;
- mac.update(tag, 0, blockSize);
-
- if (initialAssociatedText != null)
- {
- processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
- }
-
// Same BlockCipher underlies this and the mac, so reuse last key on cipher
cipher.init(true, new ParametersWithIV(null, nonceMac));
+
+ reset();
}
private void initCipher()
@@ -206,7 +200,7 @@ public class EAXBlockCipher
{
if (cipherInitialized)
{
- throw new IllegalStateException("AAD data cannot be added after encryption/decription processing has begun.");
+ throw new IllegalStateException("AAD data cannot be added after encryption/decryption processing has begun.");
}
mac.update(in, inOff, len);
}
@@ -246,6 +240,10 @@ public class EAXBlockCipher
if (forEncryption)
{
+ if (out.length < (outOff + extra))
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
cipher.processBlock(bufBlock, 0, tmp, 0);
cipher.processBlock(bufBlock, blockSize, tmp, blockSize);
@@ -263,6 +261,10 @@ public class EAXBlockCipher
}
else
{
+ if (extra < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
if (extra > macSize)
{
mac.update(bufBlock, 0, extra - macSize);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java
new file mode 100644
index 0000000..887c169
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java
@@ -0,0 +1,109 @@
+package org.bouncycastle.crypto.modes;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.crypto.params.ParametersWithSBox;
+
+/**
+ * An implementation of the GOST CFB mode with CryptoPro key meshing as described in RFC 4357.
+ */
+public class GCFBBlockCipher
+ implements BlockCipher
+{
+ private static final byte[] C =
+ {
+ 0x69, 0x00, 0x72, 0x22, 0x64, (byte)0xC9, 0x04, 0x23,
+ (byte)0x8D, 0x3A, (byte)0xDB, (byte)0x96, 0x46, (byte)0xE9, 0x2A, (byte)0xC4,
+ 0x18, (byte)0xFE, (byte)0xAC, (byte)0x94, 0x00, (byte)0xED, 0x07, 0x12,
+ (byte)0xC0, (byte)0x86, (byte)0xDC, (byte)0xC2, (byte)0xEF, 0x4C, (byte)0xA9, 0x2B
+ };
+
+ private final CFBBlockCipher cfbEngine;
+
+ private KeyParameter key;
+ private long counter = 0;
+ private boolean forEncryption;
+
+ public GCFBBlockCipher(BlockCipher engine)
+ {
+ this.cfbEngine = new CFBBlockCipher(engine, engine.getBlockSize() * 8);
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ counter = 0;
+ cfbEngine.init(forEncryption, params);
+
+ this.forEncryption = forEncryption;
+
+ if (params instanceof ParametersWithIV)
+ {
+ params = ((ParametersWithIV)params).getParameters();
+ }
+
+ if (params instanceof ParametersWithRandom)
+ {
+ params = ((ParametersWithRandom)params).getParameters();
+ }
+
+ if (params instanceof ParametersWithSBox)
+ {
+ params = ((ParametersWithSBox)params).getParameters();
+ }
+
+ key = (KeyParameter)params;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "G" + cfbEngine.getAlgorithmName();
+ }
+
+ public int getBlockSize()
+ {
+ return cfbEngine.getBlockSize();
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (counter > 0 && counter % 1024 == 0)
+ {
+ BlockCipher base = cfbEngine.getUnderlyingCipher();
+
+ base.init(false, key);
+
+ byte[] nextKey = new byte[32];
+
+ base.processBlock(C, 0, nextKey, 0);
+ base.processBlock(C, 8, nextKey, 8);
+ base.processBlock(C, 16, nextKey, 16);
+ base.processBlock(C, 24, nextKey, 24);
+
+ key = new KeyParameter(nextKey);
+
+ byte[] iv = new byte[8];
+
+ base.init(true, key);
+
+ base.processBlock(cfbEngine.getCurrentIV(), 0, iv, 0);
+
+ cfbEngine.init(forEncryption, new ParametersWithIV(key, iv));
+ }
+
+ counter += cfbEngine.getBlockSize();
+
+ return cfbEngine.processBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ counter = 0;
+ cfbEngine.reset();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java
index 1178974..0e66cf3 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java
@@ -206,6 +206,9 @@ public class GOFBBlockCipher
*/
public void reset()
{
+ firstStep = true;
+ N3 = 0;
+ N4 = 0;
System.arraycopy(IV, 0, ofbV, 0, IV.length);
cipher.reset();
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java
index d4d2910..6dc7148 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java
@@ -13,7 +13,7 @@ import org.bouncycastle.util.Arrays;
/**
* An implementation of the "work in progress" Internet-Draft <a
- * href="http://tools.ietf.org/html/draft-irtf-cfrg-ocb-00">The OCB Authenticated-Encryption
+ * href="http://tools.ietf.org/html/draft-irtf-cfrg-ocb-03">The OCB Authenticated-Encryption
* Algorithm</a>, licensed per:
* <p/>
* <blockquote> <a href="http://www.cs.ucdavis.edu/~rogaway/ocb/license1.pdf">License for
@@ -111,7 +111,6 @@ public class OCBBlockCipher
public void init(boolean forEncryption, CipherParameters parameters)
throws IllegalArgumentException
{
-
this.forEncryption = forEncryption;
this.macBlock = null;
@@ -156,23 +155,18 @@ public class OCBBlockCipher
N = new byte[0];
}
- if (N.length > 16 || (N.length == 16 && (N[0] & 0x80) != 0))
+ if (N.length > 15)
{
- /*
- * NOTE: We don't just ignore bit 128 because it would hide from the caller the fact
- * that two nonces differing only in bit 128 are not different.
- */
- throw new IllegalArgumentException("IV must be no more than 127 bits");
+ throw new IllegalArgumentException("IV must be no more than 15 bytes");
}
/*
* KEY-DEPENDENT INITIALISATION
*/
- // if keyParam is null we're reusing the last key.
- if (keyParameter != null)
+ if (keyParameter == null)
{
- // TODO
+ // TODO If 'keyParameter' is null we're re-using the last key.
}
// hashCipher always used in forward mode
@@ -193,17 +187,10 @@ public class OCBBlockCipher
byte[] nonce = new byte[16];
System.arraycopy(N, 0, nonce, nonce.length - N.length, N.length);
- if (N.length == 16)
- {
- nonce[0] &= 0x80;
- }
- else
- {
- nonce[15 - N.length] = 1;
- }
+ nonce[0] = (byte)(macSize << 4);
+ nonce[15 - N.length] |= 1;
int bottom = nonce[15] & 0x3F;
- // System.out.println("bottom: " + bottom);
byte[] Ktop = new byte[16];
nonce[15] &= 0xC0;
@@ -314,7 +301,6 @@ public class OCBBlockCipher
public int processBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
throws DataLengthException
{
-
int resultLen = 0;
for (int i = 0; i < len; ++i)
@@ -334,7 +320,6 @@ public class OCBBlockCipher
throws IllegalStateException,
InvalidCipherTextException
{
-
/*
* For decryption, get the tag from the end of the message
*/
@@ -483,7 +468,6 @@ public class OCBBlockCipher
protected void reset(boolean clearMac)
{
-
hashCipher.reset();
mainCipher.reset();
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java
new file mode 100644
index 0000000..b34432a
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java
@@ -0,0 +1,269 @@
+package org.bouncycastle.crypto.modes;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
+ * be used to produce cipher text which is the same length as the plain text.
+ * <p>
+ * This version applies the CTS algorithm from one block up, rather than following the errata update issued in 2004, where CTS mode is applied
+ * from greater than 1 block up and the first block is processed using CBC mode.
+ * </p>
+ */
+public class OldCTSBlockCipher
+ extends BufferedBlockCipher
+{
+ private int blockSize;
+
+ /**
+ * Create a buffered block cipher that uses Cipher Text Stealing
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public OldCTSBlockCipher(
+ BlockCipher cipher)
+ {
+ if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher))
+ {
+ throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
+ }
+
+ this.cipher = cipher;
+
+ blockSize = cipher.getBlockSize();
+
+ buf = new byte[blockSize * 2];
+ bufOff = 0;
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ return total - buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * return the size of the output buffer required for an update plus a
+ * doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(
+ int len)
+ {
+ return len + bufOff;
+ }
+
+ /**
+ * process a single byte, producing an output block if necessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception org.bouncycastle.crypto.DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ int resultLen = 0;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ bufOff = blockSize;
+ }
+
+ buf[bufOff++] = in;
+
+ return resultLen;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception org.bouncycastle.crypto.DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = getBlockSize();
+ int length = getUpdateOutputSize(len);
+
+ if (length > 0)
+ {
+ if ((outOff + length) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ bufOff = blockSize;
+
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, blockSize);
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @return the number of output bytes copied to out.
+ * @exception org.bouncycastle.crypto.DataLengthException if there is insufficient space in out for
+ * the output.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception org.bouncycastle.crypto.InvalidCipherTextException if cipher text decrypts wrongly (in
+ * case the exception will never get thrown).
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ if (bufOff + outOff > out.length)
+ {
+ throw new DataLengthException("output buffer to small in doFinal");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int len = bufOff - blockSize;
+ byte[] block = new byte[blockSize];
+
+ if (forEncryption)
+ {
+ cipher.processBlock(buf, 0, block, 0);
+
+ if (bufOff < blockSize)
+ {
+ throw new DataLengthException("need at least one block of input for CTS");
+ }
+
+ for (int i = bufOff; i != buf.length; i++)
+ {
+ buf[i] = block[i - blockSize];
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ buf[i] ^= block[i - blockSize];
+ }
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, blockSize, out, outOff);
+ }
+ else
+ {
+ cipher.processBlock(buf, blockSize, out, outOff);
+ }
+
+ System.arraycopy(block, 0, out, outOff + blockSize, len);
+ }
+ else
+ {
+ byte[] lastBlock = new byte[blockSize];
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, 0, block, 0);
+ }
+ else
+ {
+ cipher.processBlock(buf, 0, block, 0);
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ }
+
+ System.arraycopy(buf, blockSize, block, 0, len);
+
+ cipher.processBlock(block, 0, out, outOff);
+ System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
+ }
+
+ int offset = bufOff;
+
+ reset();
+
+ return offset;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
index 18e612b..4dee63a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
@@ -220,13 +220,13 @@ public class PGPCFBBlockCipher
throw new DataLengthException("input buffer too short");
}
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
if (count == 0)
{
+ if ((outOff + 2 * blockSize + 2) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
@@ -258,6 +258,11 @@ public class PGPCFBBlockCipher
}
else if (count >= blockSize + 2)
{
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
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
index f2be2fc..fc25810 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
@@ -4,21 +4,21 @@ import org.bouncycastle.util.Arrays;
public class BasicGCMExponentiator implements GCMExponentiator
{
- private byte[] x;
+ private int[] x;
public void init(byte[] x)
{
- this.x = Arrays.clone(x);
+ this.x = GCMUtil.asInts(x);
}
public void exponentiateX(long pow, byte[] output)
{
// Initial value is little-endian 1
- byte[] y = GCMUtil.oneAsBytes();
+ int[] y = GCMUtil.oneAsInts();
if (pow > 0)
{
- byte[] powX = Arrays.clone(x);
+ int[] powX = Arrays.clone(x);
do
{
if ((pow & 1L) != 0)
@@ -31,6 +31,6 @@ public class BasicGCMExponentiator implements GCMExponentiator
while (pow > 0);
}
- System.arraycopy(y, 0, output, 0, 16);
+ 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 4875301..3031a44 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
@@ -5,6 +5,32 @@ import org.bouncycastle.util.Arrays;
abstract class GCMUtil
{
+ private static final int E1 = 0xe1000000;
+ private static final byte E1B = (byte)0xe1;
+ private static final long E1L = (E1 & 0xFFFFFFFFL) << 24;
+
+ 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();
+
static byte[] oneAsBytes()
{
byte[] tmp = new byte[16];
@@ -15,78 +41,155 @@ abstract class GCMUtil
static int[] oneAsInts()
{
int[] tmp = new int[4];
- tmp[0] = 0x80000000;
+ tmp[0] = 1 << 31;
+ return tmp;
+ }
+
+ static long[] oneAsLongs()
+ {
+ long[] tmp = new long[2];
+ tmp[0] = 1L << 63;
return tmp;
}
- static byte[] asBytes(int[] ns)
+ static byte[] asBytes(int[] x)
+ {
+ byte[] z = new byte[16];
+ Pack.intToBigEndian(x, z, 0);
+ return z;
+ }
+
+ static void asBytes(int[] x, byte[] z)
+ {
+ Pack.intToBigEndian(x, z, 0);
+ }
+
+ static byte[] asBytes(long[] x)
+ {
+ byte[] z = new byte[16];
+ Pack.longToBigEndian(x, z, 0);
+ return z;
+ }
+
+ static void asBytes(long[] x, byte[] z)
+ {
+ Pack.longToBigEndian(x, z, 0);
+ }
+
+ static int[] asInts(byte[] x)
+ {
+ int[] z = new int[4];
+ Pack.bigEndianToInt(x, 0, z);
+ return z;
+ }
+
+ static void asInts(byte[] x, int[] z)
{
- byte[] output = new byte[16];
- Pack.intToBigEndian(ns, output, 0);
- return output;
+ Pack.bigEndianToInt(x, 0, z);
}
- static int[] asInts(byte[] bs)
+ static long[] asLongs(byte[] x)
{
- int[] output = new int[4];
- Pack.bigEndianToInt(bs, 0, output);
- return output;
+ long[] z = new long[2];
+ Pack.bigEndianToLong(x, 0, z);
+ return z;
}
- static void asInts(byte[] bs, int[] output)
+ static void asLongs(byte[] x, long[] z)
{
- Pack.bigEndianToInt(bs, 0, output);
+ Pack.bigEndianToLong(x, 0, z);
}
- static void multiply(byte[] block, byte[] val)
+ static void multiply(byte[] x, byte[] y)
{
- byte[] tmp = Arrays.clone(block);
- byte[] c = new byte[16];
+ byte[] r0 = Arrays.clone(x);
+ byte[] r1 = new byte[16];
for (int i = 0; i < 16; ++i)
{
- byte bits = val[i];
+ byte bits = y[i];
for (int j = 7; j >= 0; --j)
{
if ((bits & (1 << j)) != 0)
{
- xor(c, tmp);
+ xor(r1, r0);
}
- boolean lsb = (tmp[15] & 1) != 0;
- shiftRight(tmp);
- if (lsb)
+ if (shiftRight(r0) != 0)
{
- // R = new byte[]{ 0xe1, ... };
-// GCMUtil.xor(v, R);
- tmp[0] ^= (byte)0xe1;
+ r0[0] ^= E1B;
}
}
}
- System.arraycopy(c, 0, block, 0, 16);
+ System.arraycopy(r1, 0, x, 0, 16);
+ }
+
+ static void multiply(int[] x, int[] y)
+ {
+ int[] r0 = Arrays.clone(x);
+ int[] r1 = new int[4];
+
+ for (int i = 0; i < 4; ++i)
+ {
+ int bits = y[i];
+ for (int j = 31; j >= 0; --j)
+ {
+ if ((bits & (1 << j)) != 0)
+ {
+ xor(r1, r0);
+ }
+
+ if (shiftRight(r0) != 0)
+ {
+ r0[0] ^= E1;
+ }
+ }
+ }
+
+ System.arraycopy(r1, 0, x, 0, 4);
+ }
+
+ static void multiply(long[] x, long[] y)
+ {
+ long[] r0 = new long[]{ x[0], x[1] };
+ long[] r1 = new long[2];
+
+ for (int i = 0; i < 2; ++i)
+ {
+ long bits = y[i];
+ for (int j = 63; j >= 0; --j)
+ {
+ if ((bits & (1L << j)) != 0)
+ {
+ xor(r1, r0);
+ }
+
+ if (shiftRight(r0) != 0)
+ {
+ r0[0] ^= E1L;
+ }
+ }
+ }
+
+ x[0] = r1[0];
+ x[1] = r1[1];
}
// P is the value with only bit i=1 set
static void multiplyP(int[] x)
{
- boolean lsb = (x[3] & 1) != 0;
- shiftRight(x);
- if (lsb)
+ if (shiftRight(x) != 0)
{
- // R = new int[]{ 0xe1000000, 0, 0, 0 };
-// xor(v, R);
- x[0] ^= 0xe1000000;
+ x[0] ^= E1;
}
}
- static void multiplyP(int[] x, int[] output)
+ static void multiplyP(int[] x, int[] y)
{
- boolean lsb = (x[3] & 1) != 0;
- shiftRight(x, output);
- if (lsb)
+ if (shiftRight(x, y) != 0)
{
- output[0] ^= 0xe1000000;
+ y[0] ^= E1;
}
}
@@ -98,163 +201,257 @@ abstract class GCMUtil
// multiplyP(x);
// }
- int lsw = x[3];
- shiftRightN(x, 8);
- for (int i = 7; i >= 0; --i)
- {
- if ((lsw & (1 << i)) != 0)
- {
- x[0] ^= (0xe1000000 >>> (7 - i));
- }
- }
+ int c = shiftRightN(x, 8);
+ x[0] ^= LOOKUP[c >>> 24];
}
- static void multiplyP8(int[] x, int[] output)
+ static void multiplyP8(int[] x, int[] y)
{
- int lsw = x[3];
- shiftRightN(x, 8, output);
- for (int i = 7; i >= 0; --i)
- {
- if ((lsw & (1 << i)) != 0)
- {
- output[0] ^= (0xe1000000 >>> (7 - i));
- }
- }
+ int c = shiftRightN(x, 8, y);
+ y[0] ^= LOOKUP[c >>> 24];
}
- static void shiftRight(byte[] block)
+ static byte shiftRight(byte[] x)
{
- int i = 0;
- int bit = 0;
- for (;;)
+// int c = 0;
+// for (int i = 0; i < 16; ++i)
+// {
+// int b = x[i] & 0xff;
+// x[i] = (byte)((b >>> 1) | c);
+// c = (b & 1) << 7;
+// }
+// return (byte)c;
+
+ int i = 0, c = 0;
+ do
{
- int b = block[i] & 0xff;
- block[i] = (byte) ((b >>> 1) | bit);
- if (++i == 16)
- {
- break;
- }
- bit = (b & 1) << 7;
+ int b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
}
+ while (i < 16);
+ return (byte)c;
}
- static void shiftRight(byte[] block, byte[] output)
+ static byte shiftRight(byte[] x, byte[] z)
{
- int i = 0;
- int bit = 0;
- for (;;)
+// int c = 0;
+// for (int i = 0; i < 16; ++i)
+// {
+// int b = x[i] & 0xff;
+// z[i] = (byte) ((b >>> 1) | c);
+// c = (b & 1) << 7;
+// }
+// return (byte) c;
+
+ int i = 0, c = 0;
+ do
{
- int b = block[i] & 0xff;
- output[i] = (byte) ((b >>> 1) | bit);
- if (++i == 16)
- {
- break;
- }
- bit = (b & 1) << 7;
+ int b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
}
+ while (i < 16);
+ return (byte)c;
}
- static void shiftRight(int[] block)
+ static int shiftRight(int[] x)
{
- int i = 0;
- int bit = 0;
- for (;;)
- {
- int b = block[i];
- block[i] = (b >>> 1) | bit;
- if (++i == 4)
- {
- break;
- }
- bit = b << 31;
- }
+// 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 void shiftRight(int[] block, int[] output)
+ static int shiftRight(int[] x, int[] z)
{
- int i = 0;
- int bit = 0;
- for (;;)
- {
- int b = block[i];
- output[i] = (b >>> 1) | bit;
- if (++i == 4)
- {
- break;
- }
- bit = b << 31;
- }
+// 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 void shiftRightN(int[] block, int n)
+ static long shiftRight(long[] x)
{
- int i = 0;
- int bits = 0;
- for (;;)
- {
- int b = block[i];
- block[i] = (b >>> n) | bits;
- if (++i == 4)
- {
- break;
- }
- bits = b << (32 - n);
- }
+ 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 void shiftRightN(int[] block, int n, int[] output)
+ 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;
+ }
+
+ static void xor(byte[] x, byte[] y)
{
int i = 0;
- int bits = 0;
- for (;;)
+ do
{
- int b = block[i];
- output[i] = (b >>> n) | bits;
- if (++i == 4)
- {
- break;
- }
- bits = b << (32 - n);
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
}
+ while (i < 16);
}
- static void xor(byte[] block, byte[] val)
+ static void xor(byte[] x, byte[] y, int yOff, int yLen)
{
- for (int i = 15; i >= 0; --i)
+ while (yLen-- > 0)
{
- block[i] ^= val[i];
+ x[yLen] ^= y[yOff + yLen];
}
}
- static void xor(byte[] block, byte[] val, int off, int len)
+ static void xor(byte[] x, byte[] y, byte[] z)
{
- while (len-- > 0)
+ int i = 0;
+ do
{
- block[len] ^= val[off + len];
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
}
+ while (i < 16);
}
- static void xor(byte[] block, byte[] val, byte[] output)
+ static void xor(int[] x, int[] y)
{
- for (int i = 15; i >= 0; --i)
- {
- output[i] = (byte)(block[i] ^ val[i]);
- }
+ x[0] ^= y[0];
+ x[1] ^= y[1];
+ x[2] ^= y[2];
+ x[3] ^= y[3];
}
- static void xor(int[] block, int[] val)
+ static void xor(int[] x, int[] y, int[] z)
{
- for (int i = 3; i >= 0; --i)
- {
- block[i] ^= val[i];
- }
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ z[3] = x[3] ^ y[3];
}
- static void xor(int[] block, int[] val, int[] output)
+ static void xor(long[] x, long[] y)
{
- for (int i = 3; i >= 0; --i)
- {
- output[i] = block[i] ^ val[i];
- }
+ x[0] ^= y[0];
+ x[1] ^= y[1];
+ }
+
+ static void xor(long[] x, long[] y, long[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
}
}
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 a051208..6eff4e3 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
@@ -12,31 +12,32 @@ public class Tables1kGCMExponentiator implements GCMExponentiator
public void init(byte[] x)
{
- if (lookupPowX2 != null && Arrays.areEqual(x, (byte[])lookupPowX2.elementAt(0)))
+ int[] y = GCMUtil.asInts(x);
+ if (lookupPowX2 != null && Arrays.areEqual(y, (int[])lookupPowX2.elementAt(0)))
{
return;
}
lookupPowX2 = new Vector(8);
- lookupPowX2.addElement(Arrays.clone(x));
+ lookupPowX2.addElement(y);
}
public void exponentiateX(long pow, byte[] output)
{
- byte[] y = GCMUtil.oneAsBytes();
+ int[] y = GCMUtil.oneAsInts();
int bit = 0;
while (pow > 0)
{
if ((pow & 1L) != 0)
{
ensureAvailable(bit);
- GCMUtil.multiply(y, (byte[])lookupPowX2.elementAt(bit));
+ GCMUtil.multiply(y, (int[])lookupPowX2.elementAt(bit));
}
++bit;
pow >>>= 1;
}
- System.arraycopy(y, 0, output, 0, 16);
+ GCMUtil.asBytes(y, output);
}
private void ensureAvailable(int bit)
@@ -44,7 +45,7 @@ public class Tables1kGCMExponentiator implements GCMExponentiator
int count = lookupPowX2.size();
if (count <= bit)
{
- byte[] tmp = (byte[])lookupPowX2.elementAt(count - 1);
+ int[] tmp = (int[])lookupPowX2.elementAt(count - 1);
do
{
tmp = Arrays.clone(tmp);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/modes/package.html
deleted file mode 100644
index 5402df4..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Modes for symmetric ciphers.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/package.html
deleted file mode 100644
index ee5487f..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Base classes for the lightweight API.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/package.html
deleted file mode 100644
index 2b82e60..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Paddings for symmetric ciphers.
-</body>
-</html>
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 05a1327..9cc6e72 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java
@@ -41,7 +41,7 @@ public class ECDomainParameters
byte[] seed)
{
this.curve = curve;
- this.G = G;
+ this.G = G.normalize();
this.n = n;
this.h = h;
this.seed = seed;
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 5fbea19..b6b3fb6 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
@@ -12,7 +12,7 @@ public class ECPublicKeyParameters
ECDomainParameters params)
{
super(false, params);
- this.Q = Q;
+ this.Q = Q.normalize();
}
public ECPoint getQ()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFCounterParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFCounterParameters.java
new file mode 100644
index 0000000..0eb6cb7
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFCounterParameters.java
@@ -0,0 +1,52 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.crypto.DerivationParameters;
+import org.bouncycastle.util.Arrays;
+
+public final class KDFCounterParameters
+ implements DerivationParameters
+{
+
+ private final byte[] ki;
+ private final byte[] fixedInputData;
+ private final int r;
+
+ public KDFCounterParameters(byte[] ki, byte[] fixedInputData, int r)
+ {
+ if (ki == null)
+ {
+ throw new IllegalArgumentException("A KDF requires Ki (a seed) as input");
+ }
+ this.ki = Arrays.clone(ki);
+
+ if (fixedInputData == null)
+ {
+ this.fixedInputData = new byte[0];
+ }
+ else
+ {
+ this.fixedInputData = Arrays.clone(fixedInputData);
+ }
+
+ if (r != 8 && r != 16 && r != 24 && r != 32)
+ {
+ throw new IllegalArgumentException("Length of counter should be 8, 16, 24 or 32");
+ }
+ this.r = r;
+ }
+
+ public byte[] getKI()
+ {
+ return ki;
+ }
+
+ public byte[] getFixedInputData()
+ {
+ return Arrays.clone(fixedInputData);
+ }
+
+ public int getR()
+ {
+ return r;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFDoublePipelineIterationParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFDoublePipelineIterationParameters.java
new file mode 100644
index 0000000..383678a
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFDoublePipelineIterationParameters.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.crypto.DerivationParameters;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Note that counter is only supported at the location presented in the
+ * NIST SP 800-108 specification, not in the additional locations present
+ * in the CAVP test vectors.
+ */
+public final class KDFDoublePipelineIterationParameters
+ implements DerivationParameters
+{
+
+ // could be any valid value, using 32, don't know why
+ private static final int UNUSED_R = 32;
+
+ private final byte[] ki;
+ private final boolean useCounter;
+ private final int r;
+ private final byte[] fixedInputData;
+
+ private KDFDoublePipelineIterationParameters(byte[] ki, byte[] fixedInputData, int r, boolean useCounter)
+ {
+ if (ki == null)
+ {
+ throw new IllegalArgumentException("A KDF requires Ki (a seed) as input");
+ }
+ this.ki = Arrays.clone(ki);
+
+ if (fixedInputData == null)
+ {
+ this.fixedInputData = new byte[0];
+ }
+ else
+ {
+ this.fixedInputData = Arrays.clone(fixedInputData);
+ }
+
+ if (r != 8 && r != 16 && r != 24 && r != 32)
+ {
+ throw new IllegalArgumentException("Length of counter should be 8, 16, 24 or 32");
+ }
+ this.r = r;
+
+ this.useCounter = useCounter;
+ }
+
+ public static KDFDoublePipelineIterationParameters createWithCounter(
+ byte[] ki, byte[] fixedInputData, int r)
+ {
+ return new KDFDoublePipelineIterationParameters(ki, fixedInputData, r, true);
+ }
+
+ public static KDFDoublePipelineIterationParameters createWithoutCounter(
+ byte[] ki, byte[] fixedInputData)
+ {
+ return new KDFDoublePipelineIterationParameters(ki, fixedInputData, UNUSED_R, false);
+ }
+
+ public byte[] getKI()
+ {
+ return ki;
+ }
+
+ public boolean useCounter()
+ {
+ return useCounter;
+ }
+
+ public int getR()
+ {
+ return r;
+ }
+
+ public byte[] getFixedInputData()
+ {
+ return Arrays.clone(fixedInputData);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFFeedbackParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFFeedbackParameters.java
new file mode 100644
index 0000000..8a6e7f5
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/KDFFeedbackParameters.java
@@ -0,0 +1,96 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.crypto.DerivationParameters;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Note that counter is only supported at the location presented in the
+ * NIST SP 800-108 specification, not in the additional locations present
+ * in the CAVP test vectors.
+ */
+public final class KDFFeedbackParameters
+ implements DerivationParameters
+{
+
+ // could be any valid value, using 32, don't know why
+ private static final int UNUSED_R = -1;
+
+ private final byte[] ki;
+ private final byte[] iv;
+ private final boolean useCounter;
+ private final int r;
+ private final byte[] fixedInputData;
+
+ private KDFFeedbackParameters(byte[] ki, byte[] iv, byte[] fixedInputData, int r, boolean useCounter)
+ {
+ if (ki == null)
+ {
+ throw new IllegalArgumentException("A KDF requires Ki (a seed) as input");
+ }
+ this.ki = Arrays.clone(ki);
+
+ if (fixedInputData == null)
+ {
+ this.fixedInputData = new byte[0];
+ }
+ else
+ {
+ this.fixedInputData = Arrays.clone(fixedInputData);
+ }
+
+ this.r = r;
+
+ if (iv == null)
+ {
+ this.iv = new byte[0];
+ }
+ else
+ {
+ this.iv = Arrays.clone(iv);
+ }
+
+ this.useCounter = useCounter;
+ }
+
+ public static KDFFeedbackParameters createWithCounter(
+ byte[] ki, final byte[] iv, byte[] fixedInputData, int r)
+ {
+ if (r != 8 && r != 16 && r != 24 && r != 32)
+ {
+ throw new IllegalArgumentException("Length of counter should be 8, 16, 24 or 32");
+ }
+
+ return new KDFFeedbackParameters(ki, iv, fixedInputData, r, true);
+ }
+
+ public static KDFFeedbackParameters createWithoutCounter(
+ byte[] ki, final byte[] iv, byte[] fixedInputData)
+ {
+ return new KDFFeedbackParameters(ki, iv, fixedInputData, UNUSED_R, false);
+ }
+
+ public byte[] getKI()
+ {
+ return ki;
+ }
+
+ public byte[] getIV()
+ {
+ return iv;
+ }
+
+ public boolean useCounter()
+ {
+ return useCounter;
+ }
+
+ public int getR()
+ {
+ return r;
+ }
+
+ public byte[] getFixedInputData()
+ {
+ return Arrays.clone(fixedInputData);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/SkeinParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/SkeinParameters.java
new file mode 100644
index 0000000..76241ee
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/SkeinParameters.java
@@ -0,0 +1,293 @@
+package org.bouncycastle.crypto.params;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.digests.SkeinDigest;
+import org.bouncycastle.crypto.digests.SkeinEngine;
+import org.bouncycastle.crypto.macs.SkeinMac;
+import org.bouncycastle.util.Integers;
+
+/**
+ * Parameters for the Skein hash function - a series of byte[] strings identified by integer tags.
+ * <p/>
+ * Parameterised Skein can be used for:
+ * <ul>
+ * <li>MAC generation, by providing a {@link SkeinParameters.Builder#setKey(byte[]) key}.</li>
+ * <li>Randomised hashing, by providing a {@link SkeinParameters.Builder#setNonce(byte[]) nonce}.</li>
+ * <li>A hash function for digital signatures, associating a
+ * {@link SkeinParameters.Builder#setPublicKey(byte[]) public key} with the message digest.</li>
+ * <li>A key derivation function, by providing a
+ * {@link SkeinParameters.Builder#setKeyIdentifier(byte[]) key identifier}.</li>
+ * <li>Personalised hashing, by providing a
+ * {@link SkeinParameters.Builder#setPersonalisation(Date, String, String) recommended format} or
+ * {@link SkeinParameters.Builder#setPersonalisation(byte[]) arbitrary} personalisation string.</li>
+ * </ul>
+ *
+ * @see SkeinEngine
+ * @see SkeinDigest
+ * @see SkeinMac
+ */
+public class SkeinParameters
+ implements CipherParameters
+{
+ /**
+ * The parameter type for a secret key, supporting MAC or KDF functions: {@value
+ * #PARAM_TYPE_KEY}.
+ */
+ public static final int PARAM_TYPE_KEY = 0;
+
+ /**
+ * The parameter type for the Skein configuration block: {@value #PARAM_TYPE_CONFIG}.
+ */
+ public static final int PARAM_TYPE_CONFIG = 4;
+
+ /**
+ * The parameter type for a personalisation string: {@value #PARAM_TYPE_PERSONALISATION}.
+ */
+ public static final int PARAM_TYPE_PERSONALISATION = 8;
+
+ /**
+ * The parameter type for a public key: {@value #PARAM_TYPE_PUBLIC_KEY}.
+ */
+ public static final int PARAM_TYPE_PUBLIC_KEY = 12;
+
+ /**
+ * The parameter type for a key identifier string: {@value #PARAM_TYPE_KEY_IDENTIFIER}.
+ */
+ public static final int PARAM_TYPE_KEY_IDENTIFIER = 16;
+
+ /**
+ * The parameter type for a nonce: {@value #PARAM_TYPE_NONCE}.
+ */
+ public static final int PARAM_TYPE_NONCE = 20;
+
+ /**
+ * The parameter type for the message: {@value #PARAM_TYPE_MESSAGE}.
+ */
+ public static final int PARAM_TYPE_MESSAGE = 48;
+
+ /**
+ * The parameter type for the output transformation: {@value #PARAM_TYPE_OUTPUT}.
+ */
+ public static final int PARAM_TYPE_OUTPUT = 63;
+
+ private Hashtable parameters;
+
+ public SkeinParameters()
+ {
+ this(new Hashtable());
+ }
+
+ private SkeinParameters(final Hashtable parameters)
+ {
+ this.parameters = parameters;
+ }
+
+ /**
+ * Obtains a map of type (Integer) to value (byte[]) for the parameters tracked in this object.
+ */
+ public Hashtable getParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_KEY key parameter}, or <code>null</code> if not
+ * set.
+ */
+ public byte[] getKey()
+ {
+ return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_KEY));
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_PERSONALISATION personalisation parameter}, or
+ * <code>null</code> if not set.
+ */
+ public byte[] getPersonalisation()
+ {
+ return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_PERSONALISATION));
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_PUBLIC_KEY public key parameter}, or
+ * <code>null</code> if not set.
+ */
+ public byte[] getPublicKey()
+ {
+ return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_PUBLIC_KEY));
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_KEY_IDENTIFIER key identifier parameter}, or
+ * <code>null</code> if not set.
+ */
+ public byte[] getKeyIdentifier()
+ {
+ return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_KEY_IDENTIFIER));
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_NONCE nonce parameter}, or <code>null</code> if
+ * not set.
+ */
+ public byte[] getNonce()
+ {
+ return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_NONCE));
+ }
+
+ /**
+ * A builder for {@link SkeinParameters}.
+ */
+ public static class Builder
+ {
+ private Hashtable parameters = new Hashtable();
+
+ public Builder()
+ {
+ }
+
+ public Builder(Hashtable paramsMap)
+ {
+ Enumeration keys = paramsMap.keys();
+ while (keys.hasMoreElements())
+ {
+ Integer key = (Integer)keys.nextElement();
+ parameters.put(key, paramsMap.get(key));
+ }
+ }
+
+ public Builder(SkeinParameters params)
+ {
+ Enumeration keys = params.parameters.keys();
+ while (keys.hasMoreElements())
+ {
+ Integer key = (Integer)keys.nextElement();
+ parameters.put(key, params.parameters.get(key));
+ }
+ }
+
+ /**
+ * Sets a parameters to apply to the Skein hash function.<br>
+ * Parameter types must be in the range 0,5..62, and cannot use the value {@value
+ * SkeinParameters#PARAM_TYPE_MESSAGE} (reserved for message body).
+ * <p/>
+ * Parameters with type < {@value SkeinParameters#PARAM_TYPE_MESSAGE} are processed before
+ * the message content, parameters with type > {@value SkeinParameters#PARAM_TYPE_MESSAGE}
+ * are processed after the message and prior to output.
+ *
+ * @param type the type of the parameter, in the range 5..62.
+ * @param value the byte sequence of the parameter.
+ * @return
+ */
+ public Builder set(int type, byte[] value)
+ {
+ if (value == null)
+ {
+ throw new IllegalArgumentException("Parameter value must not be null.");
+ }
+ if ((type != PARAM_TYPE_KEY)
+ && (type <= PARAM_TYPE_CONFIG || type >= PARAM_TYPE_OUTPUT || type == PARAM_TYPE_MESSAGE))
+ {
+ throw new IllegalArgumentException("Parameter types must be in the range 0,5..47,49..62.");
+ }
+ if (type == PARAM_TYPE_CONFIG)
+ {
+ throw new IllegalArgumentException("Parameter type " + PARAM_TYPE_CONFIG
+ + " is reserved for internal use.");
+ }
+ this.parameters.put(Integers.valueOf(type), value);
+ return this;
+ }
+
+ /**
+ * Sets the {@link SkeinParameters#PARAM_TYPE_KEY} parameter.
+ */
+ public Builder setKey(byte[] key)
+ {
+ return set(PARAM_TYPE_KEY, key);
+ }
+
+ /**
+ * Sets the {@link SkeinParameters#PARAM_TYPE_PERSONALISATION} parameter.
+ */
+ public Builder setPersonalisation(byte[] personalisation)
+ {
+ return set(PARAM_TYPE_PERSONALISATION, personalisation);
+ }
+
+ /**
+ * Implements the recommended personalisation format for Skein defined in Section 4.11 of
+ * the Skein 1.3 specification.
+ * <p/>
+ * The format is <code>YYYYMMDD email@address distinguisher</code>, encoded to a byte
+ * sequence using UTF-8 encoding.
+ *
+ * @param date the date the personalised application of the Skein was defined.
+ * @param emailAddress the email address of the creation of the personalised application.
+ * @param distinguisher an arbitrary personalisation string distinguishing the application.
+ * @return
+ */
+ public Builder setPersonalisation(Date date, String emailAddress, String distinguisher)
+ {
+ try
+ {
+ final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ final OutputStreamWriter out = new OutputStreamWriter(bout, "UTF-8");
+ final DateFormat format = new SimpleDateFormat("YYYYMMDD");
+ out.write(format.format(date));
+ out.write(" ");
+ out.write(emailAddress);
+ out.write(" ");
+ out.write(distinguisher);
+ out.close();
+ return set(PARAM_TYPE_PERSONALISATION, bout.toByteArray());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("Byte I/O failed: " + e);
+ }
+ }
+
+ /**
+ * Sets the {@link SkeinParameters#PARAM_TYPE_KEY_IDENTIFIER} parameter.
+ */
+ public Builder setPublicKey(byte[] publicKey)
+ {
+ return set(PARAM_TYPE_PUBLIC_KEY, publicKey);
+ }
+
+ /**
+ * Sets the {@link SkeinParameters#PARAM_TYPE_KEY_IDENTIFIER} parameter.
+ */
+ public Builder setKeyIdentifier(byte[] keyIdentifier)
+ {
+ return set(PARAM_TYPE_KEY_IDENTIFIER, keyIdentifier);
+ }
+
+ /**
+ * Sets the {@link SkeinParameters#PARAM_TYPE_NONCE} parameter.
+ */
+ public Builder setNonce(byte[] nonce)
+ {
+ return set(PARAM_TYPE_NONCE, nonce);
+ }
+
+ /**
+ * Constructs a new {@link SkeinParameters} instance with the parameters provided to this
+ * builder.
+ */
+ public SkeinParameters build()
+ {
+ return new SkeinParameters(parameters);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java
new file mode 100644
index 0000000..fa16fac
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java
@@ -0,0 +1,40 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Parameters for tweakable block ciphers.
+ */
+public class TweakableBlockCipherParameters
+ implements CipherParameters
+{
+ private final byte[] tweak;
+ private final KeyParameter key;
+
+ public TweakableBlockCipherParameters(final KeyParameter key, final byte[] tweak)
+ {
+ this.key = key;
+ this.tweak = Arrays.clone(tweak);
+ }
+
+ /**
+ * Gets the key.
+ *
+ * @return the key to use, or <code>null</code> to use the current key.
+ */
+ public KeyParameter getKey()
+ {
+ return key;
+ }
+
+ /**
+ * Gets the tweak value.
+ *
+ * @return the tweak to use, or <code>null</code> to use the current tweak.
+ */
+ public byte[] getTweak()
+ {
+ return tweak;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/params/package.html
deleted file mode 100644
index 4e00a75..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for parameter objects for ciphers and generators.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java b/bcprov/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java
index 209b5e2..3245eab 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java
@@ -4,6 +4,9 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
+/**
+ * A secure random that returns pre-seeded data to calls of nextBytes() or generateSeed().
+ */
public class FixedSecureRandom
extends SecureRandom
{
@@ -70,7 +73,16 @@ public class FixedSecureRandom
_index += bytes.length;
}
-
+
+ public byte[] generateSeed(int numBytes)
+ {
+ byte[] bytes = new byte[numBytes];
+
+ this.nextBytes(bytes);
+
+ return bytes;
+ }
+
//
// classpath's implementation of SecureRandom doesn't currently go back to nextBytes
// when next is called. We can't override next as it's a final method.
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java b/bcprov/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java
index 66f05c5..59ea101 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java
@@ -6,6 +6,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.prng.drbg.CTRSP800DRBG;
+import org.bouncycastle.crypto.prng.drbg.DualECPoints;
import org.bouncycastle.crypto.prng.drbg.DualECSP800DRBG;
import org.bouncycastle.crypto.prng.drbg.HMacSP800DRBG;
import org.bouncycastle.crypto.prng.drbg.HashSP800DRBG;
@@ -144,7 +145,7 @@ public class SP800SecureRandomBuilder
}
/**
- * Build a SecureRandom based on a SP 800-90A Dual EC DRBG.
+ * Build a SecureRandom based on a SP 800-90A Dual EC DRBG using the NIST point set.
*
* @param digest digest algorithm to use in the DRBG underneath the SecureRandom.
* @param nonce nonce value to use in DRBG construction.
@@ -156,6 +157,21 @@ public class SP800SecureRandomBuilder
return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new DualECDRBGProvider(digest, nonce, personalizationString, securityStrength), predictionResistant);
}
+ /**
+ * Build a SecureRandom based on a SP 800-90A Dual EC DRBG according to a defined point set.
+ *
+ * @param pointSet an array of DualECPoints to use for DRB generation.
+ * @param digest digest algorithm to use in the DRBG underneath the SecureRandom.
+ * @param nonce nonce value to use in DRBG construction.
+ * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes.
+ * @return a SecureRandom supported by a Dual EC DRBG.
+ */
+ public SP800SecureRandom buildDualEC(DualECPoints[] pointSet, Digest digest, byte[] nonce, boolean predictionResistant)
+ {
+ return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new ConfigurableDualECDRBGProvider(pointSet, digest, nonce, personalizationString, securityStrength), predictionResistant);
+ }
+
+
private static class HashDRBGProvider
implements DRBGProvider
{
@@ -200,6 +216,31 @@ public class SP800SecureRandomBuilder
}
}
+ private static class ConfigurableDualECDRBGProvider
+ implements DRBGProvider
+ {
+ private final DualECPoints[] pointSet;
+ private final Digest digest;
+ private final byte[] nonce;
+ private final byte[] personalizationString;
+ private final int securityStrength;
+
+ public ConfigurableDualECDRBGProvider(DualECPoints[] pointSet, Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength)
+ {
+ this.pointSet = new DualECPoints[pointSet.length];
+ System.arraycopy(pointSet, 0, this.pointSet, 0, pointSet.length);
+ this.digest = digest;
+ this.nonce = nonce;
+ this.personalizationString = personalizationString;
+ this.securityStrength = securityStrength;
+ }
+
+ public SP80090DRBG get(EntropySource entropySource)
+ {
+ return new DualECSP800DRBG(pointSet, digest, securityStrength, entropySource, personalizationString, nonce);
+ }
+ }
+
private static class HMacDRBGProvider
implements DRBGProvider
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECPoints.java b/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECPoints.java
new file mode 100644
index 0000000..c3715bc
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECPoints.java
@@ -0,0 +1,82 @@
+package org.bouncycastle.crypto.prng.drbg;
+
+import org.bouncycastle.math.ec.ECPoint;
+
+/**
+ * General class for providing point pairs for use with DualEC DRBG. See NIST SP 800-90A for further details.
+ */
+public class DualECPoints
+{
+ private final ECPoint p;
+ private final ECPoint q;
+ private final int securityStrength;
+ private final int cofactor;
+
+ /**
+ * Base Constructor.
+ * <p>
+ * The cofactor is used to calculate the output block length (maxOutlen) according to
+ * <pre>
+ * max_outlen = largest multiple of 8 less than ((field size in bits) - (13 + log2(cofactor))
+ * </pre>
+ * </p>
+ * @param securityStrength maximum security strength to be associated with these parameters
+ * @param p the P point.
+ * @param q the Q point.
+ * @param cofactor cofactor associated with the domain parameters for the point generation.
+ */
+ public DualECPoints(int securityStrength, ECPoint p, ECPoint q, int cofactor)
+ {
+ if (!p.getCurve().equals(q.getCurve()))
+ {
+ throw new IllegalArgumentException("points need to be on the same curve");
+ }
+
+ this.securityStrength = securityStrength;
+ this.p = p;
+ this.q = q;
+ this.cofactor = cofactor;
+ }
+
+ public int getSeedLen()
+ {
+ return p.getCurve().getFieldSize();
+ }
+
+ public int getMaxOutlen()
+ {
+ return ((p.getCurve().getFieldSize() - (13 + log2(cofactor))) / 8) * 8;
+ }
+
+ public ECPoint getP()
+ {
+ return p;
+ }
+
+ public ECPoint getQ()
+ {
+ return q;
+ }
+
+ public int getSecurityStrength()
+ {
+ return securityStrength;
+ }
+
+ public int getCofactor()
+ {
+ return cofactor;
+ }
+
+ private static int log2(int value)
+ {
+ int log = 0;
+
+ while ((value >>= 1) != 0)
+ {
+ log++;
+ }
+
+ return log;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java b/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java
index 3cee39c..8d326ff 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/DualECSP800DRBG.java
@@ -6,7 +6,6 @@ import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.prng.EntropySource;
import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
@@ -35,6 +34,26 @@ public class DualECSP800DRBG
private static final BigInteger p521_Qx = new BigInteger("1b9fa3e518d683c6b65763694ac8efbaec6fab44f2276171a42726507dd08add4c3b3f4c1ebc5b1222ddba077f722943b24c3edfa0f85fe24d0c8c01591f0be6f63", 16);
private static final BigInteger p521_Qy = new BigInteger("1f3bdba585295d9a1110d1df1f9430ef8442c5018976ff3437ef91b81dc0b8132c8d5c39c32d0e004a3092b7d327c0e7a4d26d2c7b69b58f9066652911e457779de", 16);
+ private static final DualECPoints[] nistPoints;
+
+ static
+ {
+ nistPoints = new DualECPoints[3];
+
+ ECCurve.Fp curve = (ECCurve.Fp)NISTNamedCurves.getByName("P-256").getCurve();
+
+ nistPoints[0] = new DualECPoints(128, curve.createPoint(p256_Px, p256_Py), curve.createPoint(p256_Qx, p256_Qy), 1);
+
+ curve = (ECCurve.Fp)NISTNamedCurves.getByName("P-384").getCurve();
+
+ nistPoints[1] = new DualECPoints(192, curve.createPoint(p384_Px, p384_Py), curve.createPoint(p384_Qx, p384_Qy), 1);
+
+ curve = (ECCurve.Fp)NISTNamedCurves.getByName("P-521").getCurve();
+
+ nistPoints[2] = new DualECPoints(256, curve.createPoint(p521_Px, p521_Py), curve.createPoint(p521_Qx, p521_Qy), 1);
+ }
+
+
private static final long RESEED_MAX = 1L << (32 - 1);
private static final int MAX_ADDITIONAL_INPUT = 1 << (13 - 1);
private static final int MAX_ENTROPY_LENGTH = 1 << (13 - 1);
@@ -65,6 +84,23 @@ public class DualECSP800DRBG
*/
public DualECSP800DRBG(Digest digest, int securityStrength, EntropySource entropySource, byte[] personalizationString, byte[] nonce)
{
+ this(nistPoints, digest, securityStrength, entropySource, personalizationString, nonce);
+ }
+
+ /**
+ * Construct a SP800-90A Dual EC DRBG.
+ * <p>
+ * Minimum entropy requirement is the security strength requested.
+ * </p>
+ * @param pointSet an array of points to choose from, in order of increasing security strength
+ * @param digest source digest to use with the DRB stream.
+ * @param securityStrength security strength required (in bits)
+ * @param entropySource source of entropy to use for seeding/reseeding.
+ * @param personalizationString personalization string to distinguish this DRBG (may be null).
+ * @param nonce nonce to further distinguish this DRBG (may be null).
+ */
+ public DualECSP800DRBG(DualECPoints[] pointSet, Digest digest, int securityStrength, EntropySource entropySource, byte[] personalizationString, byte[] nonce)
+ {
_digest = digest;
_entropySource = entropySource;
_securityStrength = securityStrength;
@@ -82,43 +118,23 @@ public class DualECSP800DRBG
byte[] entropy = entropySource.getEntropy();
byte[] seedMaterial = Arrays.concatenate(entropy, nonce, personalizationString);
- if (securityStrength <= 128)
- {
- if (Utils.getMaxSecurityStrength(digest) < 128)
- {
- throw new IllegalArgumentException("Requested security strength is not supported by digest");
- }
- _seedlen = 256;
- _outlen = 240 / 8;
- _curve = (ECCurve.Fp)NISTNamedCurves.getByName("P-256").getCurve();
- _P = new ECPoint.Fp(_curve, new ECFieldElement.Fp(_curve.getQ(), p256_Px), new ECFieldElement.Fp(_curve.getQ(), p256_Py));
- _Q = new ECPoint.Fp(_curve, new ECFieldElement.Fp(_curve.getQ(), p256_Qx), new ECFieldElement.Fp(_curve.getQ(), p256_Qy));
- }
- else if (securityStrength <= 192)
+ for (int i = 0; i != pointSet.length; i++)
{
- if (Utils.getMaxSecurityStrength(digest) < 192)
+ if (securityStrength <= pointSet[i].getSecurityStrength())
{
- throw new IllegalArgumentException("Requested security strength is not supported by digest");
+ if (Utils.getMaxSecurityStrength(digest) < pointSet[i].getSecurityStrength())
+ {
+ throw new IllegalArgumentException("Requested security strength is not supported by digest");
+ }
+ _seedlen = pointSet[i].getSeedLen();
+ _outlen = pointSet[i].getMaxOutlen() / 8;
+ _P = pointSet[i].getP();
+ _Q = pointSet[i].getQ();
+ break;
}
- _seedlen = 384;
- _outlen = 368 / 8;
- _curve = (ECCurve.Fp)NISTNamedCurves.getByName("P-384").getCurve();
- _P = new ECPoint.Fp(_curve, new ECFieldElement.Fp(_curve.getQ(), p384_Px), new ECFieldElement.Fp(_curve.getQ(), p384_Py));
- _Q = new ECPoint.Fp(_curve, new ECFieldElement.Fp(_curve.getQ(), p384_Qx), new ECFieldElement.Fp(_curve.getQ(), p384_Qy));
}
- else if (securityStrength <= 256)
- {
- if (Utils.getMaxSecurityStrength(digest) < 256)
- {
- throw new IllegalArgumentException("Requested security strength is not supported by digest");
- }
- _seedlen = 521;
- _outlen = 504 / 8;
- _curve = (ECCurve.Fp)NISTNamedCurves.getByName("P-521").getCurve();
- _P = new ECPoint.Fp(_curve, new ECFieldElement.Fp(_curve.getQ(), p521_Px), new ECFieldElement.Fp(_curve.getQ(), p521_Py));
- _Q = new ECPoint.Fp(_curve, new ECFieldElement.Fp(_curve.getQ(), p521_Qx), new ECFieldElement.Fp(_curve.getQ(), p521_Qy));
- }
- else
+
+ if (_P == null)
{
throw new IllegalArgumentException("security strength cannot be greater than 256 bits");
}
@@ -159,50 +175,69 @@ public class DualECSP800DRBG
additionalInput = null;
}
+ BigInteger s;
+
if (additionalInput != null)
{
// Note: we ignore the use of pad8 on the additional input as we mandate byte arrays for it.
additionalInput = Utils.hash_df(_digest, additionalInput, _seedlen);
+ s = new BigInteger(1, xor(_s, additionalInput));
}
+ else
+ {
+ s = new BigInteger(1, _s);
+ }
+
+ // make sure we start with a clean output array.
+ Arrays.fill(output, (byte)0);
+
+ int outOffset = 0;
for (int i = 0; i < m; i++)
{
- BigInteger t = new BigInteger(1, xor(_s, additionalInput));
-
- _s = _P.multiply(t).getX().toBigInteger().toByteArray();
+ s = getScalarMultipleXCoord(_P, s);
//System.err.println("S: " + new String(Hex.encode(_s)));
- byte[] r = _Q.multiply(new BigInteger(1, _s)).getX().toBigInteger().toByteArray();
+ byte[] r = _Q.multiply(s).normalize().getAffineXCoord().toBigInteger().toByteArray();
if (r.length > _outlen)
{
- System.arraycopy(r, r.length - _outlen, output, i * _outlen, _outlen);
+ System.arraycopy(r, r.length - _outlen, output, outOffset, _outlen);
}
else
{
- System.arraycopy(r, 0, output, i * _outlen + (_outlen - r.length), r.length);
+ System.arraycopy(r, 0, output, outOffset + (_outlen - r.length), r.length);
}
//System.err.println("R: " + new String(Hex.encode(r)));
- additionalInput = null;
+ outOffset += _outlen;
_reseedCounter++;
}
- if (m * _outlen < output.length)
+ if (outOffset < output.length)
{
- BigInteger t = new BigInteger(1, xor(_s, additionalInput));
+ s = getScalarMultipleXCoord(_P, s);
- _s = _P.multiply(t).getX().toBigInteger().toByteArray();
+ byte[] r = _Q.multiply(s).normalize().getAffineXCoord().toBigInteger().toByteArray();
- byte[] r = _Q.multiply(new BigInteger(1, _s)).getX().toBigInteger().toByteArray();
+ int required = output.length - outOffset;
- System.arraycopy(r, 0, output, m * _outlen, output.length - (m * _outlen));
+ if (r.length > _outlen)
+ {
+ System.arraycopy(r, r.length - _outlen, output, outOffset, required);
+ }
+ else
+ {
+ System.arraycopy(r, 0, output, outOffset + (_outlen - r.length), required);
+ }
+
+ _reseedCounter++;
}
// Need to preserve length of S as unsigned int.
- _s = BigIntegers.asUnsignedByteArray(_sLength, _P.multiply(new BigInteger(1, _s)).getX().toBigInteger());
+ _s = BigIntegers.asUnsignedByteArray(_sLength, _P.multiply(s).normalize().getAffineXCoord().toBigInteger());
return numberOfBits;
}
@@ -264,4 +299,9 @@ public class DualECSP800DRBG
return s;
}
+
+ private BigInteger getScalarMultipleXCoord(ECPoint p, BigInteger s)
+ {
+ return p.multiply(s).normalize().getAffineXCoord().toBigInteger();
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/package.html
deleted file mode 100644
index 630809b..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/prng/drbg/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-NIST Deterministic Random Bit Generators (SP 800-90A).
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/prng/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/prng/package.html
deleted file mode 100644
index 9ad3854..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/prng/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Lightweight psuedo-random number generators and SecureRandom variants and builders.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java
new file mode 100644
index 0000000..fced06e
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSAKCalculator.java
@@ -0,0 +1,41 @@
+package org.bouncycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * Interface define calculators of K values for DSA/ECDSA.
+ */
+public interface DSAKCalculator
+{
+ /**
+ * Return true if this calculator is deterministic, false otherwise.
+ *
+ * @return true if deterministic, otherwise false.
+ */
+ boolean isDeterministic();
+
+ /**
+ * Non-deterministic initialiser.
+ *
+ * @param n the order of the DSA group.
+ * @param random a source of randomness.
+ */
+ void init(BigInteger n, SecureRandom random);
+
+ /**
+ * Deterministic initialiser.
+ *
+ * @param n the order of the DSA group.
+ * @param d the DSA private value.
+ * @param message the message being signed.
+ */
+ void init(BigInteger n, BigInteger d, byte[] message);
+
+ /**
+ * Return the next valid value of K.
+ *
+ * @return a K value.
+ */
+ BigInteger nextK();
+}
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 a96cef0..292c408 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
@@ -1,5 +1,8 @@
package org.bouncycastle.crypto.signers;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DSA;
import org.bouncycastle.crypto.params.DSAKeyParameters;
@@ -8,9 +11,6 @@ import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
/**
* The Digital Signature Algorithm - as described in "Handbook of Applied
* Cryptography", pages 452 - 453.
@@ -18,9 +18,28 @@ import java.security.SecureRandom;
public class DSASigner
implements DSA
{
- DSAKeyParameters key;
+ private final DSAKCalculator kCalculator;
- SecureRandom random;
+ private DSAKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * Default configuration, random K values.
+ */
+ public DSASigner()
+ {
+ this.kCalculator = new RandomDSAKCalculator();
+ }
+
+ /**
+ * Configuration with an alternate, possibly deterministic calculator of K.
+ *
+ * @param kCalculator a K value calculator.
+ */
+ public DSASigner(DSAKCalculator kCalculator)
+ {
+ this.kCalculator = kCalculator;
+ }
public void init(
boolean forSigning,
@@ -59,14 +78,17 @@ public class DSASigner
{
DSAParameters params = key.getParameters();
BigInteger m = calculateE(params.getQ(), message);
- BigInteger k;
- int qBitLength = params.getQ().bitLength();
- do
+ if (kCalculator.isDeterministic())
{
- k = new BigInteger(qBitLength, random);
+ kCalculator.init(params.getQ(), ((DSAPrivateKeyParameters)key).getX(), message);
}
- while (k.compareTo(params.getQ()) >= 0);
+ else
+ {
+ kCalculator.init(params.getQ(), random);
+ }
+
+ BigInteger k = kCalculator.nextK();
BigInteger r = params.getG().modPow(k, params.getP()).mod(params.getQ());
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java
index a8fc194..0e76950 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java
@@ -5,6 +5,7 @@ import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DSA;
+import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
@@ -56,12 +57,17 @@ public class DSTU4145Signer
public BigInteger[] generateSignature(byte[] message)
{
- ECFieldElement h = hash2FieldElement(key.getParameters().getCurve(), message);
- if (h.toBigInteger().signum() == 0)
+ ECDomainParameters parameters = key.getParameters();
+
+ ECCurve curve = parameters.getCurve();
+
+ ECFieldElement h = hash2FieldElement(curve, message);
+ if (h.isZero())
{
- h = key.getParameters().getCurve().fromBigInteger(ONE);
+ h = curve.fromBigInteger(ONE);
}
+ BigInteger n = parameters.getN();
BigInteger e, r, s;
ECFieldElement Fe, y;
@@ -71,17 +77,17 @@ public class DSTU4145Signer
{
do
{
- e = generateRandomInteger(key.getParameters().getN(), random);
- Fe = key.getParameters().getG().multiply(e).getX();
+ e = generateRandomInteger(n, random);
+ Fe = parameters.getG().multiply(e).normalize().getAffineXCoord();
}
- while (Fe.toBigInteger().signum() == 0);
+ while (Fe.isZero());
y = h.multiply(Fe);
- r = fieldElement2Integer(key.getParameters().getN(), y);
+ r = fieldElement2Integer(n, y);
}
while (r.signum() == 0);
- s = r.multiply(((ECPrivateKeyParameters)key).getD()).add(e).mod(key.getParameters().getN());
+ s = r.multiply(((ECPrivateKeyParameters)key).getD()).add(e).mod(n);
}
while (s.signum() == 0);
@@ -90,22 +96,28 @@ public class DSTU4145Signer
public boolean verifySignature(byte[] message, BigInteger r, BigInteger s)
{
- if (r.signum() == 0 || s.signum() == 0)
+ if (r.signum() <= 0 || s.signum() <= 0)
{
return false;
}
- if (r.compareTo(key.getParameters().getN()) >= 0 || s.compareTo(key.getParameters().getN()) >= 0)
+
+ ECDomainParameters parameters = key.getParameters();
+
+ BigInteger n = parameters.getN();
+ if (r.compareTo(n) >= 0 || s.compareTo(n) >= 0)
{
return false;
}
- ECFieldElement h = hash2FieldElement(key.getParameters().getCurve(), message);
- if (h.toBigInteger().signum() == 0)
+ ECCurve curve = parameters.getCurve();
+
+ ECFieldElement h = hash2FieldElement(curve, message);
+ if (h.isZero())
{
- h = key.getParameters().getCurve().fromBigInteger(ONE);
+ h = curve.fromBigInteger(ONE);
}
- ECPoint R = ECAlgorithms.sumOfTwoMultiplies(key.getParameters().getG(), s, ((ECPublicKeyParameters)key).getQ(), r);
+ ECPoint R = ECAlgorithms.sumOfTwoMultiplies(parameters.getG(), s, ((ECPublicKeyParameters)key).getQ(), r).normalize();
// components must be bogus.
if (R.isInfinity())
@@ -113,8 +125,8 @@ public class DSTU4145Signer
return false;
}
- ECFieldElement y = h.multiply(R.getX());
- return fieldElement2Integer(key.getParameters().getN(), y).compareTo(r) == 0;
+ ECFieldElement y = h.multiply(R.getAffineXCoord());
+ return fieldElement2Integer(n, y).compareTo(r) == 0;
}
/**
@@ -142,7 +154,7 @@ public class DSTU4145Signer
byte[] data = Arrays.clone(hash);
reverseBytes(data);
BigInteger num = new BigInteger(1, data);
- while (num.bitLength() >= curve.getFieldSize())
+ while (num.bitLength() > curve.getFieldSize())
{
num = num.clearBit(num.bitLength() - 1);
}
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 a80c574..2a1f98e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
@@ -19,9 +19,28 @@ import org.bouncycastle.math.ec.ECPoint;
public class ECDSASigner
implements ECConstants, DSA
{
- ECKeyParameters key;
+ private final DSAKCalculator kCalculator;
- SecureRandom random;
+ private ECKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * Default configuration, random K values.
+ */
+ public ECDSASigner()
+ {
+ this.kCalculator = new RandomDSAKCalculator();
+ }
+
+ /**
+ * Configuration with an alternate, possibly deterministic calculator of K.
+ *
+ * @param kCalculator a K value calculator.
+ */
+ public ECDSASigner(DSAKCalculator kCalculator)
+ {
+ this.kCalculator = kCalculator;
+ }
public void init(
boolean forSigning,
@@ -64,24 +83,28 @@ public class ECDSASigner
BigInteger r = null;
BigInteger s = null;
+ if (kCalculator.isDeterministic())
+ {
+ kCalculator.init(n, ((ECPrivateKeyParameters)key).getD(), message);
+ }
+ else
+ {
+ kCalculator.init(n, random);
+ }
+
// 5.3.2
do // generate s
{
BigInteger k = null;
- int nBitLength = n.bitLength();
do // generate r
{
- do
- {
- k = new BigInteger(nBitLength, random);
- }
- while (k.equals(ZERO) || k.compareTo(n) >= 0);
+ k = kCalculator.nextK();
- ECPoint p = key.getParameters().getG().multiply(k);
+ ECPoint p = key.getParameters().getG().multiply(k).normalize();
// 5.3.3
- BigInteger x = p.getX().toBigInteger();
+ BigInteger x = p.getAffineXCoord().toBigInteger();
r = x.mod(n);
}
@@ -135,7 +158,7 @@ public class ECDSASigner
ECPoint G = key.getParameters().getG();
ECPoint Q = ((ECPublicKeyParameters)key).getQ();
- ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2);
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2).normalize();
// components must be bogus.
if (point.isInfinity())
@@ -143,7 +166,7 @@ public class ECDSASigner
return false;
}
- BigInteger v = point.getX().toBigInteger().mod(n);
+ BigInteger v = point.getAffineXCoord().toBigInteger().mod(n);
return v.equals(r);
}
@@ -153,17 +176,11 @@ public class ECDSASigner
int log2n = n.bitLength();
int messageBitLength = message.length * 8;
- if (log2n >= messageBitLength)
+ BigInteger e = new BigInteger(1, message);
+ if (log2n < messageBitLength)
{
- return new BigInteger(1, message);
- }
- else
- {
- BigInteger trunc = new BigInteger(1, message);
-
- trunc = trunc.shiftRight(messageBitLength - log2n);
-
- return trunc;
+ e = e.shiftRight(messageBitLength - log2n);
}
+ return e;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java
index 7256d35..f6d7f4f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECGOST3410Signer.java
@@ -82,9 +82,9 @@ public class ECGOST3410Signer
}
while (k.equals(ECConstants.ZERO));
- ECPoint p = key.getParameters().getG().multiply(k);
+ ECPoint p = key.getParameters().getG().multiply(k).normalize();
- BigInteger x = p.getX().toBigInteger();
+ BigInteger x = p.getAffineXCoord().toBigInteger();
r = x.mod(n);
}
@@ -143,7 +143,7 @@ public class ECGOST3410Signer
ECPoint G = key.getParameters().getG(); // P
ECPoint Q = ((ECPublicKeyParameters)key).getQ();
- ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, z1, Q, z2);
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, z1, Q, z2).normalize();
// components must be bogus.
if (point.isInfinity())
@@ -151,7 +151,7 @@ public class ECGOST3410Signer
return false;
}
- BigInteger R = point.getX().toBigInteger().mod(n);
+ BigInteger R = point.getAffineXCoord().toBigInteger().mod(n);
return R.equals(r);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECNRSigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECNRSigner.java
index 07e8ca7..72bbbcb 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECNRSigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECNRSigner.java
@@ -101,8 +101,8 @@ public class ECNRSigner
// BigInteger Vx = tempPair.getPublic().getW().getAffineX();
ECPublicKeyParameters V = (ECPublicKeyParameters)tempPair.getPublic(); // get temp's public key
- BigInteger Vx = V.getQ().getX().toBigInteger(); // get the point's x coordinate
-
+ BigInteger Vx = V.getQ().normalize().getAffineXCoord().toBigInteger(); // get the point's x coordinate
+
r = Vx.add(e).mod(n);
}
while (r.equals(ECConstants.ZERO));
@@ -172,7 +172,7 @@ public class ECNRSigner
ECPoint G = pubKey.getParameters().getG();
ECPoint W = pubKey.getQ();
// calculate P using Bouncy math
- ECPoint P = ECAlgorithms.sumOfTwoMultiplies(G, s, W, r);
+ ECPoint P = ECAlgorithms.sumOfTwoMultiplies(G, s, W, r).normalize();
// components must be bogus.
if (P.isInfinity())
@@ -180,7 +180,7 @@ public class ECNRSigner
return false;
}
- BigInteger x = P.getX().toBigInteger();
+ BigInteger x = P.getAffineXCoord().toBigInteger();
BigInteger t = r.subtract(x).mod(n);
return t.equals(e);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/HMacDSAKCalculator.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/HMacDSAKCalculator.java
new file mode 100644
index 0000000..b96e3f3
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/HMacDSAKCalculator.java
@@ -0,0 +1,161 @@
+package org.bouncycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.BigIntegers;
+
+/**
+ * A deterministic K calculator based on the algorithm in section 3.2 of RFC 6979.
+ */
+public class HMacDSAKCalculator
+ implements DSAKCalculator
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ private final HMac hMac;
+ private final byte[] K;
+ private final byte[] V;
+
+ private BigInteger n;
+
+ /**
+ * Base constructor.
+ *
+ * @param digest digest to build the HMAC on.
+ */
+ public HMacDSAKCalculator(Digest digest)
+ {
+ this.hMac = new HMac(digest);
+ this.V = new byte[hMac.getMacSize()];
+ this.K = new byte[hMac.getMacSize()];
+ }
+
+ public boolean isDeterministic()
+ {
+ return true;
+ }
+
+ public void init(BigInteger n, SecureRandom random)
+ {
+ throw new IllegalStateException("Operation not supported");
+ }
+
+ public void init(BigInteger n, BigInteger d, byte[] message)
+ {
+ this.n = n;
+
+ Arrays.fill(V, (byte)0x01);
+ Arrays.fill(K, (byte)0);
+
+ byte[] x = new byte[(n.bitLength() + 7) / 8];
+ byte[] dVal = BigIntegers.asUnsignedByteArray(d);
+
+ System.arraycopy(dVal, 0, x, x.length - dVal.length, dVal.length);
+
+ byte[] m = new byte[(n.bitLength() + 7) / 8];
+
+ BigInteger mInt = bitsToInt(message);
+
+ if (mInt.compareTo(n) > 0)
+ {
+ mInt = mInt.subtract(n);
+ }
+
+ byte[] mVal = BigIntegers.asUnsignedByteArray(mInt);
+
+ System.arraycopy(mVal, 0, m, m.length - mVal.length, mVal.length);
+
+ hMac.init(new KeyParameter(K));
+
+ hMac.update(V, 0, V.length);
+ hMac.update((byte)0x00);
+ hMac.update(x, 0, x.length);
+ hMac.update(m, 0, m.length);
+
+ hMac.doFinal(K, 0);
+
+ hMac.init(new KeyParameter(K));
+
+ hMac.update(V, 0, V.length);
+
+ hMac.doFinal(V, 0);
+
+ hMac.update(V, 0, V.length);
+ hMac.update((byte)0x01);
+ hMac.update(x, 0, x.length);
+ hMac.update(m, 0, m.length);
+
+ hMac.doFinal(K, 0);
+
+ hMac.init(new KeyParameter(K));
+
+ hMac.update(V, 0, V.length);
+
+ hMac.doFinal(V, 0);
+ }
+
+ public BigInteger nextK()
+ {
+ byte[] t = new byte[((n.bitLength() + 7) / 8)];
+
+ for (;;)
+ {
+ int tOff = 0;
+
+ while (tOff < t.length)
+ {
+ hMac.update(V, 0, V.length);
+
+ hMac.doFinal(V, 0);
+
+ if (t.length - tOff < V.length)
+ {
+ System.arraycopy(V, 0, t, tOff, t.length - tOff);
+ tOff += t.length - tOff;
+ }
+ else
+ {
+ System.arraycopy(V, 0, t, tOff, V.length);
+ tOff += V.length;
+ }
+ }
+
+ BigInteger k = bitsToInt(t);
+
+ if (k.equals(ZERO) || k.compareTo(n) >= 0)
+ {
+ hMac.update(V, 0, V.length);
+ hMac.update((byte)0x00);
+
+ hMac.doFinal(K, 0);
+
+ hMac.init(new KeyParameter(K));
+
+ hMac.update(V, 0, V.length);
+
+ hMac.doFinal(V, 0);
+ }
+ else
+ {
+ return k;
+ }
+ }
+ }
+
+ private BigInteger bitsToInt(byte[] t)
+ {
+ BigInteger v = new BigInteger(1, t);
+
+ if (t.length * 8 > n.bitLength())
+ {
+ v = v.shiftRight(t.length * 8 - n.bitLength());
+ }
+
+ return v;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
index f33ed31..aaae064 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
@@ -57,9 +57,15 @@ public class RSADigestSigner
public RSADigestSigner(
Digest digest)
{
- this.digest = digest;
+ this(digest, (ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()));
+ }
- algId = new AlgorithmIdentifier((ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()), DERNull.INSTANCE);
+ public RSADigestSigner(
+ Digest digest,
+ ASN1ObjectIdentifier digestOid)
+ {
+ this.digest = digest;
+ this.algId = new AlgorithmIdentifier(digestOid, DERNull.INSTANCE);
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
new file mode 100644
index 0000000..bbd8cda
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
@@ -0,0 +1,43 @@
+package org.bouncycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+class RandomDSAKCalculator
+ implements DSAKCalculator
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ private BigInteger q;
+ private SecureRandom random;
+
+ public boolean isDeterministic()
+ {
+ return false;
+ }
+
+ public void init(BigInteger n, SecureRandom random)
+ {
+ this.q = n;
+ this.random = random;
+ }
+
+ public void init(BigInteger n, BigInteger d, byte[] message)
+ {
+ throw new IllegalStateException("Operation not supported");
+ }
+
+ public BigInteger nextK()
+ {
+ int qBitLength = q.bitLength();
+
+ BigInteger k;
+ do
+ {
+ k = new BigInteger(qBitLength, random);
+ }
+ while (k.equals(ZERO) || k.compareTo(q) >= 0);
+
+ return k;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/signers/package.html
deleted file mode 100644
index 151d3d5..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Basic signers.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsAgreementCredentials.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsAgreementCredentials.java
new file mode 100644
index 0000000..ef7f4fb
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsAgreementCredentials.java
@@ -0,0 +1,7 @@
+package org.bouncycastle.crypto.tls;
+
+public abstract class AbstractTlsAgreementCredentials
+ extends AbstractTlsCredentials
+ implements TlsAgreementCredentials
+{
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCipherFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCipherFactory.java
index 9c2a526..71a2cab 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCipherFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCipherFactory.java
@@ -5,11 +5,9 @@ import java.io.IOException;
public class AbstractTlsCipherFactory
implements TlsCipherFactory
{
-
public TlsCipher createCipher(TlsContext context, int encryptionAlgorithm, int macAlgorithm)
throws IOException
{
-
throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java
index 9e113f9..7d4fd03 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java
@@ -8,12 +8,13 @@ public abstract class AbstractTlsClient
extends AbstractTlsPeer
implements TlsClient
{
-
protected TlsCipherFactory cipherFactory;
protected TlsClientContext context;
protected Vector supportedSignatureAlgorithms;
+ protected int[] namedCurves;
+ protected short[] clientECPointFormats, serverECPointFormats;
protected int selectedCipherSuite;
protected short selectedCompressionMethod;
@@ -33,6 +34,11 @@ public abstract class AbstractTlsClient
this.context = context;
}
+ public TlsSession getSessionToResume()
+ {
+ return null;
+ }
+
/**
* RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value
* {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest
@@ -46,7 +52,7 @@ public abstract class AbstractTlsClient
// return ProtocolVersion.SSLv3;
// "the lowest version number supported by the client"
- // return getMinimumServerVersion();
+ // return getMinimumVersion();
// "the value of ClientHello.client_version"
return getClientVersion();
@@ -54,13 +60,12 @@ public abstract class AbstractTlsClient
public ProtocolVersion getClientVersion()
{
- return ProtocolVersion.TLSv11;
+ return ProtocolVersion.TLSv12;
}
public Hashtable getClientExtensions()
throws IOException
{
-
Hashtable clientExtensions = null;
ProtocolVersion clientVersion = context.getClientVersion();
@@ -71,14 +76,13 @@ public abstract class AbstractTlsClient
*/
if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion))
{
-
// TODO Provide a way for the user to specify the acceptable hash/signature algorithms.
- short[] hashAlgorithms = new short[]{HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
- HashAlgorithm.sha224, HashAlgorithm.sha1};
+ short[] hashAlgorithms = new short[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
+ HashAlgorithm.sha224, HashAlgorithm.sha1 };
// TODO Sort out ECDSA signatures and add them as the preferred option here
- short[] signatureAlgorithms = new short[]{SignatureAlgorithm.rsa};
+ short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa };
this.supportedSignatureAlgorithms = new Vector();
for (int i = 0; i < hashAlgorithms.length; ++i)
@@ -96,14 +100,33 @@ public abstract class AbstractTlsClient
this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1,
SignatureAlgorithm.dsa));
- if (clientExtensions == null)
- {
- clientExtensions = new Hashtable();
- }
+ clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions);
TlsUtils.addSignatureAlgorithmsExtension(clientExtensions, supportedSignatureAlgorithms);
}
+ if (TlsECCUtils.containsECCCipherSuites(getCipherSuites()))
+ {
+ /*
+ * RFC 4492 5.1. A client that proposes ECC cipher suites in its ClientHello message
+ * appends these extensions (along with any others), enumerating the curves it supports
+ * and the point formats it can parse. Clients SHOULD send both the Supported Elliptic
+ * Curves Extension and the Supported Point Formats Extension.
+ */
+ /*
+ * TODO Could just add all the curves since we support them all, but users may not want
+ * to use unnecessarily large fields. Need configuration options.
+ */
+ this.namedCurves = new int[]{ NamedCurve.secp256r1, NamedCurve.secp384r1 };
+ this.clientECPointFormats = new short[]{ ECPointFormat.uncompressed,
+ ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, };
+
+ clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions);
+
+ TlsECCUtils.addSupportedEllipticCurvesExtension(clientExtensions, namedCurves);
+ TlsECCUtils.addSupportedPointFormatsExtension(clientExtensions, clientECPointFormats);
+ }
+
return clientExtensions;
}
@@ -141,19 +164,6 @@ public abstract class AbstractTlsClient
this.selectedCompressionMethod = selectedCompressionMethod;
}
- public void notifySecureRenegotiation(boolean secureRenegotiation)
- throws IOException
- {
- if (!secureRenegotiation)
- {
- /*
- * RFC 5746 3.4. In this case, some clients may want to terminate the handshake instead
- * of continuing; see Section 4.1 for discussion.
- */
- // throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
-
public void processServerExtensions(Hashtable serverExtensions)
throws IOException
{
@@ -170,6 +180,18 @@ public abstract class AbstractTlsClient
{
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
+
+ int[] namedCurves = TlsECCUtils.getSupportedEllipticCurvesExtension(serverExtensions);
+ if (namedCurves != null)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ this.serverECPointFormats = TlsECCUtils.getSupportedPointFormatsExtension(serverExtensions);
+ if (this.serverECPointFormats != null && !TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
}
}
@@ -210,9 +232,4 @@ public abstract class AbstractTlsClient
throws IOException
{
}
-
- public void notifyHandshakeComplete()
- throws IOException
- {
- }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsContext.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsContext.java
index 1ff67e3..5e02892 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsContext.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsContext.java
@@ -5,12 +5,12 @@ import java.security.SecureRandom;
abstract class AbstractTlsContext
implements TlsContext
{
-
private SecureRandom secureRandom;
private SecurityParameters securityParameters;
private ProtocolVersion clientVersion = null;
private ProtocolVersion serverVersion = null;
+ private TlsSession session = null;
private Object userObject = null;
AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters)
@@ -34,7 +34,7 @@ abstract class AbstractTlsContext
return clientVersion;
}
- public void setClientVersion(ProtocolVersion clientVersion)
+ void setClientVersion(ProtocolVersion clientVersion)
{
this.clientVersion = clientVersion;
}
@@ -44,11 +44,21 @@ abstract class AbstractTlsContext
return serverVersion;
}
- public void setServerVersion(ProtocolVersion serverVersion)
+ void setServerVersion(ProtocolVersion serverVersion)
{
this.serverVersion = serverVersion;
}
+ public TlsSession getResumableSession()
+ {
+ return session;
+ }
+
+ void setResumableSession(TlsSession session)
+ {
+ this.session = session;
+ }
+
public Object getUserObject()
{
return userObject;
@@ -61,6 +71,10 @@ abstract class AbstractTlsContext
public byte[] exportKeyingMaterial(String asciiLabel, byte[] context_value, int length)
{
+ if (context_value != null && !TlsUtils.isValidUint16(context_value.length))
+ {
+ throw new IllegalArgumentException("'context_value' must have length less than 2^16 (or be null)");
+ }
SecurityParameters sp = getSecurityParameters();
byte[] cr = sp.getClientRandom(), sr = sp.getServerRandom();
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCredentials.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCredentials.java
new file mode 100644
index 0000000..b98743f
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsCredentials.java
@@ -0,0 +1,6 @@
+package org.bouncycastle.crypto.tls;
+
+public abstract class AbstractTlsCredentials
+ implements TlsCredentials
+{
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsEncryptionCredentials.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsEncryptionCredentials.java
new file mode 100644
index 0000000..e6ff39b
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsEncryptionCredentials.java
@@ -0,0 +1,7 @@
+package org.bouncycastle.crypto.tls;
+
+public abstract class AbstractTlsEncryptionCredentials
+ extends AbstractTlsCredentials
+ implements TlsEncryptionCredentials
+{
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java
index 85057c1..43e80e6 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java
@@ -7,7 +7,6 @@ import java.util.Vector;
public abstract class AbstractTlsKeyExchange
implements TlsKeyExchange
{
-
protected int keyExchange;
protected Vector supportedSignatureAlgorithms;
@@ -27,7 +26,6 @@ public abstract class AbstractTlsKeyExchange
if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion))
{
-
/*
* RFC 5264 7.4.1.4.1. If the client does not send the signature_algorithms extension,
* the server MUST do the following:
@@ -45,7 +43,6 @@ public abstract class AbstractTlsKeyExchange
{
switch (keyExchange)
{
-
case KeyExchangeAlgorithm.DH_DSS:
case KeyExchangeAlgorithm.DHE_DSS:
case KeyExchangeAlgorithm.SRP_DSS:
@@ -73,6 +70,12 @@ public abstract class AbstractTlsKeyExchange
break;
}
+ case KeyExchangeAlgorithm.DHE_PSK:
+ case KeyExchangeAlgorithm.ECDHE_PSK:
+ case KeyExchangeAlgorithm.PSK:
+ case KeyExchangeAlgorithm.SRP:
+ break;
+
default:
throw new IllegalStateException("unsupported key exchange algorithm");
}
@@ -88,7 +91,6 @@ public abstract class AbstractTlsKeyExchange
public void processServerCertificate(Certificate serverCertificate)
throws IOException
{
-
if (supportedSignatureAlgorithms == null)
{
/*
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsPeer.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsPeer.java
index bdfd0d5..80d6af7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsPeer.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsPeer.java
@@ -1,8 +1,21 @@
package org.bouncycastle.crypto.tls;
+import java.io.IOException;
+
public abstract class AbstractTlsPeer
implements TlsPeer
{
+ public void notifySecureRenegotiation(boolean secureRenegotiation) throws IOException
+ {
+ if (!secureRenegotiation)
+ {
+ /*
+ * RFC 5746 3.4/3.6. In this case, some clients/servers may want to terminate the handshake instead
+ * of continuing; see Section 4.1/4.3 for discussion.
+ */
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ }
public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Exception cause)
{
@@ -11,4 +24,8 @@ public abstract class AbstractTlsPeer
public void notifyAlertReceived(short alertLevel, short alertDescription)
{
}
+
+ public void notifyHandshakeComplete() throws IOException
+ {
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsServer.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsServer.java
index 8235fd1..bd428a9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsServer.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsServer.java
@@ -4,11 +4,12 @@ import java.io.IOException;
import java.util.Hashtable;
import java.util.Vector;
+import org.bouncycastle.util.Arrays;
+
public abstract class AbstractTlsServer
extends AbstractTlsPeer
implements TlsServer
{
-
protected TlsCipherFactory cipherFactory;
protected TlsServerContext context;
@@ -18,6 +19,8 @@ public abstract class AbstractTlsServer
protected short[] offeredCompressionMethods;
protected Hashtable clientExtensions;
+ protected short maxFragmentLengthOffered;
+ protected boolean truncatedHMacOffered;
protected Vector supportedSignatureAlgorithms;
protected boolean eccCipherSuitesOffered;
protected int[] namedCurves;
@@ -38,6 +41,16 @@ public abstract class AbstractTlsServer
this.cipherFactory = cipherFactory;
}
+ protected boolean allowTruncatedHMac()
+ {
+ return false;
+ }
+
+ protected Hashtable checkServerExtensions()
+ {
+ return this.serverExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(this.serverExtensions);
+ }
+
protected abstract int[] getCipherSuites();
protected short[] getCompressionMethods()
@@ -57,7 +70,6 @@ public abstract class AbstractTlsServer
protected boolean supportsClientECCCapabilities(int[] namedCurves, short[] ecPointFormats)
{
-
// NOTE: BC supports all the current set of point formats so we don't check them here
if (namedCurves == null)
@@ -106,27 +118,15 @@ public abstract class AbstractTlsServer
this.offeredCompressionMethods = offeredCompressionMethods;
}
- public void notifySecureRenegotiation(boolean secureRenegotiation)
- throws IOException
- {
- if (!secureRenegotiation)
- {
- /*
- * RFC 5746 3.6. In this case, some servers may want to terminate the handshake instead
- * of continuing; see Section 4.3 for discussion.
- */
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
- }
-
public void processClientExtensions(Hashtable clientExtensions)
throws IOException
{
-
this.clientExtensions = clientExtensions;
if (clientExtensions != null)
{
+ this.maxFragmentLengthOffered = TlsExtensionsUtils.getMaxFragmentLengthExtension(clientExtensions);
+ this.truncatedHMacOffered = TlsExtensionsUtils.hasTruncatedHMacExtension(clientExtensions);
this.supportedSignatureAlgorithms = TlsUtils.getSignatureAlgorithmsExtension(clientExtensions);
if (this.supportedSignatureAlgorithms != null)
@@ -176,7 +176,6 @@ public abstract class AbstractTlsServer
public int getSelectedCipherSuite()
throws IOException
{
-
/*
* TODO RFC 5246 7.4.3. In order to negotiate correctly, the server MUST check any candidate
* cipher suites against the "signature_algorithms" extension before selecting them. This is
@@ -197,7 +196,9 @@ public abstract class AbstractTlsServer
for (int i = 0; i < cipherSuites.length; ++i)
{
int cipherSuite = cipherSuites[i];
- if (TlsProtocol.arrayContains(this.offeredCipherSuites, cipherSuite)
+
+ // TODO Certain cipher suites may only be available starting at a particular version
+ if (Arrays.contains(this.offeredCipherSuites, cipherSuite)
&& (eccCipherSuitesEnabled || !TlsECCUtils.isECCCipherSuite(cipherSuite)))
{
return this.selectedCipherSuite = cipherSuite;
@@ -212,7 +213,7 @@ public abstract class AbstractTlsServer
short[] compressionMethods = getCompressionMethods();
for (int i = 0; i < compressionMethods.length; ++i)
{
- if (TlsProtocol.arrayContains(offeredCompressionMethods, compressionMethods[i]))
+ if (Arrays.contains(offeredCompressionMethods, compressionMethods[i]))
{
return this.selectedCompressionMethod = compressionMethods[i];
}
@@ -224,6 +225,15 @@ public abstract class AbstractTlsServer
public Hashtable getServerExtensions()
throws IOException
{
+ if (this.maxFragmentLengthOffered >= 0)
+ {
+ TlsExtensionsUtils.addMaxFragmentLengthExtension(checkServerExtensions(), this.maxFragmentLengthOffered);
+ }
+
+ if (this.truncatedHMacOffered && allowTruncatedHMac())
+ {
+ TlsExtensionsUtils.addTruncatedHMacExtension(checkServerExtensions());
+ }
if (this.clientECPointFormats != null && TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite))
{
@@ -232,15 +242,13 @@ public abstract class AbstractTlsServer
* message including a Supported Point Formats Extension appends this extension (along
* with others) to its ServerHello message, enumerating the point formats it can parse.
*/
- this.serverECPointFormats = new short[]{ECPointFormat.ansiX962_compressed_char2,
- ECPointFormat.ansiX962_compressed_prime, ECPointFormat.uncompressed};
+ this.serverECPointFormats = new short[]{ ECPointFormat.ansiX962_compressed_char2,
+ ECPointFormat.ansiX962_compressed_prime, ECPointFormat.uncompressed };
- this.serverExtensions = new Hashtable();
- TlsECCUtils.addSupportedPointFormatsExtension(serverExtensions, serverECPointFormats);
- return serverExtensions;
+ TlsECCUtils.addSupportedPointFormatsExtension(checkServerExtensions(), serverECPointFormats);
}
- return null;
+ return serverExtensions;
}
public Vector getServerSupplementalData()
@@ -249,7 +257,14 @@ public abstract class AbstractTlsServer
return null;
}
+ public CertificateStatus getCertificateStatus()
+ throws IOException
+ {
+ return null;
+ }
+
public CertificateRequest getCertificateRequest()
+ throws IOException
{
return null;
}
@@ -296,9 +311,4 @@ public abstract class AbstractTlsServer
*/
return new NewSessionTicket(0L, TlsUtils.EMPTY_BYTES);
}
-
- public void notifyHandshakeComplete()
- throws IOException
- {
- }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSigner.java
index a0c24c7..3a1d631 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSigner.java
@@ -1,13 +1,38 @@
package org.bouncycastle.crypto.tls;
+import org.bouncycastle.crypto.CryptoException;
+import org.bouncycastle.crypto.Signer;
+import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+
public abstract class AbstractTlsSigner
implements TlsSigner
{
-
protected TlsContext context;
public void init(TlsContext context)
{
this.context = context;
}
+
+ public byte[] generateRawSignature(AsymmetricKeyParameter privateKey, byte[] md5AndSha1)
+ throws CryptoException
+ {
+ return generateRawSignature(null, privateKey, md5AndSha1);
+ }
+
+ public boolean verifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5AndSha1)
+ throws CryptoException
+ {
+ return verifyRawSignature(null, sigBytes, publicKey, md5AndSha1);
+ }
+
+ public Signer createSigner(AsymmetricKeyParameter privateKey)
+ {
+ return createSigner(null, privateKey);
+ }
+
+ public Signer createVerifyer(AsymmetricKeyParameter publicKey)
+ {
+ return createVerifyer(null, publicKey);
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSignerCredentials.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSignerCredentials.java
new file mode 100644
index 0000000..3452f52
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsSignerCredentials.java
@@ -0,0 +1,11 @@
+package org.bouncycastle.crypto.tls;
+
+public abstract class AbstractTlsSignerCredentials
+ extends AbstractTlsCredentials
+ implements TlsSignerCredentials
+{
+ public SignatureAndHashAlgorithm getSignatureAndHashAlgorithm()
+ {
+ throw new IllegalStateException("TlsSignerCredentials implementation does not support (D)TLS 1.2+");
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AlertDescription.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AlertDescription.java
index 5e3269b..91366be 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/AlertDescription.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/AlertDescription.java
@@ -5,11 +5,12 @@ package org.bouncycastle.crypto.tls;
*/
public class AlertDescription
{
-
/**
* This message notifies the recipient that the sender will not send any more messages on this
- * connection. The session becomes unresumable if any connection is terminated without proper
- * close_notify messages with level equal to warning.
+ * connection. Note that as of TLS 1.1, failure to properly close a connection no longer
+ * requires that a session not be resumed. This is a change from TLS 1.0 ("The session becomes
+ * unresumable if any connection is terminated without proper close_notify messages with level
+ * equal to warning.") to conform with widespread implementation practice.
*/
public static final short close_notify = 0;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ByteQueue.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ByteQueue.java
index 8b9d4ab..7642c4a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ByteQueue.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ByteQueue.java
@@ -25,12 +25,12 @@ public class ByteQueue
/**
* The initial size for our buffer.
*/
- private static final int INITBUFSIZE = 1024;
+ private static final int DEFAULT_CAPACITY = 1024;
/**
* The buffer where we store our data.
*/
- private byte[] databuf = new byte[ByteQueue.INITBUFSIZE];
+ private byte[] databuf;;
/**
* How many bytes at the beginning of the buffer are skipped.
@@ -42,6 +42,16 @@ public class ByteQueue
*/
private int available = 0;
+ public ByteQueue()
+ {
+ this(DEFAULT_CAPACITY);
+ }
+
+ public ByteQueue(int capacity)
+ {
+ databuf = new byte[capacity];
+ }
+
/**
* Read data from the buffer.
*
@@ -62,26 +72,34 @@ public class ByteQueue
+ " is too small for a read of " + len + " bytes");
}
System.arraycopy(databuf, skipped + skip, buf, offset, len);
- return;
}
/**
* Add some data to our buffer.
*
- * @param data A byte-array to read data from.
- * @param offset How many bytes to skip at the beginning of the array.
- * @param len How many bytes to read from the array.
+ * @param buf A byte-array to read data from.
+ * @param off How many bytes to skip at the beginning of the array.
+ * @param len How many bytes to read from the array.
*/
- public void addData(byte[] data, int offset, int len)
+ public void addData(byte[] buf, int off, int len)
{
if ((skipped + available + len) > databuf.length)
{
- byte[] tmp = new byte[ByteQueue.nextTwoPow(data.length)];
- System.arraycopy(databuf, skipped, tmp, 0, available);
+ int desiredSize = ByteQueue.nextTwoPow(available + len);
+ if (desiredSize > databuf.length)
+ {
+ byte[] tmp = new byte[desiredSize];
+ System.arraycopy(databuf, skipped, tmp, 0, available);
+ databuf = tmp;
+ }
+ else
+ {
+ System.arraycopy(databuf, skipped, databuf, 0, available);
+ }
skipped = 0;
- databuf = tmp;
}
- System.arraycopy(data, offset, databuf, skipped + available, len);
+
+ System.arraycopy(buf, off, databuf, skipped + available, len);
available += len;
}
@@ -102,15 +120,27 @@ public class ByteQueue
*/
available -= i;
skipped += i;
+ }
- /*
- * If more than half of our data is skipped, we will move the data in the buffer.
- */
- if (skipped > (databuf.length / 2))
- {
- System.arraycopy(databuf, skipped, databuf, 0, available);
- skipped = 0;
- }
+ /**
+ * Remove data from the buffer.
+ *
+ * @param buf The buffer where the removed data will be copied to.
+ * @param off How many bytes to skip at the beginning of buf.
+ * @param len How many bytes to read at all.
+ * @param skip How many bytes from our data to skip.
+ */
+ public void removeData(byte[] buf, int off, int len, int skip)
+ {
+ read(buf, off, len, skip);
+ removeData(skip + len);
+ }
+
+ public byte[] removeData(int len, int skip)
+ {
+ byte[] buf = new byte[len];
+ removeData(buf, 0, len, skip);
+ return buf;
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertChainType.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertChainType.java
new file mode 100644
index 0000000..8902ed7
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertChainType.java
@@ -0,0 +1,15 @@
+package org.bouncycastle.crypto.tls;
+
+/*
+ * RFC 3546 3.3.
+ */
+public class CertChainType
+{
+ public static final short individual_certs = 0;
+ public static final short pkipath = 1;
+
+ public static boolean isValid(short certChainType)
+ {
+ return certChainType >= individual_certs && certChainType <= pkipath;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/Certificate.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/Certificate.java
index fab79f4..02cf693 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/Certificate.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/Certificate.java
@@ -7,7 +7,6 @@ import java.io.OutputStream;
import java.util.Vector;
import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Primitive;
/**
@@ -25,7 +24,6 @@ import org.bouncycastle.asn1.ASN1Primitive;
*/
public class Certificate
{
-
public static final Certificate EMPTY_CHAIN = new Certificate(
new org.bouncycastle.asn1.x509.Certificate[0]);
@@ -46,7 +44,7 @@ public class Certificate
*/
public org.bouncycastle.asn1.x509.Certificate[] getCerts()
{
- return clone(certificateList);
+ return getCertificateList();
}
/**
@@ -55,7 +53,7 @@ public class Certificate
*/
public org.bouncycastle.asn1.x509.Certificate[] getCertificateList()
{
- return clone(certificateList);
+ return cloneCertificateList();
}
public org.bouncycastle.asn1.x509.Certificate getCertificateAt(int index)
@@ -86,21 +84,23 @@ public class Certificate
public void encode(OutputStream output)
throws IOException
{
- Vector encCerts = new Vector(this.certificateList.length);
+ Vector derEncodings = new Vector(this.certificateList.length);
+
int totalLength = 0;
for (int i = 0; i < this.certificateList.length; ++i)
{
- byte[] encCert = certificateList[i].getEncoded(ASN1Encoding.DER);
- encCerts.addElement(encCert);
- totalLength += encCert.length + 3;
+ byte[] derEncoding = certificateList[i].getEncoded(ASN1Encoding.DER);
+ derEncodings.addElement(derEncoding);
+ totalLength += derEncoding.length + 3;
}
+ TlsUtils.checkUint24(totalLength);
TlsUtils.writeUint24(totalLength, output);
- for (int i = 0; i < encCerts.size(); ++i)
+ for (int i = 0; i < derEncodings.size(); ++i)
{
- byte[] encCert = (byte[])encCerts.elementAt(i);
- TlsUtils.writeOpaque24(encCert, output);
+ byte[] derEncoding = (byte[])derEncodings.elementAt(i);
+ TlsUtils.writeOpaque24(derEncoding, output);
}
}
@@ -114,40 +114,36 @@ public class Certificate
public static Certificate parse(InputStream input)
throws IOException
{
- org.bouncycastle.asn1.x509.Certificate[] certs;
- int left = TlsUtils.readUint24(input);
- if (left == 0)
+ int totalLength = TlsUtils.readUint24(input);
+ if (totalLength == 0)
{
return EMPTY_CHAIN;
}
- Vector tmp = new Vector();
- while (left > 0)
- {
- int size = TlsUtils.readUint24(input);
- left -= 3 + size;
- byte[] buf = TlsUtils.readFully(size, input);
+ byte[] certListData = TlsUtils.readFully(totalLength, input);
- ByteArrayInputStream bis = new ByteArrayInputStream(buf);
- ASN1Primitive asn1 = new ASN1InputStream(bis).readObject();
- TlsProtocol.assertEmpty(bis);
+ ByteArrayInputStream buf = new ByteArrayInputStream(certListData);
- tmp.addElement(org.bouncycastle.asn1.x509.Certificate.getInstance(asn1));
+ Vector certificate_list = new Vector();
+ while (buf.available() > 0)
+ {
+ byte[] derEncoding = TlsUtils.readOpaque24(buf);
+ ASN1Primitive asn1Cert = TlsUtils.readDERObject(derEncoding);
+ certificate_list.addElement(org.bouncycastle.asn1.x509.Certificate.getInstance(asn1Cert));
}
- certs = new org.bouncycastle.asn1.x509.Certificate[tmp.size()];
- for (int i = 0; i < tmp.size(); i++)
+
+ org.bouncycastle.asn1.x509.Certificate[] certificateList = new org.bouncycastle.asn1.x509.Certificate[certificate_list.size()];
+ for (int i = 0; i < certificate_list.size(); i++)
{
- certs[i] = (org.bouncycastle.asn1.x509.Certificate)tmp.elementAt(i);
+ certificateList[i] = (org.bouncycastle.asn1.x509.Certificate)certificate_list.elementAt(i);
}
- return new Certificate(certs);
+ return new Certificate(certificateList);
}
- private org.bouncycastle.asn1.x509.Certificate[] clone(org.bouncycastle.asn1.x509.Certificate[] list)
+ protected org.bouncycastle.asn1.x509.Certificate[] cloneCertificateList()
{
- org.bouncycastle.asn1.x509.Certificate[] rv = new org.bouncycastle.asn1.x509.Certificate[list.length];
-
- System.arraycopy(list, 0, rv, 0, rv.length);
-
- return rv;
+ org.bouncycastle.asn1.x509.Certificate[] result = new org.bouncycastle.asn1.x509.Certificate[certificateList.length];
+ System.arraycopy(certificateList, 0, result, 0, result.length);
+ return result;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateRequest.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateRequest.java
index 00bf950..e9606e3 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateRequest.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateRequest.java
@@ -25,8 +25,9 @@ import org.bouncycastle.asn1.x500.X500Name;
*/
public class CertificateRequest
{
- private short[] certificateTypes;
- private Vector certificateAuthorities;
+ protected short[] certificateTypes;
+ protected Vector supportedSignatureAlgorithms;
+ protected Vector certificateAuthorities;
/*
* TODO RFC 5264 7.4.4 A list of the hash/signature algorithm pairs that the server is able to
@@ -37,9 +38,10 @@ public class CertificateRequest
* @param certificateTypes see {@link ClientCertificateType} for valid constants.
* @param certificateAuthorities a {@link Vector} of {@link X500Name}.
*/
- public CertificateRequest(short[] certificateTypes, Vector certificateAuthorities)
+ public CertificateRequest(short[] certificateTypes, Vector supportedSignatureAlgorithms, Vector certificateAuthorities)
{
this.certificateTypes = certificateTypes;
+ this.supportedSignatureAlgorithms = supportedSignatureAlgorithms;
this.certificateAuthorities = certificateAuthorities;
}
@@ -53,6 +55,14 @@ public class CertificateRequest
}
/**
+ * @return a {@link Vector} of {@link SignatureAndHashAlgorithm} (or null before TLS 1.2).
+ */
+ public Vector getSupportedSignatureAlgorithms()
+ {
+ return supportedSignatureAlgorithms;
+ }
+
+ /**
* @return a {@link Vector} of {@link X500Name}
*/
public Vector getCertificateAuthorities()
@@ -69,15 +79,19 @@ public class CertificateRequest
public void encode(OutputStream output)
throws IOException
{
-
if (certificateTypes == null || certificateTypes.length == 0)
{
- TlsUtils.writeUint8((short)0, output);
+ TlsUtils.writeUint8(0, output);
}
else
{
- TlsUtils.writeUint8((short)certificateTypes.length, output);
- TlsUtils.writeUint8Array(certificateTypes, output);
+ TlsUtils.writeUint8ArrayWithUint8Length(certificateTypes, output);
+ }
+
+ if (supportedSignatureAlgorithms != null)
+ {
+ // TODO Check whether SignatureAlgorithm.anonymous is allowed here
+ TlsUtils.encodeSupportedSignatureAlgorithms(supportedSignatureAlgorithms, false, output);
}
if (certificateAuthorities == null || certificateAuthorities.isEmpty())
@@ -86,22 +100,23 @@ public class CertificateRequest
}
else
{
+ Vector derEncodings = new Vector(certificateAuthorities.size());
- Vector encDNs = new Vector(certificateAuthorities.size());
int totalLength = 0;
for (int i = 0; i < certificateAuthorities.size(); ++i)
{
- X500Name authorityDN = (X500Name)certificateAuthorities.elementAt(i);
- byte[] encDN = authorityDN.getEncoded(ASN1Encoding.DER);
- encDNs.addElement(encDN);
- totalLength += encDN.length;
+ X500Name certificateAuthority = (X500Name)certificateAuthorities.elementAt(i);
+ byte[] derEncoding = certificateAuthority.getEncoded(ASN1Encoding.DER);
+ derEncodings.addElement(derEncoding);
+ totalLength += derEncoding.length;
}
+ TlsUtils.checkUint16(totalLength);
TlsUtils.writeUint16(totalLength, output);
- for (int i = 0; i < encDNs.size(); ++i)
+ for (int i = 0; i < derEncodings.size(); ++i)
{
- byte[] encDN = (byte[])encDNs.elementAt(i);
+ byte[] encDN = (byte[])derEncodings.elementAt(i);
output.write(encDN);
}
}
@@ -109,12 +124,15 @@ public class CertificateRequest
/**
* Parse a {@link CertificateRequest} from an {@link InputStream}.
- *
- * @param input the {@link InputStream} to parse from.
+ *
+ * @param context
+ * the {@link TlsContext} of the current connection.
+ * @param input
+ * the {@link InputStream} to parse from.
* @return a {@link CertificateRequest} object.
* @throws IOException
*/
- public static CertificateRequest parse(InputStream input)
+ public static CertificateRequest parse(TlsContext context, InputStream input)
throws IOException
{
int numTypes = TlsUtils.readUint8(input);
@@ -124,17 +142,23 @@ public class CertificateRequest
certificateTypes[i] = TlsUtils.readUint8(input);
}
- byte[] authorities = TlsUtils.readOpaque16(input);
-
- Vector authorityDNs = new Vector();
+ Vector supportedSignatureAlgorithms = null;
+ if (TlsUtils.isTLSv12(context))
+ {
+ // TODO Check whether SignatureAlgorithm.anonymous is allowed here
+ supportedSignatureAlgorithms = TlsUtils.parseSupportedSignatureAlgorithms(false, input);
+ }
- ByteArrayInputStream bis = new ByteArrayInputStream(authorities);
+ Vector certificateAuthorities = new Vector();
+ byte[] certAuthData = TlsUtils.readOpaque16(input);
+ ByteArrayInputStream bis = new ByteArrayInputStream(certAuthData);
while (bis.available() > 0)
{
- byte[] dnBytes = TlsUtils.readOpaque16(bis);
- authorityDNs.addElement(X500Name.getInstance(ASN1Primitive.fromByteArray(dnBytes)));
+ byte[] derEncoding = TlsUtils.readOpaque16(bis);
+ ASN1Primitive asn1 = TlsUtils.readDERObject(derEncoding);
+ certificateAuthorities.addElement(X500Name.getInstance(asn1));
}
- return new CertificateRequest(certificateTypes, authorityDNs);
+ return new CertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatus.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatus.java
new file mode 100644
index 0000000..34a0284
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatus.java
@@ -0,0 +1,105 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ocsp.OCSPResponse;
+
+public class CertificateStatus
+{
+ protected short statusType;
+ protected Object response;
+
+ public CertificateStatus(short statusType, Object response)
+ {
+ if (!isCorrectType(statusType, response))
+ {
+ throw new IllegalArgumentException("'response' is not an instance of the correct type");
+ }
+
+ this.statusType = statusType;
+ this.response = response;
+ }
+
+ public short getStatusType()
+ {
+ return statusType;
+ }
+
+ public Object getResponse()
+ {
+ return response;
+ }
+
+ public OCSPResponse getOCSPResponse()
+ {
+ if (!isCorrectType(CertificateStatusType.ocsp, response))
+ {
+ throw new IllegalStateException("'response' is not an OCSPResponse");
+ }
+ return (OCSPResponse)response;
+ }
+
+ /**
+ * Encode this {@link CertificateStatus} to an {@link OutputStream}.
+ *
+ * @param output
+ * the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output) throws IOException
+ {
+ TlsUtils.writeUint8(statusType, output);
+
+ switch (statusType)
+ {
+ case CertificateStatusType.ocsp:
+ byte[] derEncoding = ((OCSPResponse) response).getEncoded(ASN1Encoding.DER);
+ TlsUtils.writeOpaque24(derEncoding, output);
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ /**
+ * Parse a {@link CertificateStatus} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link CertificateStatus} object.
+ * @throws IOException
+ */
+ public static CertificateStatus parse(InputStream input) throws IOException
+ {
+ short status_type = TlsUtils.readUint8(input);
+ Object response;
+
+ switch (status_type)
+ {
+ case CertificateStatusType.ocsp:
+ {
+ byte[] derEncoding = TlsUtils.readOpaque24(input);
+ response = OCSPResponse.getInstance(TlsUtils.readDERObject(derEncoding));
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ return new CertificateStatus(status_type, response);
+ }
+
+ protected static boolean isCorrectType(short statusType, Object response)
+ {
+ switch (statusType)
+ {
+ case CertificateStatusType.ocsp:
+ return response instanceof OCSPResponse;
+ default:
+ throw new IllegalArgumentException("'statusType' is an unsupported value");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusRequest.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusRequest.java
new file mode 100644
index 0000000..b947c48
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusRequest.java
@@ -0,0 +1,98 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class CertificateStatusRequest
+{
+ protected short statusType;
+ protected Object request;
+
+ public CertificateStatusRequest(short statusType, Object request)
+ {
+ if (!isCorrectType(statusType, request))
+ {
+ throw new IllegalArgumentException("'request' is not an instance of the correct type");
+ }
+
+ this.statusType = statusType;
+ this.request = request;
+ }
+
+ public short getStatusType()
+ {
+ return statusType;
+ }
+
+ public Object getRequest()
+ {
+ return request;
+ }
+
+ public OCSPStatusRequest getOCSPStatusRequest()
+ {
+ if (!isCorrectType(CertificateStatusType.ocsp, request))
+ {
+ throw new IllegalStateException("'request' is not an OCSPStatusRequest");
+ }
+ return (OCSPStatusRequest)request;
+ }
+
+ /**
+ * Encode this {@link CertificateStatusRequest} to an {@link OutputStream}.
+ *
+ * @param output
+ * the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output) throws IOException
+ {
+ TlsUtils.writeUint8(statusType, output);
+
+ switch (statusType)
+ {
+ case CertificateStatusType.ocsp:
+ ((OCSPStatusRequest) request).encode(output);
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ /**
+ * Parse a {@link CertificateStatusRequest} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link CertificateStatusRequest} object.
+ * @throws IOException
+ */
+ public static CertificateStatusRequest parse(InputStream input) throws IOException
+ {
+ short status_type = TlsUtils.readUint8(input);
+ Object result;
+
+ switch (status_type)
+ {
+ case CertificateStatusType.ocsp:
+ result = OCSPStatusRequest.parse(input);
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ return new CertificateStatusRequest(status_type, result);
+ }
+
+ protected static boolean isCorrectType(short statusType, Object request)
+ {
+ switch (statusType)
+ {
+ case CertificateStatusType.ocsp:
+ return request instanceof OCSPStatusRequest;
+ default:
+ throw new IllegalArgumentException("'statusType' is an unsupported value");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusType.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusType.java
new file mode 100644
index 0000000..bfe8298
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateStatusType.java
@@ -0,0 +1,9 @@
+package org.bouncycastle.crypto.tls;
+
+public class CertificateStatusType
+{
+ /*
+ * RFC 3546 3.6
+ */
+ public static final short ocsp = 1;
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateURL.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateURL.java
new file mode 100644
index 0000000..aab8908
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateURL.java
@@ -0,0 +1,133 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+/*
+ * RFC 3546 3.3
+ */
+public class CertificateURL
+{
+ protected short type;
+ protected Vector urlAndHashList;
+
+ /**
+ * @param type
+ * see {@link CertChainType} for valid constants.
+ * @param urlAndHashList
+ * a {@link Vector} of {@link URLAndHash}.
+ */
+ public CertificateURL(short type, Vector urlAndHashList)
+ {
+ if (!CertChainType.isValid(type))
+ {
+ throw new IllegalArgumentException("'type' is not a valid CertChainType value");
+ }
+ if (urlAndHashList == null || urlAndHashList.isEmpty())
+ {
+ throw new IllegalArgumentException("'urlAndHashList' must have length > 0");
+ }
+
+ this.type = type;
+ this.urlAndHashList = urlAndHashList;
+ }
+
+ /**
+ * @return {@link CertChainType}
+ */
+ public short getType()
+ {
+ return type;
+ }
+
+ /**
+ * @return a {@link Vector} of {@link URLAndHash}
+ */
+ public Vector getURLAndHashList()
+ {
+ return urlAndHashList;
+ }
+
+ /**
+ * Encode this {@link CertificateURL} to an {@link OutputStream}.
+ *
+ * @param output the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output)
+ throws IOException
+ {
+ TlsUtils.writeUint8(this.type, output);
+
+ ListBuffer16 buf = new ListBuffer16();
+ for (int i = 0; i < this.urlAndHashList.size(); ++i)
+ {
+ URLAndHash urlAndHash = (URLAndHash)this.urlAndHashList.elementAt(i);
+ urlAndHash.encode(buf);
+ }
+ buf.encodeTo(output);
+ }
+
+ /**
+ * Parse a {@link CertificateURL} from an {@link InputStream}.
+ *
+ * @param context
+ * the {@link TlsContext} of the current connection.
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link CertificateURL} object.
+ * @throws IOException
+ */
+ public static CertificateURL parse(TlsContext context, InputStream input)
+ throws IOException
+ {
+ short type = TlsUtils.readUint8(input);
+ if (!CertChainType.isValid(type))
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ int totalLength = TlsUtils.readUint16(input);
+ if (totalLength < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ byte[] urlAndHashListData = TlsUtils.readFully(totalLength, input);
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(urlAndHashListData);
+
+ Vector url_and_hash_list = new Vector();
+ while (buf.available() > 0)
+ {
+ URLAndHash url_and_hash = URLAndHash.parse(context, buf);
+ url_and_hash_list.addElement(url_and_hash);
+ }
+
+ return new CertificateURL(type, url_and_hash_list);
+ }
+
+ // TODO Could be more generally useful
+ class ListBuffer16 extends ByteArrayOutputStream
+ {
+ ListBuffer16() throws IOException
+ {
+ // Reserve space for length
+ TlsUtils.writeUint16(0, this);
+ }
+
+ void encodeTo(OutputStream output) throws IOException
+ {
+ // Patch actual length back in
+ int length = count - 2;
+ TlsUtils.checkUint16(length);
+ TlsUtils.writeUint16(length, buf, 0);
+ output.write(buf, 0, count);
+ buf = null;
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ChangeCipherSpec.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ChangeCipherSpec.java
new file mode 100644
index 0000000..a858ded
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ChangeCipherSpec.java
@@ -0,0 +1,6 @@
+package org.bouncycastle.crypto.tls;
+
+public class ChangeCipherSpec
+{
+ public static final short change_cipher_spec = 1;
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CipherSuite.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CipherSuite.java
index 2979cde..c1e7533 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CipherSuite.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CipherSuite.java
@@ -5,7 +5,6 @@ package org.bouncycastle.crypto.tls;
*/
public class CipherSuite
{
-
public static final int TLS_NULL_WITH_NULL_NULL = 0x0000;
public static final int TLS_RSA_WITH_NULL_MD5 = 0x0001;
public static final int TLS_RSA_WITH_NULL_SHA = 0x0002;
@@ -201,7 +200,98 @@ public class CipherSuite
public static final int TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032;
/*
+ * RFC 5487
+ */
+ public static final int TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8;
+ public static final int TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9;
+ public static final int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA;
+ public static final int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB;
+ public static final int TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC;
+ public static final int TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD;
+ public static final int TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE;
+ public static final int TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF;
+ public static final int TLS_PSK_WITH_NULL_SHA256 = 0x00B0;
+ public static final int TLS_PSK_WITH_NULL_SHA384 = 0x00B1;
+ public static final int TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2;
+ public static final int TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3;
+ public static final int TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4;
+ public static final int TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5;
+ public static final int TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6;
+ public static final int TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7;
+ public static final int TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8;
+ public static final int TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9;
+
+ /*
+ * RFC 5489
+ */
+ public static final int TLS_ECDHE_PSK_WITH_RC4_128_SHA = 0xC033;
+ public static final int TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 0xC034;
+ public static final int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035;
+ public static final int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036;
+ public static final int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0xC037;
+ public static final int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 0xC038;
+ public static final int TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039;
+ public static final int TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A;
+ public static final int TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B;
+
+ /*
* RFC 5746
*/
public static final int TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
+
+ /*
+ * RFC 6655
+ */
+ public static final int TLS_RSA_WITH_AES_128_CCM = 0xC09C;
+ public static final int TLS_RSA_WITH_AES_256_CCM = 0xC09D;
+ public static final int TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E;
+ public static final int TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F;
+ public static final int TLS_RSA_WITH_AES_128_CCM_8 = 0xC0A0;
+ public static final int TLS_RSA_WITH_AES_256_CCM_8 = 0xC0A1;
+ public static final int TLS_DHE_RSA_WITH_AES_128_CCM_8 = 0xC0A2;
+ public static final int TLS_DHE_RSA_WITH_AES_256_CCM_8 = 0xC0A3;
+ public static final int TLS_PSK_WITH_AES_128_CCM = 0xC0A4;
+ public static final int TLS_PSK_WITH_AES_256_CCM = 0xC0A5;
+ public static final int TLS_DHE_PSK_WITH_AES_128_CCM = 0xC0A6;
+ public static final int TLS_DHE_PSK_WITH_AES_256_CCM = 0xC0A7;
+ public static final int TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8;
+ public static final int TLS_PSK_WITH_AES_256_CCM_8 = 0xC0A9;
+ public static final int TLS_PSK_DHE_WITH_AES_128_CCM_8 = 0xC0AA;
+ public static final int TLS_PSK_DHE_WITH_AES_256_CCM_8 = 0xC0AB;
+
+ /*
+ * TBD[draft-josefsson-salsa20-tls-02]
+ */
+ static final int TLS_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF00;
+ static final int TLS_RSA_WITH_SALSA20_SHA1 = 0xFF01;
+ static final int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF02;
+ static final int TLS_DHE_RSA_WITH_SALSA20_SHA1 = 0xFF03;
+ static final int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF04;
+ static final int TLS_ECDHE_RSA_WITH_SALSA20_SHA1 = 0xFF05;
+ static final int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF06;
+ static final int TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1 = 0xFF07;
+ static final int TLS_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF08;
+ static final int TLS_PSK_WITH_SALSA20_SHA1 = 0xFF09;
+ static final int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF0A;
+ static final int TLS_DHE_PSK_WITH_SALSA20_SHA1 = 0xFF0B;
+ static final int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF0C;
+ static final int TLS_RSA_PSK_WITH_SALSA20_SHA1 = 0xFF0D;
+ static final int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF0E;
+ static final int TLS_ECDHE_PSK_WITH_SALSA20_SHA1 = 0xFF0F;
+ static final int TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF10;
+ static final int TLS_RSA_WITH_SALSA20_UMAC96 = 0xFF11;
+ static final int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF12;
+ static final int TLS_DHE_RSA_WITH_SALSA20_UMAC96 = 0xFF13;
+ static final int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF14;
+ static final int TLS_ECDHE_RSA_WITH_SALSA20_UMAC96 = 0xFF15;
+ static final int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF16;
+ static final int TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96 = 0xFF17;
+ static final int TLS_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF18;
+ static final int TLS_PSK_WITH_SALSA20_UMAC96 = 0xFF19;
+ static final int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF1A;
+ static final int TLS_DHE_PSK_WITH_SALSA20_UMAC96 = 0xFF1B;
+ static final int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF1C;
+ static final int TLS_RSA_PSK_WITH_SALSA20_UMAC96 = 0xFF1D;
+ static final int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF1E;
+ static final int TLS_ECDHE_PSK_WITH_SALSA20_UMAC96 = 0xFF1F;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CombinedHash.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CombinedHash.java
index 1a48491..43b73bf 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CombinedHash.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CombinedHash.java
@@ -8,7 +8,6 @@ import org.bouncycastle.crypto.Digest;
class CombinedHash
implements TlsHandshakeHash
{
-
protected TlsContext context;
protected Digest md5;
protected Digest sha1;
@@ -31,16 +30,35 @@ class CombinedHash
this.context = context;
}
- public TlsHandshakeHash commit()
+ public TlsHandshakeHash notifyPRFDetermined()
{
return this;
}
- public TlsHandshakeHash fork()
+ public void trackHashAlgorithm(short hashAlgorithm)
+ {
+ throw new IllegalStateException("CombinedHash only supports calculating the legacy PRF for handshake hash");
+ }
+
+ public void sealHashAlgorithms()
+ {
+ }
+
+ public TlsHandshakeHash stopTracking()
{
return new CombinedHash(this);
}
+ public Digest forkPRFHash()
+ {
+ return new CombinedHash(this);
+ }
+
+ public byte[] getFinalHash(short hashAlgorithm)
+ {
+ throw new IllegalStateException("CombinedHash doesn't support multiple hashes");
+ }
+
/**
* @see org.bouncycastle.crypto.Digest#getAlgorithmName()
*/
@@ -80,7 +98,7 @@ class CombinedHash
*/
public int doFinal(byte[] out, int outOff)
{
- if (context != null && context.getServerVersion().isSSL())
+ if (context != null && TlsUtils.isSSL(context))
{
ssl3Complete(md5, SSL3Mac.IPAD, SSL3Mac.OPAD, 48);
ssl3Complete(sha1, SSL3Mac.IPAD, SSL3Mac.OPAD, 40);
@@ -102,15 +120,15 @@ class CombinedHash
protected void ssl3Complete(Digest d, byte[] ipad, byte[] opad, int padLength)
{
- byte[] secret = context.getSecurityParameters().masterSecret;
+ byte[] master_secret = context.getSecurityParameters().masterSecret;
- d.update(secret, 0, secret.length);
+ d.update(master_secret, 0, master_secret.length);
d.update(ipad, 0, padLength);
byte[] tmp = new byte[d.getDigestSize()];
d.doFinal(tmp, 0);
- d.update(secret, 0, secret.length);
+ d.update(master_secret, 0, master_secret.length);
d.update(opad, 0, padLength);
d.update(tmp, 0, tmp.length);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ContentType.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ContentType.java
index d814eac..65ed9b6 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ContentType.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ContentType.java
@@ -9,4 +9,5 @@ public class ContentType
public static final short alert = 21;
public static final short handshake = 22;
public static final short application_data = 23;
+ public static final short heartbeat = 24;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java
index 8ccacfb..b3b1abe 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java
@@ -13,7 +13,6 @@ import org.bouncycastle.util.Arrays;
public class DTLSClientProtocol
extends DTLSProtocol
{
-
public DTLSClientProtocol(SecureRandom secureRandom)
{
super(secureRandom);
@@ -22,7 +21,6 @@ public class DTLSClientProtocol
public DTLSTransport connect(TlsClient client, DatagramTransport transport)
throws IOException
{
-
if (client == null)
{
throw new IllegalArgumentException("'client' cannot be null");
@@ -43,6 +41,17 @@ public class DTLSClientProtocol
DTLSRecordLayer recordLayer = new DTLSRecordLayer(transport, state.clientContext, client, ContentType.handshake);
+ TlsSession sessionToResume = state.client.getSessionToResume();
+ if (sessionToResume != null)
+ {
+ SessionParameters sessionParameters = sessionToResume.exportSessionParameters();
+ if (sessionParameters != null)
+ {
+ state.tlsSession = sessionToResume;
+ state.sessionParameters = sessionParameters;
+ }
+ }
+
try
{
return clientHandshake(state, recordLayer);
@@ -67,7 +76,6 @@ public class DTLSClientProtocol
protected DTLSTransport clientHandshake(ClientHandshakeState state, DTLSRecordLayer recordLayer)
throws IOException
{
-
SecurityParameters securityParameters = state.clientContext.getSecurityParameters();
DTLSReliableHandshake handshake = new DTLSReliableHandshake(state.clientContext, recordLayer);
@@ -76,23 +84,23 @@ public class DTLSClientProtocol
DTLSReliableHandshake.Message serverMessage = handshake.receiveMessage();
+ while (serverMessage.getType() == HandshakeType.hello_verify_request)
{
- // NOTE: After receiving a record from the server, we discover the record layer version
- ProtocolVersion server_version = recordLayer.getDiscoveredPeerVersion();
+ ProtocolVersion recordLayerVersion = recordLayer.resetDiscoveredPeerVersion();
ProtocolVersion client_version = state.clientContext.getClientVersion();
- if (!server_version.isEqualOrEarlierVersionOf(client_version))
+ /*
+ * RFC 6347 4.2.1 DTLS 1.2 server implementations SHOULD use DTLS version 1.0 regardless of
+ * the version of TLS that is expected to be negotiated. DTLS 1.2 and 1.0 clients MUST use
+ * the version solely to indicate packet formatting (which is the same in both DTLS 1.2 and
+ * 1.0) and not as part of version negotiation.
+ */
+ if (!recordLayerVersion.isEqualOrEarlierVersionOf(client_version))
{
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
- state.clientContext.setServerVersion(server_version);
- state.client.notifyServerVersion(server_version);
- }
-
- while (serverMessage.getType() == HandshakeType.hello_verify_request)
- {
- byte[] cookie = parseHelloVerifyRequest(state.clientContext, serverMessage.getBody());
+ byte[] cookie = processHelloVerifyRequest(state, serverMessage.getBody());
byte[] patched = patchClientHelloWithCookie(clientHelloBody, cookie);
handshake.resetHandshakeMessagesDigest();
@@ -103,16 +111,24 @@ public class DTLSClientProtocol
if (serverMessage.getType() == HandshakeType.server_hello)
{
+ reportServerVersion(state, recordLayer.getDiscoveredPeerVersion());
+
processServerHello(state, serverMessage.getBody());
- serverMessage = handshake.receiveMessage();
}
else
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- securityParameters.prfAlgorithm = TlsProtocol.getPRFAlgorithm(state.selectedCipherSuite);
+ if (state.maxFragmentLength >= 0)
+ {
+ int plainTextLimit = 1 << (8 + state.maxFragmentLength);
+ recordLayer.setPlaintextLimit(plainTextLimit);
+ }
+
+ securityParameters.cipherSuite = state.selectedCipherSuite;
securityParameters.compressionAlgorithm = state.selectedCompressionMethod;
+ securityParameters.prfAlgorithm = TlsProtocol.getPRFAlgorithm(state.clientContext, state.selectedCipherSuite);
/*
* RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length has
@@ -122,6 +138,48 @@ public class DTLSClientProtocol
handshake.notifyHelloComplete();
+ boolean resumedSession = state.selectedSessionID.length > 0 && state.tlsSession != null
+ && Arrays.areEqual(state.selectedSessionID, state.tlsSession.getSessionID());
+
+ if (resumedSession)
+ {
+ if (securityParameters.getCipherSuite() != state.sessionParameters.getCipherSuite()
+ || securityParameters.getCompressionAlgorithm() != state.sessionParameters.getCompressionAlgorithm())
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ securityParameters.masterSecret = Arrays.clone(state.sessionParameters.getMasterSecret());
+ recordLayer.initPendingEpoch(state.client.getCipher());
+
+ // NOTE: Calculated exclusive of the actual Finished message from the server
+ byte[] expectedServerVerifyData = TlsUtils.calculateVerifyData(state.clientContext, ExporterLabel.server_finished,
+ TlsProtocol.getCurrentPRFHash(state.clientContext, handshake.getHandshakeHash(), null));
+ processFinished(handshake.receiveMessageBody(HandshakeType.finished), expectedServerVerifyData);
+
+ // NOTE: Calculated exclusive of the Finished message itself
+ byte[] clientVerifyData = TlsUtils.calculateVerifyData(state.clientContext, ExporterLabel.client_finished,
+ TlsProtocol.getCurrentPRFHash(state.clientContext, handshake.getHandshakeHash(), null));
+ handshake.sendMessage(HandshakeType.finished, clientVerifyData);
+
+ handshake.finish();
+
+ state.clientContext.setResumableSession(state.tlsSession);
+
+ state.client.notifyHandshakeComplete();
+
+ return new DTLSTransport(recordLayer);
+ }
+
+ invalidateSession(state);
+
+ if (state.selectedSessionID.length > 0)
+ {
+ state.tlsSession = new TlsSessionImpl(state.selectedSessionID, null);
+ }
+
+ serverMessage = handshake.receiveMessage();
+
if (serverMessage.getType() == HandshakeType.supplemental_data)
{
processServerSupplementalData(state, serverMessage.getBody());
@@ -135,9 +193,11 @@ public class DTLSClientProtocol
state.keyExchange = state.client.getKeyExchange();
state.keyExchange.init(state.clientContext);
+ Certificate serverCertificate = null;
+
if (serverMessage.getType() == HandshakeType.certificate)
{
- processServerCertificate(state, serverMessage.getBody());
+ serverCertificate = processServerCertificate(state, serverMessage.getBody());
serverMessage = handshake.receiveMessage();
}
else
@@ -146,6 +206,22 @@ public class DTLSClientProtocol
state.keyExchange.skipServerCredentials();
}
+ // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus
+ if (serverCertificate == null || serverCertificate.isEmpty())
+ {
+ state.allowCertificateStatus = false;
+ }
+
+ if (serverMessage.getType() == HandshakeType.certificate_status)
+ {
+ processCertificateStatus(state, serverMessage.getBody());
+ serverMessage = handshake.receiveMessage();
+ }
+ else
+ {
+ // Okay, CertificateStatus is optional
+ }
+
if (serverMessage.getType() == HandshakeType.server_key_exchange)
{
processServerKeyExchange(state, serverMessage.getBody());
@@ -160,6 +236,14 @@ public class DTLSClientProtocol
if (serverMessage.getType() == HandshakeType.certificate_request)
{
processCertificateRequest(state, serverMessage.getBody());
+
+ /*
+ * TODO Give the client a chance to immediately select the CertificateVerify hash
+ * algorithm here to avoid tracking the other hash algorithms unnecessarily?
+ */
+ TlsUtils.trackHashAlgorithms(handshake.getHandshakeHash(),
+ state.certificateRequest.getSupportedSignatureAlgorithms());
+
serverMessage = handshake.receiveMessage();
}
else
@@ -179,6 +263,8 @@ public class DTLSClientProtocol
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
+ handshake.getHandshakeHash().sealHashAlgorithms();
+
Vector clientSupplementalData = state.client.getClientSupplementalData();
if (clientSupplementalData != null)
{
@@ -223,25 +309,45 @@ public class DTLSClientProtocol
handshake.sendMessage(HandshakeType.client_key_exchange, clientKeyExchangeBody);
TlsProtocol.establishMasterSecret(state.clientContext, state.keyExchange);
+ recordLayer.initPendingEpoch(state.client.getCipher());
+
+ TlsHandshakeHash prepareFinishHash = handshake.prepareToFinish();
- if (state.clientCredentials instanceof TlsSignerCredentials)
+ if (state.clientCredentials != null && state.clientCredentials instanceof TlsSignerCredentials)
{
+ TlsSignerCredentials signerCredentials = (TlsSignerCredentials)state.clientCredentials;
+
/*
- * TODO RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm prepended
- * from TLS 1.2
+ * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
*/
- TlsSignerCredentials signerCredentials = (TlsSignerCredentials)state.clientCredentials;
- byte[] md5andsha1 = handshake.getCurrentHash();
- byte[] signature = signerCredentials.generateCertificateSignature(md5andsha1);
- byte[] certificateVerifyBody = generateCertificateVerify(state, signature);
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm;
+ byte[] hash;
+
+ if (TlsUtils.isTLSv12(state.clientContext))
+ {
+ signatureAndHashAlgorithm = signerCredentials.getSignatureAndHashAlgorithm();
+ if (signatureAndHashAlgorithm == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ hash = prepareFinishHash.getFinalHash(signatureAndHashAlgorithm.getHash());
+ }
+ else
+ {
+ signatureAndHashAlgorithm = null;
+ hash = TlsProtocol.getCurrentPRFHash(state.clientContext, prepareFinishHash, null);
+ }
+
+ byte[] signature = signerCredentials.generateCertificateSignature(hash);
+ DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature);
+ byte[] certificateVerifyBody = generateCertificateVerify(state, certificateVerify);
handshake.sendMessage(HandshakeType.certificate_verify, certificateVerifyBody);
}
- recordLayer.initPendingEpoch(state.client.getCipher());
-
// NOTE: Calculated exclusive of the Finished message itself
- byte[] clientVerifyData = TlsUtils.calculateVerifyData(state.clientContext, "client finished",
- handshake.getCurrentHash());
+ byte[] clientVerifyData = TlsUtils.calculateVerifyData(state.clientContext, ExporterLabel.client_finished,
+ TlsProtocol.getCurrentPRFHash(state.clientContext, handshake.getHandshakeHash(), null));
handshake.sendMessage(HandshakeType.finished, clientVerifyData);
if (state.expectSessionTicket)
@@ -258,39 +364,42 @@ public class DTLSClientProtocol
}
// NOTE: Calculated exclusive of the actual Finished message from the server
- byte[] expectedServerVerifyData = TlsUtils.calculateVerifyData(state.clientContext, "server finished",
- handshake.getCurrentHash());
- serverMessage = handshake.receiveMessage();
+ byte[] expectedServerVerifyData = TlsUtils.calculateVerifyData(state.clientContext, ExporterLabel.server_finished,
+ TlsProtocol.getCurrentPRFHash(state.clientContext, handshake.getHandshakeHash(), null));
+ processFinished(handshake.receiveMessageBody(HandshakeType.finished), expectedServerVerifyData);
- if (serverMessage.getType() == HandshakeType.finished)
- {
- processFinished(serverMessage.getBody(), expectedServerVerifyData);
- }
- else
+ handshake.finish();
+
+ if (state.tlsSession != null)
{
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
+ state.sessionParameters = new SessionParameters.Builder()
+ .setCipherSuite(securityParameters.cipherSuite)
+ .setCompressionAlgorithm(securityParameters.compressionAlgorithm)
+ .setMasterSecret(securityParameters.masterSecret)
+ .setPeerCertificate(serverCertificate)
+ .build();
- handshake.finish();
+ state.tlsSession = TlsUtils.importSession(state.tlsSession.getSessionID(), state.sessionParameters);
+
+ state.clientContext.setResumableSession(state.tlsSession);
+ }
state.client.notifyHandshakeComplete();
return new DTLSTransport(recordLayer);
}
- protected byte[] generateCertificateVerify(ClientHandshakeState state, byte[] signature)
+ protected byte[] generateCertificateVerify(ClientHandshakeState state, DigitallySigned certificateVerify)
throws IOException
{
-
ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeOpaque16(signature, buf);
+ certificateVerify.encode(buf);
return buf.toByteArray();
}
protected byte[] generateClientHello(ClientHandshakeState state, TlsClient client)
throws IOException
{
-
ByteArrayOutputStream buf = new ByteArrayOutputStream();
ProtocolVersion client_version = client.getClientVersion();
@@ -304,8 +413,17 @@ public class DTLSClientProtocol
buf.write(state.clientContext.getSecurityParameters().getClientRandom());
- // Session id
- TlsUtils.writeOpaque8(TlsUtils.EMPTY_BYTES, buf);
+ // Session ID
+ byte[] session_id = TlsUtils.EMPTY_BYTES;
+ if (state.tlsSession != null)
+ {
+ session_id = state.tlsSession.getSessionID();
+ if (session_id == null || session_id.length > 32)
+ {
+ session_id = TlsUtils.EMPTY_BYTES;
+ }
+ }
+ TlsUtils.writeOpaque8(session_id, buf);
// Cookie
TlsUtils.writeOpaque8(TlsUtils.EMPTY_BYTES, buf);
@@ -325,32 +443,26 @@ public class DTLSClientProtocol
* or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
* ClientHello. Including both is NOT RECOMMENDED.
*/
- boolean noRenegExt = state.clientExtensions == null
- || state.clientExtensions.get(TlsProtocol.EXT_RenegotiationInfo) == null;
+ byte[] renegExtData = TlsUtils.getExtensionData(state.clientExtensions, TlsProtocol.EXT_RenegotiationInfo);
+ boolean noRenegExt = (null == renegExtData);
- int count = state.offeredCipherSuites.length;
- if (noRenegExt)
- {
- // Note: 1 extra slot for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- ++count;
- }
+ boolean noSCSV = !Arrays.contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
- TlsUtils.writeUint16(2 * count, buf);
- TlsUtils.writeUint16Array(state.offeredCipherSuites, buf);
-
- if (noRenegExt)
+ if (noRenegExt && noSCSV)
{
- TlsUtils.writeUint16(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV, buf);
+ // TODO Consider whether to default to a client extension instead
+ state.offeredCipherSuites = Arrays.append(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
}
+
+ TlsUtils.writeUint16ArrayWithUint16Length(state.offeredCipherSuites, buf);
}
// TODO Add support for compression
// Compression methods
// state.offeredCompressionMethods = client.getCompressionMethods();
- state.offeredCompressionMethods = new short[]{CompressionMethod._null};
+ state.offeredCompressionMethods = new short[]{ CompressionMethod._null };
- TlsUtils.writeUint8((short)state.offeredCompressionMethods.length, buf);
- TlsUtils.writeUint8Array(state.offeredCompressionMethods, buf);
+ TlsUtils.writeUint8ArrayWithUint8Length(state.offeredCompressionMethods, buf);
// Extensions
if (state.clientExtensions != null)
@@ -364,16 +476,29 @@ public class DTLSClientProtocol
protected byte[] generateClientKeyExchange(ClientHandshakeState state)
throws IOException
{
-
ByteArrayOutputStream buf = new ByteArrayOutputStream();
state.keyExchange.generateClientKeyExchange(buf);
return buf.toByteArray();
}
+ protected void invalidateSession(ClientHandshakeState state)
+ {
+ if (state.sessionParameters != null)
+ {
+ state.sessionParameters.clear();
+ state.sessionParameters = null;
+ }
+
+ if (state.tlsSession != null)
+ {
+ state.tlsSession.invalidate();
+ state.tlsSession = null;
+ }
+ }
+
protected void processCertificateRequest(ClientHandshakeState state, byte[] body)
throws IOException
{
-
if (state.authentication == null)
{
/*
@@ -385,19 +510,69 @@ public class DTLSClientProtocol
ByteArrayInputStream buf = new ByteArrayInputStream(body);
- state.certificateRequest = CertificateRequest.parse(buf);
+ state.certificateRequest = CertificateRequest.parse(state.clientContext, buf);
TlsProtocol.assertEmpty(buf);
state.keyExchange.validateCertificateRequest(state.certificateRequest);
}
- protected void processNewSessionTicket(ClientHandshakeState state, byte[] body)
+ protected void processCertificateStatus(ClientHandshakeState state, byte[] body)
throws IOException
{
+ if (!state.allowCertificateStatus)
+ {
+ /*
+ * RFC 3546 3.6. If a server returns a "CertificateStatus" message, then the
+ * server MUST have included an extension of type "status_request" with empty
+ * "extension_data" in the extended server hello..
+ */
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
ByteArrayInputStream buf = new ByteArrayInputStream(body);
+ state.certificateStatus = CertificateStatus.parse(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ // TODO[RFC 3546] Figure out how to provide this to the client/authentication.
+ }
+
+ protected byte[] processHelloVerifyRequest(ClientHandshakeState state, byte[] body)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+
+ ProtocolVersion server_version = TlsUtils.readVersion(buf);
+ byte[] cookie = TlsUtils.readOpaque8(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ // TODO Seems this behaviour is not yet in line with OpenSSL for DTLS 1.2
+// reportServerVersion(state, server_version);
+ if (!server_version.isEqualOrEarlierVersionOf(state.clientContext.getClientVersion()))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ /*
+ * RFC 6347 This specification increases the cookie size limit to 255 bytes for greater
+ * future flexibility. The limit remains 32 for previous versions of DTLS.
+ */
+ if (!ProtocolVersion.DTLSv12.isEqualOrEarlierVersionOf(server_version) && cookie.length > 32)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return cookie;
+ }
+
+ protected void processNewSessionTicket(ClientHandshakeState state, byte[] body)
+ throws IOException
+ {
+ ByteArrayInputStream buf = new ByteArrayInputStream(body);
+
NewSessionTicket newSessionTicket = NewSessionTicket.parse(buf);
TlsProtocol.assertEmpty(buf);
@@ -405,10 +580,9 @@ public class DTLSClientProtocol
state.client.notifyNewSessionTicket(newSessionTicket);
}
- protected void processServerCertificate(ClientHandshakeState state, byte[] body)
+ protected Certificate processServerCertificate(ClientHandshakeState state, byte[] body)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(body);
Certificate serverCertificate = Certificate.parse(buf);
@@ -418,34 +592,31 @@ public class DTLSClientProtocol
state.keyExchange.processServerCertificate(serverCertificate);
state.authentication = state.client.getAuthentication();
state.authentication.notifyServerCertificate(serverCertificate);
+
+ return serverCertificate;
}
protected void processServerHello(ClientHandshakeState state, byte[] body)
throws IOException
{
-
SecurityParameters securityParameters = state.clientContext.getSecurityParameters();
ByteArrayInputStream buf = new ByteArrayInputStream(body);
- // TODO Read RFCs for guidance on the expected record layer version number
ProtocolVersion server_version = TlsUtils.readVersion(buf);
- if (!server_version.equals(state.clientContext.getServerVersion()))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
+ reportServerVersion(state, server_version);
securityParameters.serverRandom = TlsUtils.readFully(32, buf);
- byte[] sessionID = TlsUtils.readOpaque8(buf);
- if (sessionID.length > 32)
+ state.selectedSessionID = TlsUtils.readOpaque8(buf);
+ if (state.selectedSessionID.length > 32)
{
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
- state.client.notifySessionID(sessionID);
+ state.client.notifySessionID(state.selectedSessionID);
state.selectedCipherSuite = TlsUtils.readUint16(buf);
- if (!TlsProtocol.arrayContains(state.offeredCipherSuites, state.selectedCipherSuite)
+ if (!Arrays.contains(state.offeredCipherSuites, state.selectedCipherSuite)
|| state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
|| state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
{
@@ -457,7 +628,7 @@ public class DTLSClientProtocol
state.client.notifySelectedCipherSuite(state.selectedCipherSuite);
state.selectedCompressionMethod = TlsUtils.readUint8(buf);
- if (!TlsProtocol.arrayContains(state.offeredCompressionMethods, state.selectedCompressionMethod))
+ if (!Arrays.contains(state.offeredCompressionMethods, state.selectedCompressionMethod))
{
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
@@ -502,7 +673,7 @@ public class DTLSClientProtocol
* MUST continue to comply with Section 7.4.1.4 for all other extensions.
*/
if (!extType.equals(TlsProtocol.EXT_RenegotiationInfo)
- && (state.clientExtensions == null || state.clientExtensions.get(extType) == null))
+ && null == TlsUtils.getExtensionData(state.clientExtensions, extType))
{
/*
* RFC 3546 2.3 Note that for all extension types (including those defined in
@@ -524,8 +695,8 @@ public class DTLSClientProtocol
* When a ServerHello is received, the client MUST check if it includes the
* "renegotiation_info" extension:
*/
- byte[] renegExtValue = (byte[])serverExtensions.get(TlsProtocol.EXT_RenegotiationInfo);
- if (renegExtValue != null)
+ byte[] renegExtData = (byte[])serverExtensions.get(TlsProtocol.EXT_RenegotiationInfo);
+ if (renegExtData != null)
{
/*
* If the extension is present, set the secure_renegotiation flag to TRUE. The
@@ -535,7 +706,7 @@ public class DTLSClientProtocol
*/
state.secure_renegotiation = true;
- if (!Arrays.constantTimeAreEqual(renegExtValue,
+ if (!Arrays.constantTimeAreEqual(renegExtData,
TlsProtocol.createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
{
throw new TlsFatalAlert(AlertDescription.handshake_failure);
@@ -543,7 +714,16 @@ public class DTLSClientProtocol
}
}
- state.expectSessionTicket = serverExtensions.containsKey(TlsProtocol.EXT_SessionTicket);
+ state.maxFragmentLength = evaluateMaxFragmentLengthExtension(state.clientExtensions, serverExtensions,
+ AlertDescription.illegal_parameter);
+
+ securityParameters.truncatedHMac = TlsExtensionsUtils.hasTruncatedHMacExtension(serverExtensions);
+
+ state.allowCertificateStatus = TlsUtils.hasExpectedEmptyExtensionData(serverExtensions,
+ TlsExtensionsUtils.EXT_status_request, AlertDescription.illegal_parameter);
+
+ state.expectSessionTicket = TlsUtils.hasExpectedEmptyExtensionData(serverExtensions,
+ TlsProtocol.EXT_SessionTicket, AlertDescription.illegal_parameter);
}
state.client.notifySecureRenegotiation(state.secure_renegotiation);
@@ -557,7 +737,6 @@ public class DTLSClientProtocol
protected void processServerKeyExchange(ClientHandshakeState state, byte[] body)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(body);
state.keyExchange.processServerKeyExchange(buf);
@@ -568,37 +747,30 @@ public class DTLSClientProtocol
protected void processServerSupplementalData(ClientHandshakeState state, byte[] body)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(body);
Vector serverSupplementalData = TlsProtocol.readSupplementalDataMessage(buf);
state.client.processServerSupplementalData(serverSupplementalData);
}
- protected static byte[] parseHelloVerifyRequest(TlsContext context, byte[] body)
+ protected void reportServerVersion(ClientHandshakeState state, ProtocolVersion server_version)
throws IOException
{
-
- ByteArrayInputStream buf = new ByteArrayInputStream(body);
-
- ProtocolVersion server_version = TlsUtils.readVersion(buf);
- if (!server_version.equals(context.getServerVersion()))
+ TlsClientContextImpl clientContext = state.clientContext;
+ ProtocolVersion currentServerVersion = clientContext.getServerVersion();
+ if (null == currentServerVersion)
+ {
+ clientContext.setServerVersion(server_version);
+ state.client.notifyServerVersion(server_version);
+ }
+ else if (!currentServerVersion.equals(server_version))
{
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
-
- byte[] cookie = TlsUtils.readOpaque8(buf);
-
- // TODO RFC 4347 has the cookie length restricted to 32, but not in RFC 6347
-
- TlsProtocol.assertEmpty(buf);
-
- return cookie;
}
protected static byte[] patchClientHelloWithCookie(byte[] clientHelloBody, byte[] cookie)
throws IOException
{
-
int sessionIDPos = 34;
int sessionIDLength = TlsUtils.readUint8(clientHelloBody, sessionIDPos);
@@ -607,7 +779,8 @@ public class DTLSClientProtocol
byte[] patched = new byte[clientHelloBody.length + cookie.length];
System.arraycopy(clientHelloBody, 0, patched, 0, cookieLengthPos);
- TlsUtils.writeUint8((short)cookie.length, patched, cookieLengthPos);
+ TlsUtils.checkUint8(cookie.length);
+ TlsUtils.writeUint8(cookie.length, patched, cookieLengthPos);
System.arraycopy(cookie, 0, patched, cookiePos, cookie.length);
System.arraycopy(clientHelloBody, cookiePos, patched, cookiePos + cookie.length, clientHelloBody.length
- cookiePos);
@@ -619,15 +792,22 @@ public class DTLSClientProtocol
{
TlsClient client = null;
TlsClientContextImpl clientContext = null;
+ TlsSession tlsSession = null;
+ SessionParameters sessionParameters = null;
+ SessionParameters.Builder sessionParametersBuilder = null;
int[] offeredCipherSuites = null;
short[] offeredCompressionMethods = null;
Hashtable clientExtensions = null;
+ byte[] selectedSessionID = null;
int selectedCipherSuite = -1;
short selectedCompressionMethod = -1;
boolean secure_renegotiation = false;
+ short maxFragmentLength = -1;
+ boolean allowCertificateStatus = false;
boolean expectSessionTicket = false;
TlsKeyExchange keyExchange = null;
TlsAuthentication authentication = null;
+ CertificateStatus certificateStatus = null;
CertificateRequest certificateRequest = null;
TlsCredentials clientCredentials = null;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSProtocol.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSProtocol.java
index 2789b22..e27580c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSProtocol.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSProtocol.java
@@ -4,18 +4,17 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
+import java.util.Hashtable;
import java.util.Vector;
import org.bouncycastle.util.Arrays;
public abstract class DTLSProtocol
{
-
protected final SecureRandom secureRandom;
protected DTLSProtocol(SecureRandom secureRandom)
{
-
if (secureRandom == null)
{
throw new IllegalArgumentException("'secureRandom' cannot be null");
@@ -27,7 +26,6 @@ public abstract class DTLSProtocol
protected void processFinished(byte[] body, byte[] expected_verify_data)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(body);
byte[] verify_data = TlsUtils.readFully(expected_verify_data.length, buf);
@@ -40,10 +38,20 @@ public abstract class DTLSProtocol
}
}
+ protected static short evaluateMaxFragmentLengthExtension(Hashtable clientExtensions, Hashtable serverExtensions,
+ short alertDescription) throws IOException
+ {
+ short maxFragmentLength = TlsExtensionsUtils.getMaxFragmentLengthExtension(serverExtensions);
+ if (maxFragmentLength >= 0 && maxFragmentLength != TlsExtensionsUtils.getMaxFragmentLengthExtension(clientExtensions))
+ {
+ throw new TlsFatalAlert(alertDescription);
+ }
+ return maxFragmentLength;
+ }
+
protected static byte[] generateCertificate(Certificate certificate)
throws IOException
{
-
ByteArrayOutputStream buf = new ByteArrayOutputStream();
certificate.encode(buf);
return buf.toByteArray();
@@ -52,7 +60,6 @@ public abstract class DTLSProtocol
protected static byte[] generateSupplementalData(Vector supplementalData)
throws IOException
{
-
ByteArrayOutputStream buf = new ByteArrayOutputStream();
TlsProtocol.writeSupplementalData(buf, supplementalData);
return buf.toByteArray();
@@ -61,7 +68,6 @@ public abstract class DTLSProtocol
protected static void validateSelectedCipherSuite(int selectedCipherSuite, short alertDescription)
throws IOException
{
-
switch (selectedCipherSuite)
{
case CipherSuite.TLS_RSA_EXPORT_WITH_RC4_40_MD5:
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSRecordLayer.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSRecordLayer.java
index 3fde01a..cba13d5 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSRecordLayer.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSRecordLayer.java
@@ -5,7 +5,6 @@ import java.io.IOException;
class DTLSRecordLayer
implements DatagramTransport
{
-
private static final int RECORD_HEADER_LENGTH = 13;
private static final int MAX_FRAGMENT_LENGTH = 1 << 14;
private static final long TCP_MSL = 1000L * 60 * 2;
@@ -21,6 +20,7 @@ class DTLSRecordLayer
private volatile boolean failed = false;
private volatile ProtocolVersion discoveredPeerVersion = null;
private volatile boolean inHandshake;
+ private volatile int plaintextLimit;
private DTLSEpoch currentEpoch, pendingEpoch;
private DTLSEpoch readEpoch, writeEpoch;
@@ -40,6 +40,13 @@ class DTLSRecordLayer
this.pendingEpoch = null;
this.readEpoch = currentEpoch;
this.writeEpoch = currentEpoch;
+
+ setPlaintextLimit(MAX_FRAGMENT_LENGTH);
+ }
+
+ void setPlaintextLimit(int plaintextLimit)
+ {
+ this.plaintextLimit = plaintextLimit;
}
ProtocolVersion getDiscoveredPeerVersion()
@@ -47,6 +54,13 @@ class DTLSRecordLayer
return discoveredPeerVersion;
}
+ ProtocolVersion resetDiscoveredPeerVersion()
+ {
+ ProtocolVersion result = discoveredPeerVersion;
+ discoveredPeerVersion = null;
+ return result;
+ }
+
void initPendingEpoch(TlsCipher pendingCipher)
{
if (pendingEpoch != null)
@@ -99,26 +113,24 @@ class DTLSRecordLayer
public int getReceiveLimit()
throws IOException
{
- return Math.min(MAX_FRAGMENT_LENGTH,
+ return Math.min(this.plaintextLimit,
readEpoch.getCipher().getPlaintextLimit(transport.getReceiveLimit() - RECORD_HEADER_LENGTH));
}
public int getSendLimit()
throws IOException
{
- return Math.min(MAX_FRAGMENT_LENGTH,
+ return Math.min(this.plaintextLimit,
writeEpoch.getCipher().getPlaintextLimit(transport.getSendLimit() - RECORD_HEADER_LENGTH));
}
public int receive(byte[] buf, int off, int len, int waitMillis)
throws IOException
{
-
byte[] record = null;
- for (; ; )
+ for (;;)
{
-
int receiveLimit = Math.min(len, getReceiveLimit()) + RECORD_HEADER_LENGTH;
if (record == null || record.length < receiveLimit)
{
@@ -157,6 +169,7 @@ class DTLSRecordLayer
case ContentType.application_data:
case ContentType.change_cipher_spec:
case ContentType.handshake:
+ case ContentType.heartbeat:
break;
default:
// TODO Exception?
@@ -199,6 +212,11 @@ class DTLSRecordLayer
recordEpoch.getReplayWindow().reportAuthenticated(seq);
+ if (plaintext.length > this.plaintextLimit)
+ {
+ continue;
+ }
+
if (discoveredPeerVersion == null)
{
discoveredPeerVersion = version;
@@ -208,7 +226,6 @@ class DTLSRecordLayer
{
case ContentType.alert:
{
-
if (plaintext.length == 2)
{
short alertLevel = plaintext[0];
@@ -249,14 +266,18 @@ class DTLSRecordLayer
{
// Implicitly receive change_cipher_spec and change to pending cipher state
- if (plaintext.length != 1 || plaintext[0] != 1)
+ for (int i = 0; i < plaintext.length; ++i)
{
- continue;
- }
+ short message = TlsUtils.readUint8(plaintext, i);
+ if (message != ChangeCipherSpec.change_cipher_spec)
+ {
+ continue;
+ }
- if (pendingEpoch != null)
- {
- readEpoch = pendingEpoch;
+ if (pendingEpoch != null)
+ {
+ readEpoch = pendingEpoch;
+ }
}
continue;
@@ -273,6 +294,12 @@ class DTLSRecordLayer
// TODO Consider support for HelloRequest
continue;
}
+ break;
+ }
+ case ContentType.heartbeat:
+ {
+ // TODO[RFC 6520]
+ continue;
}
}
@@ -300,18 +327,15 @@ class DTLSRecordLayer
public void send(byte[] buf, int off, int len)
throws IOException
{
-
short contentType = ContentType.application_data;
if (this.inHandshake || this.writeEpoch == this.retransmitEpoch)
{
-
contentType = ContentType.handshake;
short handshakeType = TlsUtils.readUint8(buf, off);
if (handshakeType == HandshakeType.finished)
{
-
DTLSEpoch nextEpoch = null;
if (this.inHandshake)
{
@@ -331,7 +355,7 @@ class DTLSRecordLayer
// Implicitly send change_cipher_spec and change to pending cipher state
// TODO Send change_cipher_spec and finished records in single datagram?
- byte[] data = new byte[]{1};
+ byte[] data = new byte[]{ 1 };
sendRecord(ContentType.change_cipher_spec, data, 0, data.length);
writeEpoch = nextEpoch;
@@ -410,7 +434,6 @@ class DTLSRecordLayer
private void raiseAlert(short alertLevel, short alertDescription, String message, Exception cause)
throws IOException
{
-
peer.notifyAlertRaised(alertLevel, alertDescription, message, cause);
byte[] error = new byte[2];
@@ -434,8 +457,7 @@ class DTLSRecordLayer
}
int received = Math.min(recordQueue.size(), RECORD_HEADER_LENGTH + length);
- recordQueue.read(buf, off, received, 0);
- recordQueue.removeData(received);
+ recordQueue.removeData(buf, off, received, 0);
return received;
}
@@ -457,6 +479,10 @@ class DTLSRecordLayer
private void sendRecord(short contentType, byte[] buf, int off, int len)
throws IOException
{
+ if (len > this.plaintextLimit)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
/*
* RFC 5264 6.2.1 Implementations MUST NOT send zero-length fragments of Handshake, Alert,
@@ -473,10 +499,7 @@ class DTLSRecordLayer
byte[] ciphertext = writeEpoch.getCipher().encodePlaintext(
getMacSequenceNumber(recordEpoch, recordSequenceNumber), contentType, buf, off, len);
- if (ciphertext.length > MAX_FRAGMENT_LENGTH)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
+ // TODO Check the ciphertext length?
byte[] record = new byte[ciphertext.length + RECORD_HEADER_LENGTH];
TlsUtils.writeUint8(contentType, record, 0);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java
index 3819251..84ccfcb 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java
@@ -10,12 +10,11 @@ import org.bouncycastle.util.Integers;
class DTLSReliableHandshake
{
-
private final static int MAX_RECEIVE_AHEAD = 10;
private final DTLSRecordLayer recordLayer;
- private TlsHandshakeHash hash = new DeferredHash();
+ private TlsHandshakeHash handshakeHash;
private Hashtable currentInboundFlight = new Hashtable();
private Hashtable previousInboundFlight = null;
@@ -27,25 +26,31 @@ class DTLSReliableHandshake
DTLSReliableHandshake(TlsContext context, DTLSRecordLayer transport)
{
this.recordLayer = transport;
- this.hash.init(context);
+ this.handshakeHash = new DeferredHash();
+ this.handshakeHash.init(context);
}
void notifyHelloComplete()
{
- this.hash = this.hash.commit();
+ this.handshakeHash = handshakeHash.notifyPRFDetermined();
+ }
+
+ TlsHandshakeHash getHandshakeHash()
+ {
+ return handshakeHash;
}
- byte[] getCurrentHash()
+ TlsHandshakeHash prepareToFinish()
{
- TlsHandshakeHash copyOfHash = hash.fork();
- byte[] result = new byte[copyOfHash.getDigestSize()];
- copyOfHash.doFinal(result, 0);
+ TlsHandshakeHash result = handshakeHash;
+ this.handshakeHash = handshakeHash.stopTracking();
return result;
}
void sendMessage(short msg_type, byte[] body)
throws IOException
{
+ TlsUtils.checkUint24(body.length);
if (!sending)
{
@@ -62,10 +67,21 @@ class DTLSReliableHandshake
updateHandshakeMessagesDigest(message);
}
- Message receiveMessage()
+ byte[] receiveMessageBody(short msg_type)
throws IOException
{
+ Message message = receiveMessage();
+ if (message.getType() != msg_type)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ return message.getBody();
+ }
+
+ Message receiveMessage()
+ throws IOException
+ {
if (sending)
{
sending = false;
@@ -93,7 +109,6 @@ class DTLSReliableHandshake
for (; ; )
{
-
int receiveLimit = recordLayer.getReceiveLimit();
if (buf == null || buf.length < receiveLimit)
{
@@ -280,7 +295,7 @@ class DTLSReliableHandshake
void resetHandshakeMessagesDigest()
{
- hash.reset();
+ handshakeHash.reset();
}
/**
@@ -328,8 +343,8 @@ class DTLSReliableHandshake
TlsUtils.writeUint16(message.getSeq(), buf, 4);
TlsUtils.writeUint24(0, buf, 6);
TlsUtils.writeUint24(body.length, buf, 9);
- hash.update(buf, 0, buf.length);
- hash.update(body, 0, body.length);
+ handshakeHash.update(buf, 0, buf.length);
+ handshakeHash.update(body, 0, body.length);
}
return message;
}
@@ -337,7 +352,6 @@ class DTLSReliableHandshake
private void writeMessage(Message message)
throws IOException
{
-
int sendLimit = recordLayer.getSendLimit();
int fragmentLimit = sendLimit - 12;
@@ -364,18 +378,15 @@ class DTLSReliableHandshake
private void writeHandshakeFragment(Message message, int fragment_offset, int fragment_length)
throws IOException
{
-
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeUint8(message.getType(), buf);
- TlsUtils.writeUint24(message.getBody().length, buf);
- TlsUtils.writeUint16(message.getSeq(), buf);
- TlsUtils.writeUint24(fragment_offset, buf);
- TlsUtils.writeUint24(fragment_length, buf);
- buf.write(message.getBody(), fragment_offset, fragment_length);
-
- byte[] fragment = buf.toByteArray();
-
- recordLayer.send(fragment, 0, fragment.length);
+ RecordLayerBuffer fragment = new RecordLayerBuffer(12 + fragment_length);
+ TlsUtils.writeUint8(message.getType(), fragment);
+ TlsUtils.writeUint24(message.getBody().length, fragment);
+ TlsUtils.writeUint16(message.getSeq(), fragment);
+ TlsUtils.writeUint24(fragment_offset, fragment);
+ TlsUtils.writeUint24(fragment_length, fragment);
+ fragment.write(message.getBody(), fragment_offset, fragment_length);
+
+ fragment.sendToRecordLayer(recordLayer);
}
private static boolean checkAll(Hashtable inboundFlight)
@@ -402,7 +413,6 @@ class DTLSReliableHandshake
static class Message
{
-
private final int message_seq;
private final short msg_type;
private final byte[] body;
@@ -429,4 +439,18 @@ class DTLSReliableHandshake
return body;
}
}
+
+ static class RecordLayerBuffer extends ByteArrayOutputStream
+ {
+ RecordLayerBuffer(int size)
+ {
+ super(size);
+ }
+
+ void sendToRecordLayer(DTLSRecordLayer recordLayer) throws IOException
+ {
+ recordLayer.send(buf, 0, count);
+ buf = null;
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSServerProtocol.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSServerProtocol.java
index 3a100d1..fbb3336 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSServerProtocol.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DTLSServerProtocol.java
@@ -15,7 +15,6 @@ import org.bouncycastle.util.Arrays;
public class DTLSServerProtocol
extends DTLSProtocol
{
-
protected boolean verifyRequests = true;
public DTLSServerProtocol(SecureRandom secureRandom)
@@ -36,7 +35,6 @@ public class DTLSServerProtocol
public DTLSTransport accept(TlsServer server, DatagramTransport transport)
throws IOException
{
-
if (server == null)
{
throw new IllegalArgumentException("'server' cannot be null");
@@ -80,10 +78,9 @@ public class DTLSServerProtocol
}
}
- public DTLSTransport serverHandshake(ServerHandshakeState state, DTLSRecordLayer recordLayer)
+ protected DTLSTransport serverHandshake(ServerHandshakeState state, DTLSRecordLayer recordLayer)
throws IOException
{
-
SecurityParameters securityParameters = state.serverContext.getSecurityParameters();
DTLSReliableHandshake handshake = new DTLSReliableHandshake(state.serverContext, recordLayer);
@@ -105,23 +102,31 @@ public class DTLSServerProtocol
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- byte[] serverHelloBody = generateServerHello(state);
- handshake.sendMessage(HandshakeType.server_hello, serverHelloBody);
-
- // TODO This block could really be done before actually sending the hello
{
- securityParameters.prfAlgorithm = TlsProtocol.getPRFAlgorithm(state.selectedCipherSuite);
+ byte[] serverHelloBody = generateServerHello(state);
+
+ if (state.maxFragmentLength >= 0)
+ {
+ int plainTextLimit = 1 << (8 + state.maxFragmentLength);
+ recordLayer.setPlaintextLimit(plainTextLimit);
+ }
+
+ securityParameters.cipherSuite = state.selectedCipherSuite;
securityParameters.compressionAlgorithm = state.selectedCompressionMethod;
-
+ securityParameters.prfAlgorithm = TlsProtocol.getPRFAlgorithm(state.serverContext,
+ state.selectedCipherSuite);
+
/*
* RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length
* has a verify_data_length equal to 12. This includes all existing cipher suites.
*/
securityParameters.verifyDataLength = 12;
-
- handshake.notifyHelloComplete();
+
+ handshake.sendMessage(HandshakeType.server_hello, serverHelloBody);
}
+ handshake.notifyHelloComplete();
+
Vector serverSupplementalData = state.server.getServerSupplementalData();
if (serverSupplementalData != null)
{
@@ -133,6 +138,9 @@ public class DTLSServerProtocol
state.keyExchange.init(state.serverContext);
state.serverCredentials = state.server.getCredentials();
+
+ Certificate serverCertificate = null;
+
if (state.serverCredentials == null)
{
state.keyExchange.skipServerCredentials();
@@ -141,10 +149,27 @@ public class DTLSServerProtocol
{
state.keyExchange.processServerCredentials(state.serverCredentials);
- byte[] certificateBody = generateCertificate(state.serverCredentials.getCertificate());
+ serverCertificate = state.serverCredentials.getCertificate();
+ byte[] certificateBody = generateCertificate(serverCertificate);
handshake.sendMessage(HandshakeType.certificate, certificateBody);
}
+ // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus
+ if (serverCertificate == null || serverCertificate.isEmpty())
+ {
+ state.allowCertificateStatus = false;
+ }
+
+ if (state.allowCertificateStatus)
+ {
+ CertificateStatus certificateStatus = state.server.getCertificateStatus();
+ if (certificateStatus != null)
+ {
+ byte[] certificateStatusBody = generateCertificateStatus(state, certificateStatus);
+ handshake.sendMessage(HandshakeType.certificate_status, certificateStatusBody);
+ }
+ }
+
byte[] serverKeyExchange = state.keyExchange.generateServerKeyExchange();
if (serverKeyExchange != null)
{
@@ -160,11 +185,16 @@ public class DTLSServerProtocol
byte[] certificateRequestBody = generateCertificateRequest(state, state.certificateRequest);
handshake.sendMessage(HandshakeType.certificate_request, certificateRequestBody);
+
+ TlsUtils.trackHashAlgorithms(handshake.getHandshakeHash(),
+ state.certificateRequest.getSupportedSignatureAlgorithms());
}
}
handshake.sendMessage(HandshakeType.server_hello_done, TlsUtils.EMPTY_BYTES);
+ handshake.getHandshakeHash().sealHashAlgorithms();
+
clientMessage = handshake.receiveMessage();
if (clientMessage.getType() == HandshakeType.supplemental_data)
@@ -190,9 +220,7 @@ public class DTLSServerProtocol
}
else
{
- ProtocolVersion equivalentTLSVersion = state.serverContext.getServerVersion().getEquivalentTLSVersion();
-
- if (ProtocolVersion.TLSv12.isEqualOrEarlierVersionOf(equivalentTLSVersion))
+ if (TlsUtils.isTLSv12(state.serverContext))
{
/*
* RFC 5246 If no suitable certificate is available, the client MUST send a
@@ -216,8 +244,11 @@ public class DTLSServerProtocol
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
+ TlsProtocol.establishMasterSecret(state.serverContext, state.keyExchange);
recordLayer.initPendingEpoch(state.server.getCipher());
+ TlsHandshakeHash prepareFinishHash = handshake.prepareToFinish();
+
/*
* RFC 5246 7.4.8 This message is only sent following a client certificate that has signing
* capability (i.e., all certificates except those containing fixed Diffie-Hellman
@@ -225,33 +256,14 @@ public class DTLSServerProtocol
*/
if (expectCertificateVerifyMessage(state))
{
- byte[] certificateVerifyHash = handshake.getCurrentHash();
- clientMessage = handshake.receiveMessage();
-
- if (clientMessage.getType() == HandshakeType.certificate_verify)
- {
- processCertificateVerify(state, clientMessage.getBody(), certificateVerifyHash);
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
+ byte[] certificateVerifyBody = handshake.receiveMessageBody(HandshakeType.certificate_verify);
+ processCertificateVerify(state, certificateVerifyBody, prepareFinishHash);
}
// NOTE: Calculated exclusive of the actual Finished message from the client
- byte[] clientFinishedHash = handshake.getCurrentHash();
- clientMessage = handshake.receiveMessage();
-
- if (clientMessage.getType() == HandshakeType.finished)
- {
- byte[] expectedClientVerifyData = TlsUtils.calculateVerifyData(state.serverContext, "client finished",
- clientFinishedHash);
- processFinished(clientMessage.getBody(), expectedClientVerifyData);
- }
- else
- {
- throw new TlsFatalAlert(AlertDescription.unexpected_message);
- }
+ byte[] expectedClientVerifyData = TlsUtils.calculateVerifyData(state.serverContext, ExporterLabel.client_finished,
+ TlsProtocol.getCurrentPRFHash(state.serverContext, handshake.getHandshakeHash(), null));
+ processFinished(handshake.receiveMessageBody(HandshakeType.finished), expectedClientVerifyData);
if (state.expectSessionTicket)
{
@@ -261,8 +273,8 @@ public class DTLSServerProtocol
}
// NOTE: Calculated exclusive of the Finished message itself
- byte[] serverVerifyData = TlsUtils.calculateVerifyData(state.serverContext, "server finished",
- handshake.getCurrentHash());
+ byte[] serverVerifyData = TlsUtils.calculateVerifyData(state.serverContext, ExporterLabel.server_finished,
+ TlsProtocol.getCurrentPRFHash(state.serverContext, handshake.getHandshakeHash(), null));
handshake.sendMessage(HandshakeType.finished, serverVerifyData);
handshake.finish();
@@ -275,16 +287,22 @@ public class DTLSServerProtocol
protected byte[] generateCertificateRequest(ServerHandshakeState state, CertificateRequest certificateRequest)
throws IOException
{
-
ByteArrayOutputStream buf = new ByteArrayOutputStream();
certificateRequest.encode(buf);
return buf.toByteArray();
}
- protected byte[] generateNewSessionTicket(ServerHandshakeState state, NewSessionTicket newSessionTicket)
+ protected byte[] generateCertificateStatus(ServerHandshakeState state, CertificateStatus certificateStatus)
throws IOException
{
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ certificateStatus.encode(buf);
+ return buf.toByteArray();
+ }
+ protected byte[] generateNewSessionTicket(ServerHandshakeState state, NewSessionTicket newSessionTicket)
+ throws IOException
+ {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
newSessionTicket.encode(buf);
return buf.toByteArray();
@@ -293,6 +311,7 @@ public class DTLSServerProtocol
protected byte[] generateServerHello(ServerHandshakeState state)
throws IOException
{
+ SecurityParameters securityParameters = state.serverContext.getSecurityParameters();
ByteArrayOutputStream buf = new ByteArrayOutputStream();
@@ -310,7 +329,7 @@ public class DTLSServerProtocol
TlsUtils.writeVersion(state.serverContext.getServerVersion(), buf);
- buf.write(state.serverContext.getSecurityParameters().serverRandom);
+ buf.write(securityParameters.getServerRandom());
/*
* The server may return an empty session_id to indicate that the session will not be cached
@@ -319,7 +338,7 @@ public class DTLSServerProtocol
TlsUtils.writeOpaque8(TlsUtils.EMPTY_BYTES, buf);
state.selectedCipherSuite = state.server.getSelectedCipherSuite();
- if (!TlsProtocol.arrayContains(state.offeredCipherSuites, state.selectedCipherSuite)
+ if (!Arrays.contains(state.offeredCipherSuites, state.selectedCipherSuite)
|| state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
|| state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
{
@@ -329,7 +348,7 @@ public class DTLSServerProtocol
validateSelectedCipherSuite(state.selectedCipherSuite, AlertDescription.internal_error);
state.selectedCompressionMethod = state.server.getSelectedCompressionMethod();
- if (!TlsProtocol.arrayContains(state.offeredCompressionMethods, state.selectedCompressionMethod))
+ if (!Arrays.contains(state.offeredCompressionMethods, state.selectedCompressionMethod))
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
@@ -344,9 +363,8 @@ public class DTLSServerProtocol
*/
if (state.secure_renegotiation)
{
-
- boolean noRenegExt = state.serverExtensions == null
- || !state.serverExtensions.containsKey(TlsProtocol.EXT_RenegotiationInfo);
+ byte[] renegExtData = TlsUtils.getExtensionData(state.serverExtensions, TlsProtocol.EXT_RenegotiationInfo);
+ boolean noRenegExt = (null == renegExtData);
if (noRenegExt)
{
@@ -357,15 +375,12 @@ public class DTLSServerProtocol
* because the client is signaling its willingness to receive the extension via the
* TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
*/
- if (state.serverExtensions == null)
- {
- state.serverExtensions = new Hashtable();
- }
/*
* If the secure_renegotiation flag is set to TRUE, the server MUST include an empty
* "renegotiation_info" extension in the ServerHello message.
*/
+ state.serverExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(state.serverExtensions);
state.serverExtensions.put(TlsProtocol.EXT_RenegotiationInfo,
TlsProtocol.createRenegotiationInfo(TlsUtils.EMPTY_BYTES));
}
@@ -373,7 +388,17 @@ public class DTLSServerProtocol
if (state.serverExtensions != null)
{
- state.expectSessionTicket = state.serverExtensions.containsKey(TlsProtocol.EXT_SessionTicket);
+ state.maxFragmentLength = evaluateMaxFragmentLengthExtension(state.clientExtensions, state.serverExtensions,
+ AlertDescription.internal_error);
+
+ securityParameters.truncatedHMac = TlsExtensionsUtils.hasTruncatedHMacExtension(state.serverExtensions);
+
+ state.allowCertificateStatus = TlsUtils.hasExpectedEmptyExtensionData(state.serverExtensions,
+ TlsExtensionsUtils.EXT_status_request, AlertDescription.internal_error);
+
+ state.expectSessionTicket = TlsUtils.hasExpectedEmptyExtensionData(state.serverExtensions,
+ TlsProtocol.EXT_SessionTicket, AlertDescription.internal_error);
+
TlsProtocol.writeExtensions(buf, state.serverExtensions);
}
@@ -383,7 +408,6 @@ public class DTLSServerProtocol
protected void notifyClientCertificate(ServerHandshakeState state, Certificate clientCertificate)
throws IOException
{
-
if (state.certificateRequest == null)
{
throw new IllegalStateException();
@@ -429,7 +453,6 @@ public class DTLSServerProtocol
protected void processClientCertificate(ServerHandshakeState state, byte[] body)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(body);
Certificate clientCertificate = Certificate.parse(buf);
@@ -439,27 +462,29 @@ public class DTLSServerProtocol
notifyClientCertificate(state, clientCertificate);
}
- protected void processCertificateVerify(ServerHandshakeState state, byte[] body, byte[] certificateVerifyHash)
+ protected void processCertificateVerify(ServerHandshakeState state, byte[] body, TlsHandshakeHash prepareFinishHash)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(body);
- byte[] clientCertificateSignature = TlsUtils.readOpaque16(buf);
+ DigitallySigned clientCertificateVerify = DigitallySigned.parse(state.serverContext, buf);
TlsProtocol.assertEmpty(buf);
// Verify the CertificateVerify message contains a correct signature.
try
{
- TlsSigner tlsSigner = TlsUtils.createTlsSigner(state.clientCertificateType);
- tlsSigner.init(state.serverContext);
+ // TODO For TLS 1.2, this needs to be the hash specified in the DigitallySigned
+ byte[] certificateVerifyHash = TlsProtocol.getCurrentPRFHash(state.serverContext, prepareFinishHash, null);
org.bouncycastle.asn1.x509.Certificate x509Cert = state.clientCertificate.getCertificateAt(0);
SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(keyInfo);
- tlsSigner.verifyRawSignature(clientCertificateSignature, publicKey, certificateVerifyHash);
+ TlsSigner tlsSigner = TlsUtils.createTlsSigner(state.clientCertificateType);
+ tlsSigner.init(state.serverContext);
+ tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(),
+ clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash);
}
catch (Exception e)
{
@@ -470,7 +495,6 @@ public class DTLSServerProtocol
protected void processClientHello(ServerHandshakeState state, byte[] body)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(body);
// TODO Read RFCs for guidance on the expected record layer version number
@@ -545,7 +569,7 @@ public class DTLSServerProtocol
* TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
* to TRUE.
*/
- if (TlsProtocol.arrayContains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
+ if (Arrays.contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
{
state.secure_renegotiation = true;
}
@@ -554,23 +578,19 @@ public class DTLSServerProtocol
* The server MUST check if the "renegotiation_info" extension is included in the
* ClientHello.
*/
- if (state.clientExtensions != null)
+ byte[] renegExtData = TlsUtils.getExtensionData(state.clientExtensions, TlsProtocol.EXT_RenegotiationInfo);
+ if (renegExtData != null)
{
- byte[] renegExtValue = (byte[])state.clientExtensions.get(TlsProtocol.EXT_RenegotiationInfo);
- if (renegExtValue != null)
- {
- /*
- * If the extension is present, set secure_renegotiation flag to TRUE. The
- * server MUST then verify that the length of the "renegotiated_connection"
- * field is zero, and if it is not, MUST abort the handshake.
- */
- state.secure_renegotiation = true;
+ /*
+ * If the extension is present, set secure_renegotiation flag to TRUE. The
+ * server MUST then verify that the length of the "renegotiated_connection"
+ * field is zero, and if it is not, MUST abort the handshake.
+ */
+ state.secure_renegotiation = true;
- if (!Arrays.constantTimeAreEqual(renegExtValue,
- TlsProtocol.createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
- {
- throw new TlsFatalAlert(AlertDescription.handshake_failure);
- }
+ if (!Arrays.constantTimeAreEqual(renegExtData, TlsProtocol.createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
}
}
@@ -586,20 +606,16 @@ public class DTLSServerProtocol
protected void processClientKeyExchange(ServerHandshakeState state, byte[] body)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(body);
state.keyExchange.processClientKeyExchange(buf);
TlsProtocol.assertEmpty(buf);
-
- TlsProtocol.establishMasterSecret(state.serverContext, state.keyExchange);
}
protected void processClientSupplementalData(ServerHandshakeState state, byte[] body)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(body);
Vector clientSupplementalData = TlsProtocol.readSupplementalDataMessage(buf);
state.server.processClientSupplementalData(clientSupplementalData);
@@ -620,6 +636,8 @@ public class DTLSServerProtocol
int selectedCipherSuite = -1;
short selectedCompressionMethod = -1;
boolean secure_renegotiation = false;
+ short maxFragmentLength = -1;
+ boolean allowCertificateStatus = false;
boolean expectSessionTicket = false;
Hashtable serverExtensions = null;
TlsKeyExchange keyExchange = null;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java
index 98efc4f..78afb41 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java
@@ -11,9 +11,8 @@ import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.util.BigIntegers;
public class DefaultTlsAgreementCredentials
- implements TlsAgreementCredentials
+ extends AbstractTlsAgreementCredentials
{
-
protected Certificate certificate;
protected AsymmetricKeyParameter privateKey;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java
index 82b37d9..7f70c64 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java
@@ -4,6 +4,7 @@ import java.io.IOException;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
@@ -15,24 +16,37 @@ import org.bouncycastle.crypto.engines.CamelliaEngine;
import org.bouncycastle.crypto.engines.DESedeEngine;
import org.bouncycastle.crypto.engines.RC4Engine;
import org.bouncycastle.crypto.engines.SEEDEngine;
+import org.bouncycastle.crypto.engines.Salsa20Engine;
+import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.modes.AEADBlockCipher;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
+import org.bouncycastle.crypto.modes.CCMBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
public class DefaultTlsCipherFactory
extends AbstractTlsCipherFactory
{
-
public TlsCipher createCipher(TlsContext context, int encryptionAlgorithm, int macAlgorithm)
throws IOException
{
-
switch (encryptionAlgorithm)
{
case EncryptionAlgorithm._3DES_EDE_CBC:
return createDESedeCipher(context, macAlgorithm);
case EncryptionAlgorithm.AES_128_CBC:
return createAESCipher(context, 16, macAlgorithm);
+ case EncryptionAlgorithm.AES_128_CCM:
+ // NOTE: Ignores macAlgorithm
+ return createCipher_AES_CCM(context, 16, 16);
+ case EncryptionAlgorithm.AES_128_CCM_8:
+ // NOTE: Ignores macAlgorithm
+ return createCipher_AES_CCM(context, 16, 8);
+ case EncryptionAlgorithm.AES_256_CCM:
+ // NOTE: Ignores macAlgorithm
+ return createCipher_AES_CCM(context, 32, 16);
+ case EncryptionAlgorithm.AES_256_CCM_8:
+ // NOTE: Ignores macAlgorithm
+ return createCipher_AES_CCM(context, 32, 8);
case EncryptionAlgorithm.AES_128_GCM:
// NOTE: Ignores macAlgorithm
return createCipher_AES_GCM(context, 16, 16);
@@ -45,10 +59,14 @@ public class DefaultTlsCipherFactory
return createCamelliaCipher(context, 16, macAlgorithm);
case EncryptionAlgorithm.CAMELLIA_256_CBC:
return createCamelliaCipher(context, 32, macAlgorithm);
+ case EncryptionAlgorithm.ESTREAM_SALSA20:
+ return createSalsa20Cipher(context, 12, 32, macAlgorithm);
case EncryptionAlgorithm.NULL:
return createNullCipher(context, macAlgorithm);
case EncryptionAlgorithm.RC4_128:
return createRC4Cipher(context, 16, macAlgorithm);
+ case EncryptionAlgorithm.SALSA20:
+ return createSalsa20Cipher(context, 20, 32, macAlgorithm);
case EncryptionAlgorithm.SEED_CBC:
return createSEEDCipher(context, macAlgorithm);
default:
@@ -63,6 +81,13 @@ public class DefaultTlsCipherFactory
createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize);
}
+ protected TlsAEADCipher createCipher_AES_CCM(TlsContext context, int cipherKeySize, int macSize)
+ throws IOException
+ {
+ return new TlsAEADCipher(context, createAEADBlockCipher_AES_CCM(),
+ createAEADBlockCipher_AES_CCM(), cipherKeySize, macSize);
+ }
+
protected TlsAEADCipher createCipher_AES_GCM(TlsContext context, int cipherKeySize, int macSize)
throws IOException
{
@@ -70,8 +95,7 @@ public class DefaultTlsCipherFactory
createAEADBlockCipher_AES_GCM(), cipherKeySize, macSize);
}
- protected TlsBlockCipher createCamelliaCipher(TlsContext context, int cipherKeySize,
- int macAlgorithm)
+ protected TlsBlockCipher createCamelliaCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
throws IOException
{
return new TlsBlockCipher(context, createCamelliaBlockCipher(),
@@ -79,6 +103,13 @@ public class DefaultTlsCipherFactory
createHMACDigest(macAlgorithm), cipherKeySize);
}
+ protected TlsBlockCipher createDESedeCipher(TlsContext context, int macAlgorithm)
+ throws IOException
+ {
+ return new TlsBlockCipher(context, createDESedeBlockCipher(), createDESedeBlockCipher(),
+ createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), 24);
+ }
+
protected TlsNullCipher createNullCipher(TlsContext context, int macAlgorithm)
throws IOException
{
@@ -86,19 +117,22 @@ public class DefaultTlsCipherFactory
createHMACDigest(macAlgorithm));
}
- protected TlsStreamCipher createRC4Cipher(TlsContext context, int cipherKeySize,
- int macAlgorithm)
+ protected TlsStreamCipher createRC4Cipher(TlsContext context, int cipherKeySize, int macAlgorithm)
throws IOException
{
return new TlsStreamCipher(context, createRC4StreamCipher(), createRC4StreamCipher(),
createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize);
}
- protected TlsBlockCipher createDESedeCipher(TlsContext context, int macAlgorithm)
+ protected TlsStreamCipher createSalsa20Cipher(TlsContext context, int rounds, int cipherKeySize, int macAlgorithm)
throws IOException
{
- return new TlsBlockCipher(context, createDESedeBlockCipher(), createDESedeBlockCipher(),
- createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), 24);
+ /*
+ * TODO To be able to support UMAC96, we need to give the TlsStreamCipher a Mac instead of
+ * assuming HMAC and passing a digest.
+ */
+ return new TlsStreamCipher(context, createSalsa20StreamCipher(rounds), createSalsa20StreamCipher(rounds),
+ createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize);
}
protected TlsBlockCipher createSEEDCipher(TlsContext context, int macAlgorithm)
@@ -108,14 +142,14 @@ public class DefaultTlsCipherFactory
createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), 16);
}
- protected StreamCipher createRC4StreamCipher()
+ protected BlockCipher createAESBlockCipher()
{
- return new RC4Engine();
+ return new CBCBlockCipher(new AESFastEngine());
}
- protected BlockCipher createAESBlockCipher()
+ protected AEADBlockCipher createAEADBlockCipher_AES_CCM()
{
- return new CBCBlockCipher(new AESFastEngine());
+ return new CCMBlockCipher(new AESFastEngine());
}
protected AEADBlockCipher createAEADBlockCipher_AES_GCM()
@@ -134,13 +168,22 @@ public class DefaultTlsCipherFactory
return new CBCBlockCipher(new DESedeEngine());
}
+ protected StreamCipher createRC4StreamCipher()
+ {
+ return new RC4Engine();
+ }
+
+ protected StreamCipher createSalsa20StreamCipher(int rounds)
+ {
+ return new Salsa20Engine(rounds);
+ }
+
protected BlockCipher createSEEDBlockCipher()
{
return new CBCBlockCipher(new SEEDEngine());
}
- protected Digest createHMACDigest(int macAlgorithm)
- throws IOException
+ protected Digest createHMACDigest(int macAlgorithm) throws IOException
{
switch (macAlgorithm)
{
@@ -160,4 +203,16 @@ public class DefaultTlsCipherFactory
throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
+
+ protected Mac createMac(int macAlgorithm) throws IOException
+ {
+ switch (macAlgorithm)
+ {
+ // TODO Need an implementation of UMAC
+// case MACAlgorithm.umac96:
+// return
+ default:
+ return new HMac(createHMACDigest(macAlgorithm));
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsClient.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsClient.java
index 4f9fe27..63db45f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsClient.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsClient.java
@@ -1,15 +1,10 @@
package org.bouncycastle.crypto.tls;
import java.io.IOException;
-import java.util.Hashtable;
public abstract class DefaultTlsClient
extends AbstractTlsClient
{
-
- protected int[] namedCurves;
- protected short[] clientECPointFormats, serverECPointFormats;
-
public DefaultTlsClient()
{
super();
@@ -22,75 +17,15 @@ public abstract class DefaultTlsClient
public int[] getCipherSuites()
{
- return new int[]{CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
- CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA,};
- }
-
- public Hashtable getClientExtensions()
- throws IOException
- {
-
- Hashtable clientExtensions = super.getClientExtensions();
-
- if (TlsECCUtils.containsECCCipherSuites(getCipherSuites()))
- {
- /*
- * RFC 4492 5.1. A client that proposes ECC cipher suites in its ClientHello message
- * appends these extensions (along with any others), enumerating the curves it supports
- * and the point formats it can parse. Clients SHOULD send both the Supported Elliptic
- * Curves Extension and the Supported Point Formats Extension.
- */
- /*
- * TODO Could just add all the curves since we support them all, but users may not want
- * to use unnecessarily large fields. Need configuration options.
- */
- this.namedCurves = new int[]{NamedCurve.secp256r1, NamedCurve.sect233r1, NamedCurve.secp224r1,
- NamedCurve.sect193r1, NamedCurve.secp192r1, NamedCurve.arbitrary_explicit_char2_curves,
- NamedCurve.arbitrary_explicit_prime_curves};
- this.clientECPointFormats = new short[]{ECPointFormat.ansiX962_compressed_char2,
- ECPointFormat.ansiX962_compressed_prime, ECPointFormat.uncompressed};
-
- if (clientExtensions == null)
- {
- clientExtensions = new Hashtable();
- }
-
- TlsECCUtils.addSupportedEllipticCurvesExtension(clientExtensions, namedCurves);
- TlsECCUtils.addSupportedPointFormatsExtension(clientExtensions, clientECPointFormats);
- }
-
- return clientExtensions;
- }
-
- public void processServerExtensions(Hashtable serverExtensions)
- throws IOException
- {
-
- super.processServerExtensions(serverExtensions);
-
- if (serverExtensions != null)
- {
- int[] namedCurves = TlsECCUtils.getSupportedEllipticCurvesExtension(serverExtensions);
- if (namedCurves != null)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
-
- this.serverECPointFormats = TlsECCUtils.getSupportedPointFormatsExtension(serverExtensions);
- if (this.serverECPointFormats != null && !TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
- }
+ return new int[] { CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA };
}
public TlsKeyExchange getKeyExchange()
throws IOException
{
-
switch (selectedCipherSuite)
{
case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
@@ -132,12 +67,20 @@ public abstract class DefaultTlsClient
case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_UMAC96:
case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
@@ -170,8 +113,12 @@ public abstract class DefaultTlsClient
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96:
return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
@@ -181,24 +128,36 @@ public abstract class DefaultTlsClient
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96:
case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96:
return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA);
case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96:
case CipherSuite.TLS_RSA_WITH_NULL_MD5:
case CipherSuite.TLS_RSA_WITH_NULL_SHA:
case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_SALSA20_UMAC96:
case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
return createRSAKeyExchange();
@@ -215,7 +174,6 @@ public abstract class DefaultTlsClient
public TlsCipher getCipher()
throws IOException
{
-
switch (selectedCipherSuite)
{
case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
@@ -251,6 +209,14 @@ public abstract class DefaultTlsClient
case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha256);
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CCM_8, MACAlgorithm._null);
+
case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
@@ -286,6 +252,14 @@ public abstract class DefaultTlsClient
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha384);
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CCM_8, MACAlgorithm._null);
+
case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
@@ -311,6 +285,18 @@ public abstract class DefaultTlsClient
case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha1);
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.umac96);
+
case CipherSuite.TLS_RSA_WITH_NULL_MD5:
return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_md5);
@@ -334,6 +320,18 @@ public abstract class DefaultTlsClient
case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
return cipherFactory.createCipher(context, EncryptionAlgorithm.RC4_128, MACAlgorithm.hmac_sha1);
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_RSA_WITH_SALSA20_UMAC96:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.umac96);
+
case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsEncryptionCredentials.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsEncryptionCredentials.java
index a338c38..dcdb493 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsEncryptionCredentials.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsEncryptionCredentials.java
@@ -10,14 +10,14 @@ import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyParameters;
public class DefaultTlsEncryptionCredentials
- implements TlsEncryptionCredentials
+ extends AbstractTlsEncryptionCredentials
{
protected TlsContext context;
protected Certificate certificate;
protected AsymmetricKeyParameter privateKey;
public DefaultTlsEncryptionCredentials(TlsContext context, Certificate certificate,
- AsymmetricKeyParameter privateKey)
+ AsymmetricKeyParameter privateKey)
{
if (certificate == null)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsServer.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsServer.java
index 246b87e..31b6a74 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsServer.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsServer.java
@@ -48,15 +48,18 @@ public abstract class DefaultTlsServer
public TlsCredentials getCredentials()
throws IOException
{
-
switch (selectedCipherSuite)
{
case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
@@ -71,9 +74,13 @@ public abstract class DefaultTlsServer
case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
@@ -85,6 +92,8 @@ public abstract class DefaultTlsServer
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
return getRSASignerCredentials();
default:
@@ -98,7 +107,6 @@ public abstract class DefaultTlsServer
public TlsKeyExchange getKeyExchange()
throws IOException
{
-
switch (selectedCipherSuite)
{
case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
@@ -140,12 +148,20 @@ public abstract class DefaultTlsServer
case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_UMAC96:
case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
@@ -178,8 +194,12 @@ public abstract class DefaultTlsServer
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96:
return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
@@ -189,24 +209,36 @@ public abstract class DefaultTlsServer
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96:
case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96:
return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA);
case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96:
case CipherSuite.TLS_RSA_WITH_NULL_MD5:
case CipherSuite.TLS_RSA_WITH_NULL_SHA:
case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_SALSA20_UMAC96:
case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
return createRSAKeyExchange();
@@ -221,7 +253,6 @@ public abstract class DefaultTlsServer
public TlsCipher getCipher()
throws IOException
{
-
switch (selectedCipherSuite)
{
case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
@@ -257,6 +288,14 @@ public abstract class DefaultTlsServer
case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha256);
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CCM_8, MACAlgorithm._null);
+
case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
@@ -292,6 +331,14 @@ public abstract class DefaultTlsServer
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha384);
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CCM_8, MACAlgorithm._null);
+
case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
@@ -317,6 +364,18 @@ public abstract class DefaultTlsServer
case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha1);
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.umac96);
+
case CipherSuite.TLS_RSA_WITH_NULL_MD5:
return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_md5);
@@ -340,6 +399,18 @@ public abstract class DefaultTlsServer
case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
return cipherFactory.createCipher(context, EncryptionAlgorithm.RC4_128, MACAlgorithm.hmac_sha1);
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_RSA_WITH_SALSA20_UMAC96:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.umac96);
+
case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java
index b775250..15bf4a4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java
@@ -9,17 +9,23 @@ import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
public class DefaultTlsSignerCredentials
- implements TlsSignerCredentials
+ extends AbstractTlsSignerCredentials
{
protected TlsContext context;
protected Certificate certificate;
protected AsymmetricKeyParameter privateKey;
+ protected SignatureAndHashAlgorithm signatureAndHashAlgorithm;
protected TlsSigner signer;
public DefaultTlsSignerCredentials(TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey)
{
+ this(context, certificate, privateKey, null);
+ }
+ public DefaultTlsSignerCredentials(TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey,
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm)
+ {
if (certificate == null)
{
throw new IllegalArgumentException("'certificate' cannot be null");
@@ -36,6 +42,10 @@ public class DefaultTlsSignerCredentials
{
throw new IllegalArgumentException("'privateKey' must be private");
}
+ if (TlsUtils.isTLSv12(context) && signatureAndHashAlgorithm == null)
+ {
+ throw new IllegalArgumentException("'signatureAndHashAlgorithm' cannot be null for (D)TLS 1.2+");
+ }
if (privateKey instanceof RSAKeyParameters)
{
@@ -59,6 +69,7 @@ public class DefaultTlsSignerCredentials
this.context = context;
this.certificate = certificate;
this.privateKey = privateKey;
+ this.signatureAndHashAlgorithm = signatureAndHashAlgorithm;
}
public Certificate getCertificate()
@@ -66,16 +77,28 @@ public class DefaultTlsSignerCredentials
return certificate;
}
- public byte[] generateCertificateSignature(byte[] md5andsha1)
+ public byte[] generateCertificateSignature(byte[] hash)
throws IOException
{
try
{
- return signer.generateRawSignature(privateKey, md5andsha1);
+ if (TlsUtils.isTLSv12(context))
+ {
+ return signer.generateRawSignature(signatureAndHashAlgorithm, privateKey, hash);
+ }
+ else
+ {
+ return signer.generateRawSignature(privateKey, hash);
+ }
}
catch (CryptoException e)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
+
+ public SignatureAndHashAlgorithm getSignatureAndHashAlgorithm()
+ {
+ return signatureAndHashAlgorithm;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DeferredHash.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DeferredHash.java
index e8c76e6..274e69a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DeferredHash.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DeferredHash.java
@@ -1,8 +1,10 @@
package org.bouncycastle.crypto.tls;
-import java.io.ByteArrayOutputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.util.Shorts;
/**
* Buffers input until the hash algorithm is determined.
@@ -10,23 +12,27 @@ import org.bouncycastle.crypto.Digest;
class DeferredHash
implements TlsHandshakeHash
{
+ protected static final int BUFFERING_HASH_LIMIT = 4;
protected TlsContext context;
- private ByteArrayOutputStream buf = new ByteArrayOutputStream();
- private int prfAlgorithm = -1;
- private Digest hash = null;
+ private DigestInputBuffer buf;
+ private Hashtable hashes;
+ private Short prfHashAlgorithm;
DeferredHash()
{
- this.buf = new ByteArrayOutputStream();
- this.hash = null;
+ this.buf = new DigestInputBuffer();
+ this.hashes = new Hashtable();
+ this.prfHashAlgorithm = null;
}
- private DeferredHash(Digest hash)
+ private DeferredHash(Short prfHashAlgorithm, Digest prfHash)
{
this.buf = null;
- this.hash = hash;
+ this.hashes = new Hashtable();
+ this.prfHashAlgorithm = prfHashAlgorithm;
+ hashes.put(prfHashAlgorithm, prfHash);
}
public void init(TlsContext context)
@@ -34,95 +40,168 @@ class DeferredHash
this.context = context;
}
- public TlsHandshakeHash commit()
+ public TlsHandshakeHash notifyPRFDetermined()
{
-
int prfAlgorithm = context.getSecurityParameters().getPrfAlgorithm();
+ if (prfAlgorithm == PRFAlgorithm.tls_prf_legacy)
+ {
+ CombinedHash legacyHash = new CombinedHash();
+ legacyHash.init(context);
+ buf.updateDigest(legacyHash);
+ return legacyHash.notifyPRFDetermined();
+ }
- Digest prfHash = TlsUtils.createPRFHash(prfAlgorithm);
+ this.prfHashAlgorithm = Shorts.valueOf(TlsUtils.getHashAlgorithmForPRFAlgorithm(prfAlgorithm));
- byte[] data = buf.toByteArray();
- prfHash.update(data, 0, data.length);
+ checkTrackingHash(prfHashAlgorithm);
+
+ return this;
+ }
- if (prfHash instanceof TlsHandshakeHash)
+ public void trackHashAlgorithm(short hashAlgorithm)
+ {
+ if (buf == null)
{
- TlsHandshakeHash tlsPRFHash = (TlsHandshakeHash)prfHash;
- tlsPRFHash.init(context);
- return tlsPRFHash.commit();
+ throw new IllegalStateException("Too late to track more hash algorithms");
}
- this.prfAlgorithm = prfAlgorithm;
- this.hash = prfHash;
- this.buf = null;
+ checkTrackingHash(Shorts.valueOf(hashAlgorithm));
+ }
- return this;
+ public void sealHashAlgorithms()
+ {
+ checkStopBuffering();
}
- public TlsHandshakeHash fork()
+ public TlsHandshakeHash stopTracking()
{
- checkHash();
- return new DeferredHash(TlsUtils.clonePRFHash(prfAlgorithm, hash));
+ Digest prfHash = TlsUtils.cloneHash(prfHashAlgorithm.shortValue(), (Digest)hashes.get(prfHashAlgorithm));
+ if (buf != null)
+ {
+ buf.updateDigest(prfHash);
+ }
+ DeferredHash result = new DeferredHash(prfHashAlgorithm, prfHash);
+ result.init(context);
+ return result;
+ }
+
+ public Digest forkPRFHash()
+ {
+ checkStopBuffering();
+
+ if (buf != null)
+ {
+ Digest prfHash = TlsUtils.createHash(prfHashAlgorithm.shortValue());
+ buf.updateDigest(prfHash);
+ return prfHash;
+ }
+
+ return TlsUtils.cloneHash(prfHashAlgorithm.shortValue(), (Digest)hashes.get(prfHashAlgorithm));
+ }
+
+ public byte[] getFinalHash(short hashAlgorithm)
+ {
+ Digest d = (Digest)hashes.get(Shorts.valueOf(hashAlgorithm));
+ if (d == null)
+ {
+ throw new IllegalStateException("HashAlgorithm " + hashAlgorithm + " is not being tracked");
+ }
+
+ d = TlsUtils.cloneHash(hashAlgorithm, d);
+ if (buf != null)
+ {
+ buf.updateDigest(d);
+ }
+
+ byte[] bs = new byte[d.getDigestSize()];
+ d.doFinal(bs, 0);
+ return bs;
}
public String getAlgorithmName()
{
- checkHash();
- return hash.getAlgorithmName();
+ throw new IllegalStateException("Use fork() to get a definite Digest");
}
public int getDigestSize()
{
- checkHash();
- return hash.getDigestSize();
+ throw new IllegalStateException("Use fork() to get a definite Digest");
}
public void update(byte input)
{
- if (hash == null)
+ if (buf != null)
{
buf.write(input);
+ return;
}
- else
+
+ Enumeration e = hashes.elements();
+ while (e.hasMoreElements())
{
+ Digest hash = (Digest)e.nextElement();
hash.update(input);
}
}
public void update(byte[] input, int inOff, int len)
{
- if (hash == null)
+ if (buf != null)
{
buf.write(input, inOff, len);
+ return;
}
- else
+
+ Enumeration e = hashes.elements();
+ while (e.hasMoreElements())
{
+ Digest hash = (Digest)e.nextElement();
hash.update(input, inOff, len);
}
}
public int doFinal(byte[] output, int outOff)
{
- checkHash();
- return hash.doFinal(output, outOff);
+ throw new IllegalStateException("Use fork() to get a definite Digest");
}
public void reset()
{
- if (hash == null)
+ if (buf != null)
{
buf.reset();
+ return;
}
- else
+
+ Enumeration e = hashes.elements();
+ while (e.hasMoreElements())
{
+ Digest hash = (Digest)e.nextElement();
hash.reset();
}
}
- protected void checkHash()
+ protected void checkStopBuffering()
+ {
+ if (buf != null && hashes.size() <= BUFFERING_HASH_LIMIT)
+ {
+ Enumeration e = hashes.elements();
+ while (e.hasMoreElements())
+ {
+ Digest hash = (Digest)e.nextElement();
+ buf.updateDigest(hash);
+ }
+
+ this.buf = null;
+ }
+ }
+
+ protected void checkTrackingHash(Short hashAlgorithm)
{
- if (hash == null)
+ if (!hashes.containsKey(hashAlgorithm))
{
- throw new IllegalStateException("No hash algorithm has been set");
+ Digest hash = TlsUtils.createHash(hashAlgorithm.shortValue());
+ hashes.put(hashAlgorithm, hash);
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DigestInputBuffer.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DigestInputBuffer.java
new file mode 100644
index 0000000..7cfa890
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DigestInputBuffer.java
@@ -0,0 +1,13 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+
+import org.bouncycastle.crypto.Digest;
+
+class DigestInputBuffer extends ByteArrayOutputStream
+{
+ void updateDigest(Digest d)
+ {
+ d.update(this.buf, 0, count);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/DigitallySigned.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DigitallySigned.java
new file mode 100644
index 0000000..c366ca9
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/DigitallySigned.java
@@ -0,0 +1,72 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class DigitallySigned
+{
+ protected SignatureAndHashAlgorithm algorithm;
+ protected byte[] signature;
+
+ public DigitallySigned(SignatureAndHashAlgorithm algorithm, byte[] signature)
+ {
+ if (signature == null)
+ {
+ throw new IllegalArgumentException("'signature' cannot be null");
+ }
+
+ this.algorithm = algorithm;
+ this.signature = signature;
+ }
+
+ /**
+ * @return a {@link SignatureAndHashAlgorithm} (or null before TLS 1.2).
+ */
+ public SignatureAndHashAlgorithm getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public byte[] getSignature()
+ {
+ return signature;
+ }
+
+ /**
+ * Encode this {@link DigitallySigned} to an {@link OutputStream}.
+ *
+ * @param output
+ * the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output) throws IOException
+ {
+ if (algorithm != null)
+ {
+ algorithm.encode(output);
+ }
+ TlsUtils.writeOpaque16(signature, output);
+ }
+
+ /**
+ * Parse a {@link DigitallySigned} from an {@link InputStream}.
+ *
+ * @param context
+ * the {@link TlsContext} of the current connection.
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link DigitallySigned} object.
+ * @throws IOException
+ */
+ public static DigitallySigned parse(TlsContext context, InputStream input) throws IOException
+ {
+ SignatureAndHashAlgorithm algorithm = null;
+ if (TlsUtils.isTLSv12(context))
+ {
+ algorithm = SignatureAndHashAlgorithm.parse(input);
+ }
+ byte[] signature = TlsUtils.readOpaque16(input);
+ return new DigitallySigned(algorithm, signature);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java
index f991e4a..6f3fe01 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java
@@ -25,6 +25,12 @@ public class EncryptionAlgorithm
public static final int AES_256_CBC = 9;
/*
+ * RFC 5289
+ */
+ public static final int AES_128_GCM = 10;
+ public static final int AES_256_GCM = 11;
+
+ /*
* RFC 4132
*/
public static final int CAMELLIA_128_CBC = 12;
@@ -36,8 +42,16 @@ public class EncryptionAlgorithm
public static final int SEED_CBC = 14;
/*
- * RFC 5289
+ * RFC 6655
*/
- public static final int AES_128_GCM = 10;
- public static final int AES_256_GCM = 11;
+ public static final int AES_128_CCM = 15;
+ public static final int AES_128_CCM_8 = 16;
+ public static final int AES_256_CCM = 17;
+ public static final int AES_256_CCM_8 = 18;
+
+ /*
+ * TBD[draft-josefsson-salsa20-tls-02]
+ */
+ static final int ESTREAM_SALSA20 = 100;
+ static final int SALSA20 = 101;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ExtensionType.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ExtensionType.java
index 0be6465..8312e93 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ExtensionType.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ExtensionType.java
@@ -3,7 +3,7 @@ package org.bouncycastle.crypto.tls;
public class ExtensionType
{
/*
- * RFC 6066 1.1.
+ * RFC 2546 2.3.
*/
public static final int server_name = 0;
public static final int max_fragment_length = 1;
@@ -44,6 +44,11 @@ public class ExtensionType
public static final int use_srtp = 14;
/*
+ * RFC 6520 6.
+ */
+ public static final int heartbeat = 15;
+
+ /*
* RFC 5746 3.2.
*/
public static final int renegotiation_info = 0xff01;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/HandshakeType.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HandshakeType.java
index 53b4520..c81660a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/HandshakeType.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HandshakeType.java
@@ -17,6 +17,12 @@ public class HandshakeType
public static final short finished = 20;
/*
+ * RFC 3546 2.4
+ */
+ public static final short certificate_url = 21;
+ public static final short certificate_status = 22;
+
+ /*
* (DTLS) RFC 4347 4.3.2
*/
public static final short hello_verify_request = 3;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/HashAlgorithm.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HashAlgorithm.java
index ac0a4c6..dc7482b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/HashAlgorithm.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HashAlgorithm.java
@@ -5,7 +5,6 @@ package org.bouncycastle.crypto.tls;
*/
public class HashAlgorithm
{
-
public static final short none = 0;
public static final short md5 = 1;
public static final short sha1 = 2;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatExtension.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatExtension.java
new file mode 100644
index 0000000..f9f3670
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatExtension.java
@@ -0,0 +1,56 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class HeartbeatExtension
+{
+ protected short mode;
+
+ public HeartbeatExtension(short mode)
+ {
+ if (!HeartbeatMode.isValid(mode))
+ {
+ throw new IllegalArgumentException("'mode' is not a valid HeartbeatMode value");
+ }
+
+ this.mode = mode;
+ }
+
+ public short getMode()
+ {
+ return mode;
+ }
+
+ /**
+ * Encode this {@link HeartbeatExtension} to an {@link OutputStream}.
+ *
+ * @param output
+ * the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output) throws IOException
+ {
+ TlsUtils.writeUint8(mode, output);
+ }
+
+ /**
+ * Parse a {@link HeartbeatExtension} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link HeartbeatExtension} object.
+ * @throws IOException
+ */
+ public static HeartbeatExtension parse(InputStream input) throws IOException
+ {
+ short mode = TlsUtils.readUint8(input);
+ if (!HeartbeatMode.isValid(mode))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return new HeartbeatExtension(mode);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessage.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessage.java
new file mode 100644
index 0000000..320a128
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessage.java
@@ -0,0 +1,108 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.io.Streams;
+
+public class HeartbeatMessage
+{
+ protected short type;
+ protected byte[] payload;
+ protected int paddingLength;
+
+ public HeartbeatMessage(short type, byte[] payload, int paddingLength)
+ {
+ if (!HeartbeatMessageType.isValid(type))
+ {
+ throw new IllegalArgumentException("'type' is not a valid HeartbeatMessageType value");
+ }
+ if (payload == null || payload.length >= (1 << 16))
+ {
+ throw new IllegalArgumentException("'payload' must have length < 2^16");
+ }
+ if (paddingLength < 16)
+ {
+ throw new IllegalArgumentException("'paddingLength' must be at least 16");
+ }
+
+ this.type = type;
+ this.payload = payload;
+ this.paddingLength = paddingLength;
+ }
+
+ /**
+ * Encode this {@link HeartbeatMessage} to an {@link OutputStream}.
+ *
+ * @param output
+ * the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(TlsContext context, OutputStream output) throws IOException
+ {
+ TlsUtils.writeUint8(type, output);
+
+ TlsUtils.checkUint16(payload.length);
+ TlsUtils.writeUint16(payload.length, output);
+ output.write(payload);
+
+ byte[] padding = new byte[paddingLength];
+ context.getSecureRandom().nextBytes(padding);
+ output.write(padding);
+ }
+
+ /**
+ * Parse a {@link HeartbeatMessage} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link HeartbeatMessage} object.
+ * @throws IOException
+ */
+ public static HeartbeatMessage parse(InputStream input) throws IOException
+ {
+ short type = TlsUtils.readUint8(input);
+ if (!HeartbeatMessageType.isValid(type))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ int payload_length = TlsUtils.readUint16(input);
+
+ PayloadBuffer buf = new PayloadBuffer();
+ Streams.pipeAll(input, buf);
+
+ byte[] payload = buf.toTruncatedByteArray(payload_length);
+ if (payload == null)
+ {
+ /*
+ * RFC 6520 4. If the payload_length of a received HeartbeatMessage is too large, the
+ * received HeartbeatMessage MUST be discarded silently.
+ */
+ return null;
+ }
+
+ int padding_length = buf.size() - payload.length;
+
+ return new HeartbeatMessage(type, payload, padding_length);
+ }
+
+ static class PayloadBuffer extends ByteArrayOutputStream
+ {
+ byte[] toTruncatedByteArray(int payloadLength)
+ {
+ /*
+ * RFC 6520 4. The padding_length MUST be at least 16.
+ */
+ int minimumCount = payloadLength + 16;
+ if (count < minimumCount)
+ {
+ return null;
+ }
+ return Arrays.copyOf(buf, payloadLength);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessageType.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessageType.java
new file mode 100644
index 0000000..f1a3b43
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMessageType.java
@@ -0,0 +1,15 @@
+package org.bouncycastle.crypto.tls;
+
+/*
+ * RFC 6520 3.
+ */
+public class HeartbeatMessageType
+{
+ public static final short heartbeat_request = 1;
+ public static final short heartbeat_response = 2;
+
+ public static boolean isValid(short heartbeatMessageType)
+ {
+ return heartbeatMessageType >= heartbeat_request && heartbeatMessageType <= heartbeat_response;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMode.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMode.java
new file mode 100644
index 0000000..4024faa
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/HeartbeatMode.java
@@ -0,0 +1,15 @@
+package org.bouncycastle.crypto.tls;
+
+/*
+ * RFC 6520
+ */
+public class HeartbeatMode
+{
+ public static final short peer_allowed_to_send = 1;
+ public static final short peer_not_allowed_to_send = 2;
+
+ public static boolean isValid(short heartbeatMode)
+ {
+ return heartbeatMode >= peer_allowed_to_send && heartbeatMode <= peer_not_allowed_to_send;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java
index c049bb7..72a944f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java
@@ -44,4 +44,9 @@ public class KeyExchangeAlgorithm
public static final int SRP = 21;
public static final int SRP_DSS = 22;
public static final int SRP_RSA = 23;
+
+ /*
+ * RFC 5489
+ */
+ public static final int ECDHE_PSK = 24;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/MACAlgorithm.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/MACAlgorithm.java
index 40ef15c..92adc8c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/MACAlgorithm.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/MACAlgorithm.java
@@ -8,7 +8,6 @@ package org.bouncycastle.crypto.tls;
*/
public class MACAlgorithm
{
-
public static final int _null = 0;
public static final int md5 = 1;
public static final int sha = 2;
@@ -21,4 +20,9 @@ public class MACAlgorithm
public static final int hmac_sha256 = 3;
public static final int hmac_sha384 = 4;
public static final int hmac_sha512 = 5;
+
+ /*
+ * TBD[draft-josefsson-salsa20-tls-02]
+ */
+ static final int umac96 = 100;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/MaxFragmentLength.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/MaxFragmentLength.java
new file mode 100644
index 0000000..413695c
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/MaxFragmentLength.java
@@ -0,0 +1,17 @@
+package org.bouncycastle.crypto.tls;
+
+public class MaxFragmentLength
+{
+ /*
+ * RFC 3546 3.2.
+ */
+ public static short pow2_9 = 1;
+ public static short pow2_10 = 2;
+ public static short pow2_11 = 3;
+ public static short pow2_12 = 4;
+
+ public static boolean isValid(short maxFragmentLength)
+ {
+ return maxFragmentLength >= pow2_9 && maxFragmentLength <= pow2_12;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/NameType.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/NameType.java
new file mode 100644
index 0000000..9b0cd1b
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/NameType.java
@@ -0,0 +1,9 @@
+package org.bouncycastle.crypto.tls;
+
+public class NameType
+{
+ /*
+ * RFC 3546 3.1.
+ */
+ public static final short host_name = 0;
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/NamedCurve.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/NamedCurve.java
index 690115c..a965d13 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/NamedCurve.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/NamedCurve.java
@@ -36,6 +36,13 @@ public class NamedCurve
public static final int secp256r1 = 23;
public static final int secp384r1 = 24;
public static final int secp521r1 = 25;
+
+ /*
+ * RFC 7027
+ */
+ public static final int brainpoolP256r1 = 26;
+ public static final int brainpoolP384r1 = 27;
+ public static final int brainpoolP512r1 = 28;
/*
* reserved (0xFE00..0xFEFF)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java
index f3d1022..8f87a65 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java
@@ -6,7 +6,6 @@ import java.io.OutputStream;
public class NewSessionTicket
{
-
protected long ticketLifetimeHint;
protected byte[] ticket;
@@ -26,6 +25,12 @@ public class NewSessionTicket
return ticket;
}
+ /**
+ * Encode this {@link NewSessionTicket} to an {@link OutputStream}.
+ *
+ * @param output the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
public void encode(OutputStream output)
throws IOException
{
@@ -33,6 +38,13 @@ public class NewSessionTicket
TlsUtils.writeOpaque16(ticket, output);
}
+ /**
+ * Parse a {@link NewSessionTicket} from an {@link InputStream}.
+ *
+ * @param input the {@link InputStream} to parse from.
+ * @return a {@link NewSessionTicket} object.
+ * @throws IOException
+ */
public static NewSessionTicket parse(InputStream input)
throws IOException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/OCSPStatusRequest.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/OCSPStatusRequest.java
new file mode 100644
index 0000000..db8168f
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/OCSPStatusRequest.java
@@ -0,0 +1,131 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ocsp.ResponderID;
+import org.bouncycastle.asn1.x509.Extensions;
+
+/**
+ * RFC 3546 3.6
+ */
+public class OCSPStatusRequest
+{
+ protected Vector responderIDList;
+ protected Extensions requestExtensions;
+
+ /**
+ * @param responderIDList
+ * a {@link Vector} of {@link ResponderID}, specifying the list of trusted OCSP
+ * responders. An empty list has the special meaning that the responders are
+ * implicitly known to the server - e.g., by prior arrangement.
+ * @param requestExtensions
+ * OCSP request extensions. A null value means that there are no extensions.
+ */
+ public OCSPStatusRequest(Vector responderIDList, Extensions requestExtensions)
+ {
+ this.responderIDList = responderIDList;
+ this.requestExtensions = requestExtensions;
+ }
+
+ /**
+ * @return a {@link Vector} of {@link ResponderID}
+ */
+ public Vector getResponderIDList()
+ {
+ return responderIDList;
+ }
+
+ /**
+ * @return OCSP request extensions
+ */
+ public Extensions getRequestExtensions()
+ {
+ return requestExtensions;
+ }
+
+ /**
+ * Encode this {@link OCSPStatusRequest} to an {@link OutputStream}.
+ *
+ * @param output
+ * the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output) throws IOException
+ {
+ if (responderIDList == null || responderIDList.isEmpty())
+ {
+ TlsUtils.writeUint16(0, output);
+ }
+ else
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ for (int i = 0; i < responderIDList.size(); ++i)
+ {
+ ResponderID responderID = (ResponderID) responderIDList.elementAt(i);
+ byte[] derEncoding = responderID.getEncoded(ASN1Encoding.DER);
+ TlsUtils.writeOpaque16(derEncoding, buf);
+ }
+ TlsUtils.checkUint16(buf.size());
+ TlsUtils.writeUint16(buf.size(), output);
+ buf.writeTo(output);
+ }
+
+ if (requestExtensions == null)
+ {
+ TlsUtils.writeUint16(0, output);
+ }
+ else
+ {
+ byte[] derEncoding = requestExtensions.getEncoded(ASN1Encoding.DER);
+ TlsUtils.checkUint16(derEncoding.length);
+ TlsUtils.writeUint16(derEncoding.length, output);
+ output.write(derEncoding);
+ }
+ }
+
+ /**
+ * Parse a {@link OCSPStatusRequest} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link OCSPStatusRequest} object.
+ * @throws IOException
+ */
+ public static OCSPStatusRequest parse(InputStream input) throws IOException
+ {
+ Vector responderIDList = new Vector();
+ {
+ int length = TlsUtils.readUint16(input);
+ if (length > 0)
+ {
+ byte[] data = TlsUtils.readFully(length, input);
+ ByteArrayInputStream buf = new ByteArrayInputStream(data);
+ do
+ {
+ byte[] derEncoding = TlsUtils.readOpaque16(buf);
+ ResponderID responderID = ResponderID.getInstance(TlsUtils.readDERObject(derEncoding));
+ responderIDList.addElement(responderID);
+ }
+ while (buf.available() > 0);
+ }
+ }
+
+ Extensions requestExtensions = null;
+ {
+ int length = TlsUtils.readUint16(input);
+ if (length > 0)
+ {
+ byte[] derEncoding = TlsUtils.readFully(length, input);
+ requestExtensions = Extensions.getInstance(TlsUtils.readDERObject(derEncoding));
+ }
+ }
+
+ return new OCSPStatusRequest(responderIDList, requestExtensions);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/PSKTlsClient.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/PSKTlsClient.java
index 29750cb..92475b2 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/PSKTlsClient.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/PSKTlsClient.java
@@ -21,41 +21,89 @@ public abstract class PSKTlsClient
public int[] getCipherSuites()
{
- return new int[]{CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA, CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA,
- CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA, CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA,
- CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA, CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA, CipherSuite.TLS_PSK_WITH_RC4_128_SHA,};
+ return new int[] { CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA };
}
- public TlsKeyExchange getKeyExchange()
- throws IOException
+ public TlsKeyExchange getKeyExchange() throws IOException
{
-
switch (selectedCipherSuite)
{
+ case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+ return createPSKKeyExchange(KeyExchangeAlgorithm.DHE_PSK);
+
+ case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_UMAC96:
+ return createPSKKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK);
+
case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_UMAC96:
case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_SALSA20_UMAC96:
return createPSKKeyExchange(KeyExchangeAlgorithm.PSK);
case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_UMAC96:
case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_UMAC96:
return createPSKKeyExchange(KeyExchangeAlgorithm.RSA_PSK);
- case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
- return createPSKKeyExchange(KeyExchangeAlgorithm.DHE_PSK);
-
default:
/*
* Note: internal error here; the TlsProtocol implementation verifies that the
@@ -66,37 +114,114 @@ public abstract class PSKTlsClient
}
}
- public TlsCipher getCipher()
- throws IOException
+ public TlsCipher getCipher() throws IOException
{
-
switch (selectedCipherSuite)
{
+ case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, MACAlgorithm.hmac_sha1);
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha1);
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, MACAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CCM_8, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha1);
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, MACAlgorithm.hmac_sha384);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CCM_8, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_GCM, MACAlgorithm._null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_UMAC96:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.umac96);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
case CipherSuite.TLS_PSK_WITH_NULL_SHA:
case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha1);
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_sha384);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
- case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
return cipherFactory.createCipher(context, EncryptionAlgorithm.RC4_128, MACAlgorithm.hmac_sha1);
+ case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_PSK_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_UMAC96:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.umac96);
+
default:
/*
* Note: internal error here; the TlsProtocol implementation verifies that the
@@ -109,6 +234,7 @@ public abstract class PSKTlsClient
protected TlsKeyExchange createPSKKeyExchange(int keyExchange)
{
- return new TlsPSKKeyExchange(keyExchange, supportedSignatureAlgorithms, pskIdentity);
+ return new TlsPSKKeyExchange(keyExchange, supportedSignatureAlgorithms, pskIdentity, null, namedCurves,
+ clientECPointFormats, serverECPointFormats);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ProtocolVersion.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ProtocolVersion.java
index c001e58..b32bd9d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ProtocolVersion.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ProtocolVersion.java
@@ -4,7 +4,6 @@ import java.io.IOException;
public final class ProtocolVersion
{
-
public static final ProtocolVersion SSLv3 = new ProtocolVersion(0x0300, "SSL 3.0");
public static final ProtocolVersion TLSv10 = new ProtocolVersion(0x0301, "TLS 1.0");
public static final ProtocolVersion TLSv11 = new ProtocolVersion(0x0302, "TLS 1.1");
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/RecordStream.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/RecordStream.java
index 3a31c20..cc6640b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/RecordStream.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/RecordStream.java
@@ -12,10 +12,7 @@ import org.bouncycastle.crypto.Digest;
*/
class RecordStream
{
-
- private static int PLAINTEXT_LIMIT = (1 << 14);
- private static int COMPRESSED_LIMIT = PLAINTEXT_LIMIT + 1024;
- private static int CIPHERTEXT_LIMIT = COMPRESSED_LIMIT + 1024;
+ private static int DEFAULT_PLAINTEXT_LIMIT = (1 << 14);
private TlsProtocol handler;
private InputStream input;
@@ -26,11 +23,13 @@ class RecordStream
private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private TlsContext context = null;
- private TlsHandshakeHash hash = null;
+ private TlsHandshakeHash handshakeHash = null;
private ProtocolVersion readVersion = null, writeVersion = null;
private boolean restrictReadVersion = true;
+ private int plaintextLimit, compressedLimit, ciphertextLimit;
+
RecordStream(TlsProtocol handler, InputStream input, OutputStream output)
{
this.handler = handler;
@@ -40,13 +39,27 @@ class RecordStream
this.writeCompression = this.readCompression;
this.readCipher = new TlsNullCipher(context);
this.writeCipher = this.readCipher;
+
+ setPlaintextLimit(DEFAULT_PLAINTEXT_LIMIT);
}
void init(TlsContext context)
{
this.context = context;
- this.hash = new DeferredHash();
- this.hash.init(context);
+ this.handshakeHash = new DeferredHash();
+ this.handshakeHash.init(context);
+ }
+
+ int getPlaintextLimit()
+ {
+ return plaintextLimit;
+ }
+
+ void setPlaintextLimit(int plaintextLimit)
+ {
+ this.plaintextLimit = plaintextLimit;
+ this.compressedLimit = this.plaintextLimit + 1024;
+ this.ciphertextLimit = this.compressedLimit + 1024;
}
ProtocolVersion getReadVersion()
@@ -76,11 +89,6 @@ class RecordStream
this.restrictReadVersion = enabled;
}
- void notifyHelloComplete()
- {
- this.hash = this.hash.commit();
- }
-
void setPendingConnectionState(TlsCompression tlsCompression, TlsCipher tlsCipher)
{
this.pendingCompression = tlsCompression;
@@ -123,13 +131,17 @@ class RecordStream
pendingCipher = null;
}
- public void readRecord()
+ public boolean readRecord()
throws IOException
{
+ byte[] recordHeader = TlsUtils.readAllOrNothing(5, input);
+ if (recordHeader == null)
+ {
+ return false;
+ }
- short type = TlsUtils.readUint8(input);
+ short type = TlsUtils.readUint8(recordHeader, 0);
- // TODO In earlier RFCs, it was "SHOULD ignore"; should this be version-dependent?
/*
* RFC 5246 6. If a TLS implementation receives an unexpected record type, it MUST send an
* unexpected_message alert.
@@ -138,7 +150,7 @@ class RecordStream
if (!restrictReadVersion)
{
- int version = TlsUtils.readVersionRaw(input);
+ int version = TlsUtils.readVersionRaw(recordHeader, 1);
if ((version & 0xffffff00) != 0x0300)
{
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
@@ -146,7 +158,7 @@ class RecordStream
}
else
{
- ProtocolVersion version = TlsUtils.readVersion(input);
+ ProtocolVersion version = TlsUtils.readVersion(recordHeader, 1);
if (readVersion == null)
{
readVersion = version;
@@ -157,21 +169,21 @@ class RecordStream
}
}
- int length = TlsUtils.readUint16(input);
+ int length = TlsUtils.readUint16(recordHeader, 3);
byte[] plaintext = decodeAndVerify(type, input, length);
handler.processRecord(type, plaintext, 0, plaintext.length);
+ return true;
}
protected byte[] decodeAndVerify(short type, InputStream input, int len)
throws IOException
{
-
- checkLength(len, CIPHERTEXT_LIMIT, AlertDescription.record_overflow);
+ checkLength(len, ciphertextLimit, AlertDescription.record_overflow);
byte[] buf = TlsUtils.readFully(len, input);
byte[] decoded = readCipher.decodeCiphertext(readSeqNo++, type, buf, 0, buf.length);
- checkLength(decoded.length, COMPRESSED_LIMIT, AlertDescription.record_overflow);
+ checkLength(decoded.length, compressedLimit, AlertDescription.record_overflow);
/*
* TODO RFC5264 6.2.2. Implementation note: Decompression functions are responsible for
@@ -190,7 +202,16 @@ class RecordStream
* would decompress to a length in excess of 2^14 bytes, it should report a fatal
* decompression failure error.
*/
- checkLength(decoded.length, PLAINTEXT_LIMIT, AlertDescription.decompression_failure);
+ checkLength(decoded.length, plaintextLimit, AlertDescription.decompression_failure);
+
+ /*
+ * RFC 5264 6.2.1 Implementations MUST NOT send zero-length fragments of Handshake, Alert,
+ * or ChangeCipherSpec content types.
+ */
+ if (decoded.length < 1 && type != ContentType.application_data)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
return decoded;
}
@@ -198,7 +219,6 @@ class RecordStream
protected void writeRecord(short type, byte[] plaintext, int plaintextOffset, int plaintextLength)
throws IOException
{
-
/*
* RFC 5264 6. Implementations MUST NOT send record types not defined in this document
* unless negotiated by some extension.
@@ -208,7 +228,7 @@ class RecordStream
/*
* RFC 5264 6.2.1 The length should not exceed 2^14.
*/
- checkLength(plaintextLength, PLAINTEXT_LIMIT, AlertDescription.internal_error);
+ checkLength(plaintextLength, plaintextLimit, AlertDescription.internal_error);
/*
* RFC 5264 6.2.1 Implementations MUST NOT send zero-length fragments of Handshake, Alert,
@@ -249,7 +269,7 @@ class RecordStream
/*
* RFC 5264 6.2.3. The length may not exceed 2^14 + 2048.
*/
- checkLength(ciphertext.length, CIPHERTEXT_LIMIT, AlertDescription.internal_error);
+ checkLength(ciphertext.length, ciphertextLimit, AlertDescription.internal_error);
byte[] record = new byte[ciphertext.length + 5];
TlsUtils.writeUint8(type, record, 0);
@@ -260,52 +280,44 @@ class RecordStream
output.flush();
}
- void updateHandshakeData(byte[] message, int offset, int len)
+ void notifyHelloComplete()
{
- hash.update(message, offset, len);
+ this.handshakeHash = handshakeHash.notifyPRFDetermined();
}
- /**
- * 'sender' only relevant to SSLv3
- */
- byte[] getCurrentHash(byte[] sender)
+ TlsHandshakeHash getHandshakeHash()
{
- TlsHandshakeHash d = hash.fork();
+ return handshakeHash;
+ }
- if (context.getServerVersion().isSSL())
- {
- if (sender != null)
- {
- d.update(sender, 0, sender.length);
- }
- }
+ TlsHandshakeHash prepareToFinish()
+ {
+ TlsHandshakeHash result = handshakeHash;
+ this.handshakeHash = handshakeHash.stopTracking();
+ return result;
+ }
- return doFinal(d);
+ void updateHandshakeData(byte[] message, int offset, int len)
+ {
+ handshakeHash.update(message, offset, len);
}
- protected void close()
- throws IOException
+ protected void safeClose()
{
- IOException e = null;
try
{
input.close();
}
- catch (IOException ex)
+ catch (IOException e)
{
- e = ex;
}
+
try
{
output.close();
}
- catch (IOException ex)
- {
- e = ex;
- }
- if (e != null)
+ catch (IOException e)
{
- throw e;
}
}
@@ -322,23 +334,16 @@ class RecordStream
return contents;
}
- private static byte[] doFinal(Digest d)
- {
- byte[] bs = new byte[d.getDigestSize()];
- d.doFinal(bs, 0);
- return bs;
- }
-
private static void checkType(short type, short alertDescription)
throws IOException
{
-
switch (type)
{
- case ContentType.change_cipher_spec:
+ case ContentType.application_data:
case ContentType.alert:
+ case ContentType.change_cipher_spec:
case ContentType.handshake:
- case ContentType.application_data:
+ case ContentType.heartbeat:
break;
default:
throw new TlsFatalAlert(alertDescription);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SRPTlsClient.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SRPTlsClient.java
index a5d4840..15295ea 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SRPTlsClient.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SRPTlsClient.java
@@ -1,16 +1,17 @@
package org.bouncycastle.crypto.tls;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Hashtable;
import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Integers;
public abstract class SRPTlsClient
extends AbstractTlsClient
{
- public static final Integer EXT_SRP = Integers.valueOf(ExtensionType.srp);
+ /**
+ * @deprecated use TlsSRPUtils.EXT_SRP instead
+ */
+ public static final Integer EXT_SRP = TlsSRPUtils.EXT_SRP;
protected byte[] identity;
protected byte[] password;
@@ -31,40 +32,23 @@ public abstract class SRPTlsClient
public int[] getCipherSuites()
{
- return new int[]{CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,};
+ return new int[] { CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA };
}
public Hashtable getClientExtensions()
throws IOException
{
-
- Hashtable clientExtensions = super.getClientExtensions();
- if (clientExtensions == null)
- {
- clientExtensions = new Hashtable();
- }
-
- ByteArrayOutputStream srpData = new ByteArrayOutputStream();
- TlsUtils.writeOpaque8(this.identity, srpData);
- clientExtensions.put(EXT_SRP, srpData.toByteArray());
-
+ Hashtable clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(super.getClientExtensions());
+ TlsSRPUtils.addSRPExtension(clientExtensions, this.identity);
return clientExtensions;
}
public void processServerExtensions(Hashtable serverExtensions)
throws IOException
{
- // No explicit guidance in RFC 5054 here; we allow an optional empty extension from server
- if (serverExtensions != null)
+ if (!TlsUtils.hasExpectedEmptyExtensionData(serverExtensions, TlsSRPUtils.EXT_SRP, AlertDescription.illegal_parameter))
{
- byte[] extValue = (byte[])serverExtensions.get(EXT_SRP);
- if (extValue != null && extValue.length > 0)
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
+ // No explicit guidance in RFC 5054 here; we allow an optional empty extension from server
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java
index a7701fe..984246e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java
@@ -1,16 +1,41 @@
package org.bouncycastle.crypto.tls;
+import org.bouncycastle.util.Arrays;
+
public class SecurityParameters
{
-
int entity = -1;
- int prfAlgorithm = -1;
+ int cipherSuite = -1;
short compressionAlgorithm = -1;
+ int prfAlgorithm = -1;
int verifyDataLength = -1;
byte[] masterSecret = null;
byte[] clientRandom = null;
byte[] serverRandom = null;
+ // TODO Keep these internal, since it's maybe not the ideal place for them
+ short maxFragmentLength = -1;
+ boolean truncatedHMac = false;
+
+ void copySessionParametersFrom(SecurityParameters other)
+ {
+ this.entity = other.entity;
+ this.cipherSuite = other.cipherSuite;
+ this.compressionAlgorithm = other.compressionAlgorithm;
+ this.prfAlgorithm = other.prfAlgorithm;
+ this.verifyDataLength = other.verifyDataLength;
+ this.masterSecret = Arrays.clone(other.masterSecret);
+ }
+
+ void clear()
+ {
+ if (this.masterSecret != null)
+ {
+ Arrays.fill(this.masterSecret, (byte)0);
+ this.masterSecret = null;
+ }
+ }
+
/**
* @return {@link ConnectionEnd}
*/
@@ -20,11 +45,11 @@ public class SecurityParameters
}
/**
- * @return {@link PRFAlgorithm}
+ * @return {@link CipherSuite}
*/
- public int getPrfAlgorithm()
+ public int getCipherSuite()
{
- return prfAlgorithm;
+ return cipherSuite;
}
/**
@@ -35,6 +60,14 @@ public class SecurityParameters
return compressionAlgorithm;
}
+ /**
+ * @return {@link PRFAlgorithm}
+ */
+ public int getPrfAlgorithm()
+ {
+ return prfAlgorithm;
+ }
+
public int getVerifyDataLength()
{
return verifyDataLength;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerDHParams.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerDHParams.java
new file mode 100644
index 0000000..c3050f1
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerDHParams.java
@@ -0,0 +1,63 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.params.DHParameters;
+import org.bouncycastle.crypto.params.DHPublicKeyParameters;
+
+public class ServerDHParams
+{
+ protected DHPublicKeyParameters publicKey;
+
+ public ServerDHParams(DHPublicKeyParameters publicKey)
+ {
+ if (publicKey == null)
+ {
+ throw new IllegalArgumentException("'publicKey' cannot be null");
+ }
+
+ this.publicKey = publicKey;
+ }
+
+ public DHPublicKeyParameters getPublicKey()
+ {
+ return publicKey;
+ }
+
+ /**
+ * Encode this {@link ServerDHParams} to an {@link OutputStream}.
+ *
+ * @param output
+ * the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output) throws IOException
+ {
+ DHParameters dhParameters = publicKey.getParameters();
+ BigInteger Ys = publicKey.getY();
+
+ TlsDHUtils.writeDHParameter(dhParameters.getP(), output);
+ TlsDHUtils.writeDHParameter(dhParameters.getG(), output);
+ TlsDHUtils.writeDHParameter(Ys, output);
+ }
+
+ /**
+ * Parse a {@link ServerDHParams} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link ServerDHParams} object.
+ * @throws IOException
+ */
+ public static ServerDHParams parse(InputStream input) throws IOException
+ {
+ BigInteger p = TlsDHUtils.readDHParameter(input);
+ BigInteger g = TlsDHUtils.readDHParameter(input);
+ BigInteger Ys = TlsDHUtils.readDHParameter(input);
+
+ return new ServerDHParams(new DHPublicKeyParameters(Ys, new DHParameters(p, g)));
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerName.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerName.java
new file mode 100644
index 0000000..df9a439
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerName.java
@@ -0,0 +1,112 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.bouncycastle.util.Strings;
+
+public class ServerName
+{
+ protected short nameType;
+ protected Object name;
+
+ public ServerName(short nameType, Object name)
+ {
+ if (!isCorrectType(nameType, name))
+ {
+ throw new IllegalArgumentException("'name' is not an instance of the correct type");
+ }
+
+ this.nameType = nameType;
+ this.name = name;
+ }
+
+ public short getNameType()
+ {
+ return nameType;
+ }
+
+ public Object getName()
+ {
+ return name;
+ }
+
+ public String getHostName()
+ {
+ if (!isCorrectType(NameType.host_name, name))
+ {
+ throw new IllegalStateException("'name' is not a HostName string");
+ }
+ return (String)name;
+ }
+
+ /**
+ * Encode this {@link ServerName} to an {@link OutputStream}.
+ *
+ * @param output
+ * the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output) throws IOException
+ {
+ TlsUtils.writeUint8(nameType, output);
+
+ switch (nameType)
+ {
+ case NameType.host_name:
+ byte[] utf8Encoding = Strings.toUTF8ByteArray((String)name);
+ if (utf8Encoding.length < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ TlsUtils.writeOpaque16(utf8Encoding, output);
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ /**
+ * Parse a {@link ServerName} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link ServerName} object.
+ * @throws IOException
+ */
+ public static ServerName parse(InputStream input) throws IOException
+ {
+ short name_type = TlsUtils.readUint8(input);
+ Object name;
+
+ switch (name_type)
+ {
+ case NameType.host_name:
+ {
+ byte[] utf8Encoding = TlsUtils.readOpaque16(input);
+ if (utf8Encoding.length < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ name = Strings.fromUTF8ByteArray(utf8Encoding);
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ return new ServerName(name_type, name);
+ }
+
+ protected static boolean isCorrectType(short nameType, Object name)
+ {
+ switch (nameType)
+ {
+ case NameType.host_name:
+ return name instanceof String;
+ default:
+ throw new IllegalArgumentException("'name' is an unsupported value");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerNameList.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerNameList.java
new file mode 100644
index 0000000..1dc81f0
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/ServerNameList.java
@@ -0,0 +1,86 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+public class ServerNameList
+{
+ protected Vector serverNameList;
+
+ /**
+ * @param serverNameList a {@link Vector} of {@link ServerName}.
+ */
+ public ServerNameList(Vector serverNameList)
+ {
+ if (serverNameList == null || serverNameList.isEmpty())
+ {
+ throw new IllegalArgumentException("'serverNameList' must not be null or empty");
+ }
+
+ this.serverNameList = serverNameList;
+ }
+
+ /**
+ * @return a {@link Vector} of {@link ServerName}.
+ */
+ public Vector getServerNameList()
+ {
+ return serverNameList;
+ }
+
+ /**
+ * Encode this {@link ServerNameList} to an {@link OutputStream}.
+ *
+ * @param output
+ * the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output) throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ for (int i = 0; i < serverNameList.size(); ++i)
+ {
+ ServerName entry = (ServerName)serverNameList.elementAt(i);
+ entry.encode(buf);
+ }
+
+ TlsUtils.checkUint16(buf.size());
+ TlsUtils.writeUint16(buf.size(), output);
+ buf.writeTo(output);
+ }
+
+ /**
+ * Parse a {@link ServerNameList} from an {@link InputStream}.
+ *
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link ServerNameList} object.
+ * @throws IOException
+ */
+ public static ServerNameList parse(InputStream input) throws IOException
+ {
+ int length = TlsUtils.readUint16(input);
+ if (length < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ byte[] data = TlsUtils.readFully(length, input);
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(data);
+
+ Vector server_name_list = new Vector();
+ while (buf.available() > 0)
+ {
+ ServerName entry = ServerName.parse(buf);
+ server_name_list.addElement(entry);
+ }
+
+ return new ServerNameList(server_name_list);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SessionParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SessionParameters.java
new file mode 100644
index 0000000..68412f8
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SessionParameters.java
@@ -0,0 +1,142 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.bouncycastle.util.Arrays;
+
+public final class SessionParameters
+{
+ public static final class Builder
+ {
+ private int cipherSuite = -1;
+ private short compressionAlgorithm = -1;
+ private byte[] masterSecret = null;
+ private Certificate peerCertificate = null;
+ private byte[] encodedServerExtensions = null;
+
+ public Builder()
+ {
+ }
+
+ public SessionParameters build()
+ {
+ validate(this.cipherSuite >= 0, "cipherSuite");
+ validate(this.compressionAlgorithm >= 0, "compressionAlgorithm");
+ validate(this.masterSecret != null, "masterSecret");
+ return new SessionParameters(cipherSuite, compressionAlgorithm, masterSecret, peerCertificate,
+ encodedServerExtensions);
+ }
+
+ public Builder setCipherSuite(int cipherSuite)
+ {
+ this.cipherSuite = cipherSuite;
+ return this;
+ }
+
+ public Builder setCompressionAlgorithm(short compressionAlgorithm)
+ {
+ this.compressionAlgorithm = compressionAlgorithm;
+ return this;
+ }
+
+ public Builder setMasterSecret(byte[] masterSecret)
+ {
+ this.masterSecret = masterSecret;
+ return this;
+ }
+
+ public Builder setPeerCertificate(Certificate peerCertificate)
+ {
+ this.peerCertificate = peerCertificate;
+ return this;
+ }
+
+ public Builder setServerExtensions(Hashtable serverExtensions)
+ throws IOException
+ {
+ if (serverExtensions == null)
+ {
+ encodedServerExtensions = null;
+ }
+ else
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ TlsProtocol.writeExtensions(buf, serverExtensions);
+ encodedServerExtensions = buf.toByteArray();
+ }
+ return this;
+ }
+
+ private void validate(boolean condition, String parameter)
+ {
+ if (!condition)
+ {
+ throw new IllegalStateException("Required session parameter '" + parameter + "' not configured");
+ }
+ }
+ }
+
+ private int cipherSuite;
+ private short compressionAlgorithm;
+ private byte[] masterSecret;
+ private Certificate peerCertificate;
+ private byte[] encodedServerExtensions;
+
+ private SessionParameters(int cipherSuite, short compressionAlgorithm, byte[] masterSecret,
+ Certificate peerCertificate, byte[] encodedServerExtensions)
+ {
+ this.cipherSuite = cipherSuite;
+ this.compressionAlgorithm = compressionAlgorithm;
+ this.masterSecret = Arrays.clone(masterSecret);
+ this.peerCertificate = peerCertificate;
+ this.encodedServerExtensions = encodedServerExtensions;
+ }
+
+ public void clear()
+ {
+ if (this.masterSecret != null)
+ {
+ Arrays.fill(this.masterSecret, (byte)0);
+ }
+ }
+
+ public SessionParameters copy()
+ {
+ return new SessionParameters(cipherSuite, compressionAlgorithm, masterSecret, peerCertificate,
+ encodedServerExtensions);
+ }
+
+ public int getCipherSuite()
+ {
+ return cipherSuite;
+ }
+
+ public short getCompressionAlgorithm()
+ {
+ return compressionAlgorithm;
+ }
+
+ public byte[] getMasterSecret()
+ {
+ return masterSecret;
+ }
+
+ public Certificate getPeerCertificate()
+ {
+ return peerCertificate;
+ }
+
+ public Hashtable readServerExtensions() throws IOException
+ {
+ if (encodedServerExtensions == null)
+ {
+ return null;
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(encodedServerExtensions);
+ return TlsProtocol.readExtensions(buf);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SignatureAndHashAlgorithm.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SignatureAndHashAlgorithm.java
index 7ad4644..a5a591e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SignatureAndHashAlgorithm.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SignatureAndHashAlgorithm.java
@@ -9,9 +9,8 @@ import java.io.OutputStream;
*/
public class SignatureAndHashAlgorithm
{
-
- private short hash;
- private short signature;
+ protected short hash;
+ protected short signature;
/**
* @param hash {@link HashAlgorithm}
@@ -19,7 +18,6 @@ public class SignatureAndHashAlgorithm
*/
public SignatureAndHashAlgorithm(short hash, short signature)
{
-
if (!TlsUtils.isValidUint8(hash))
{
throw new IllegalArgumentException("'hash' should be a uint8");
@@ -65,7 +63,7 @@ public class SignatureAndHashAlgorithm
public int hashCode()
{
- return (getHash() << 8) | getSignature();
+ return (getHash() << 16) | getSignature();
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SignerInputBuffer.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SignerInputBuffer.java
new file mode 100644
index 0000000..8293135
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SignerInputBuffer.java
@@ -0,0 +1,13 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+
+import org.bouncycastle.crypto.Signer;
+
+class SignerInputBuffer extends ByteArrayOutputStream
+{
+ void updateSigner(Signer s)
+ {
+ s.update(this.buf, 0, count);
+ }
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataEntry.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataEntry.java
index 5a71f9b..4080aaa 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataEntry.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/SupplementalDataEntry.java
@@ -2,19 +2,18 @@ package org.bouncycastle.crypto.tls;
public class SupplementalDataEntry
{
+ protected int dataType;
+ protected byte[] data;
- private int supp_data_type;
- private byte[] data;
-
- public SupplementalDataEntry(int supp_data_type, byte[] data)
+ public SupplementalDataEntry(int dataType, byte[] data)
{
- this.supp_data_type = supp_data_type;
+ this.dataType = dataType;
this.data = data;
}
public int getDataType()
{
- return supp_data_type;
+ return dataType;
}
public byte[] getData()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsAEADCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsAEADCipher.java
index dbf9d79..bb9306a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsAEADCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsAEADCipher.java
@@ -10,7 +10,6 @@ import org.bouncycastle.util.Arrays;
public class TlsAEADCipher
implements TlsCipher
{
-
protected TlsContext context;
protected int macSize;
protected int nonce_explicit_length;
@@ -21,11 +20,9 @@ public class TlsAEADCipher
protected byte[] encryptImplicitNonce, decryptImplicitNonce;
public TlsAEADCipher(TlsContext context, AEADBlockCipher clientWriteCipher, AEADBlockCipher serverWriteCipher,
- int cipherKeySize, int macSize)
- throws IOException
+ int cipherKeySize, int macSize) throws IOException
{
-
- if (!ProtocolVersion.TLSv12.isEqualOrEarlierVersionOf(context.getServerVersion().getEquivalentTLSVersion()))
+ if (!TlsUtils.isTLSv12(context))
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
@@ -33,7 +30,7 @@ public class TlsAEADCipher
this.context = context;
this.macSize = macSize;
- // NOTE: Valid for RFC 5288 ciphers but may need review for other AEAD ciphers
+ // NOTE: Valid for RFC 5288/6655 ciphers but may need review for other AEAD ciphers
this.nonce_explicit_length = 8;
// TODO SecurityParameters.fixed_iv_length
@@ -94,12 +91,11 @@ public class TlsAEADCipher
public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len)
throws IOException
{
-
byte[] nonce = new byte[this.encryptImplicitNonce.length + nonce_explicit_length];
System.arraycopy(encryptImplicitNonce, 0, nonce, 0, encryptImplicitNonce.length);
/*
- * RFC 5288 The nonce_explicit MAY be the 64-bit sequence number.
+ * RFC 5288/6655 The nonce_explicit MAY be the 64-bit sequence number.
*
* (May need review for other AEAD ciphers).
*/
@@ -113,12 +109,13 @@ public class TlsAEADCipher
System.arraycopy(nonce, encryptImplicitNonce.length, output, 0, nonce_explicit_length);
int outputPos = nonce_explicit_length;
- encryptCipher.init(true,
- new AEADParameters(null, 8 * macSize, nonce, getAdditionalData(seqNo, type, plaintextLength)));
+ byte[] additionalData = getAdditionalData(seqNo, type, plaintextLength);
+ AEADParameters parameters = new AEADParameters(null, 8 * macSize, nonce, additionalData);
- outputPos += encryptCipher.processBytes(plaintext, plaintextOffset, plaintextLength, output, outputPos);
try
{
+ encryptCipher.init(true, parameters);
+ outputPos += encryptCipher.processBytes(plaintext, plaintextOffset, plaintextLength, output, outputPos);
outputPos += encryptCipher.doFinal(output, outputPos);
}
catch (Exception e)
@@ -138,7 +135,6 @@ public class TlsAEADCipher
public byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len)
throws IOException
{
-
if (getPlaintextLimit(len) < 0)
{
throw new TlsFatalAlert(AlertDescription.decode_error);
@@ -155,13 +151,13 @@ public class TlsAEADCipher
byte[] output = new byte[plaintextLength];
int outputPos = 0;
- decryptCipher.init(false,
- new AEADParameters(null, 8 * macSize, nonce, getAdditionalData(seqNo, type, plaintextLength)));
-
- outputPos += decryptCipher.processBytes(ciphertext, ciphertextOffset, ciphertextLength, output, outputPos);
+ byte[] additionalData = getAdditionalData(seqNo, type, plaintextLength);
+ AEADParameters parameters = new AEADParameters(null, 8 * macSize, nonce, additionalData);
try
{
+ decryptCipher.init(false, parameters);
+ outputPos += decryptCipher.processBytes(ciphertext, ciphertextOffset, ciphertextLength, output, outputPos);
outputPos += decryptCipher.doFinal(output, outputPos);
}
catch (Exception e)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsBlockCipher.java
index 0b218c1..2f9e8a9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsBlockCipher.java
@@ -16,6 +16,7 @@ import org.bouncycastle.util.Arrays;
public class TlsBlockCipher
implements TlsCipher
{
+ private static boolean encryptThenMAC = false;
protected TlsContext context;
protected byte[] randomData;
@@ -38,17 +39,14 @@ public class TlsBlockCipher
}
public TlsBlockCipher(TlsContext context, BlockCipher clientWriteCipher, BlockCipher serverWriteCipher,
- Digest clientWriteDigest, Digest serverWriteDigest, int cipherKeySize)
- throws IOException
+ Digest clientWriteDigest, Digest serverWriteDigest, int cipherKeySize) throws IOException
{
-
this.context = context;
this.randomData = new byte[256];
context.getSecureRandom().nextBytes(randomData);
- this.useExplicitIV = ProtocolVersion.TLSv11.isEqualOrEarlierVersionOf(context.getServerVersion()
- .getEquivalentTLSVersion());
+ this.useExplicitIV = TlsUtils.isTLSv11(context);
int key_block_size = (2 * cipherKeySize) + clientWriteDigest.getDigestSize()
+ serverWriteDigest.getDigestSize();
@@ -123,13 +121,30 @@ public class TlsBlockCipher
int blockSize = encryptCipher.getBlockSize();
int macSize = writeMac.getSize();
- int result = ciphertextLimit - (ciphertextLimit % blockSize) - macSize - 1;
+ int plaintextLimit = ciphertextLimit;
+
+ // An explicit IV consumes 1 block
if (useExplicitIV)
{
- result -= blockSize;
+ plaintextLimit -= blockSize;
}
- return result;
+ // Leave room for the MAC, and require block-alignment
+ if (encryptThenMAC)
+ {
+ plaintextLimit -= macSize;
+ plaintextLimit -= plaintextLimit % blockSize;
+ }
+ else
+ {
+ plaintextLimit -= plaintextLimit % blockSize;
+ plaintextLimit -= macSize;
+ }
+
+ // Minimum 1 byte of padding
+ --plaintextLimit;
+
+ return plaintextLimit;
}
public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len)
@@ -139,7 +154,13 @@ public class TlsBlockCipher
ProtocolVersion version = context.getServerVersion();
- int padding_length = blockSize - 1 - ((len + macSize) % blockSize);
+ int enc_input_length = len;
+ if (!encryptThenMAC)
+ {
+ enc_input_length += macSize;
+ }
+
+ int padding_length = blockSize - 1 - (enc_input_length % blockSize);
// TODO[DTLS] Consider supporting in DTLS (without exceeding send limit though)
if (!version.isDTLS() && !version.isSSL())
@@ -156,7 +177,7 @@ public class TlsBlockCipher
totalSize += blockSize;
}
- byte[] outbuf = new byte[totalSize];
+ byte[] outBuf = new byte[totalSize];
int outOff = 0;
if (useExplicitIV)
@@ -166,25 +187,42 @@ public class TlsBlockCipher
encryptCipher.init(true, new ParametersWithIV(null, explicitIV));
- System.arraycopy(explicitIV, 0, outbuf, outOff, blockSize);
+ System.arraycopy(explicitIV, 0, outBuf, outOff, blockSize);
outOff += blockSize;
}
- byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
+ int blocks_start = outOff;
+
+ System.arraycopy(plaintext, offset, outBuf, outOff, len);
+ outOff += len;
- System.arraycopy(plaintext, offset, outbuf, outOff, len);
- System.arraycopy(mac, 0, outbuf, outOff + len, mac.length);
+ if (!encryptThenMAC)
+ {
+ byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
+ System.arraycopy(mac, 0, outBuf, outOff, mac.length);
+ outOff += mac.length;
+ }
- int padOffset = outOff + len + mac.length;
for (int i = 0; i <= padding_length; i++)
{
- outbuf[i + padOffset] = (byte)padding_length;
+ outBuf[outOff++] = (byte)padding_length;
}
- for (int i = outOff; i < totalSize; i += blockSize)
+
+ for (int i = blocks_start; i < outOff; i += blockSize)
{
- encryptCipher.processBlock(outbuf, i, outbuf, i);
+ encryptCipher.processBlock(outBuf, i, outBuf, i);
}
- return outbuf;
+
+ if (encryptThenMAC)
+ {
+ byte[] mac = writeMac.calculateMac(seqNo, type, outBuf, 0, outOff);
+ System.arraycopy(mac, 0, outBuf, outOff, mac.length);
+ outOff += mac.length;
+ }
+
+// assert outBuf.length == outOff;
+
+ return outBuf;
}
public byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len)
@@ -193,7 +231,16 @@ public class TlsBlockCipher
int blockSize = decryptCipher.getBlockSize();
int macSize = readMac.getSize();
- int minLen = Math.max(blockSize, macSize + 1);
+ int minLen = blockSize;
+ if (encryptThenMAC)
+ {
+ minLen += macSize;
+ }
+ else
+ {
+ minLen = Math.max(minLen, macSize + 1);
+ }
+
if (useExplicitIV)
{
minLen += blockSize;
@@ -204,41 +251,67 @@ public class TlsBlockCipher
throw new TlsFatalAlert(AlertDescription.decode_error);
}
- if (len % blockSize != 0)
+ int blocks_length = len;
+ if (encryptThenMAC)
+ {
+ blocks_length -= macSize;
+ }
+
+ if (blocks_length % blockSize != 0)
{
throw new TlsFatalAlert(AlertDescription.decryption_failed);
}
+ if (encryptThenMAC)
+ {
+ int end = offset + len;
+ byte[] receivedMac = Arrays.copyOfRange(ciphertext, end - macSize, end);
+ byte[] calculatedMac = readMac.calculateMac(seqNo, type, ciphertext, offset, len - macSize);
+
+ boolean badMac = !Arrays.constantTimeAreEqual(calculatedMac, receivedMac);
+
+ if (badMac)
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ }
+ }
+
if (useExplicitIV)
{
decryptCipher.init(false, new ParametersWithIV(null, ciphertext, offset, blockSize));
offset += blockSize;
- len -= blockSize;
+ blocks_length -= blockSize;
}
- for (int i = 0; i < len; i += blockSize)
+ for (int i = 0; i < blocks_length; i += blockSize)
{
decryptCipher.processBlock(ciphertext, offset + i, ciphertext, offset + i);
}
// If there's anything wrong with the padding, this will return zero
- int totalPad = checkPaddingConstantTime(ciphertext, offset, len, blockSize, macSize);
+ int totalPad = checkPaddingConstantTime(ciphertext, offset, blocks_length, blockSize, encryptThenMAC ? 0 : macSize);
- int macInputLen = len - totalPad - macSize;
+ int dec_output_length = blocks_length - totalPad;
- byte[] decryptedMac = Arrays.copyOfRange(ciphertext, offset + macInputLen, offset + macInputLen + macSize);
- byte[] calculatedMac = readMac.calculateMacConstantTime(seqNo, type, ciphertext, offset, macInputLen, len
- - macSize, randomData);
+ if (!encryptThenMAC)
+ {
+ dec_output_length -= macSize;
+ int macInputLen = dec_output_length;
+ int macOff = offset + macInputLen;
+ byte[] receivedMac = Arrays.copyOfRange(ciphertext, macOff, macOff + macSize);
+ byte[] calculatedMac = readMac.calculateMacConstantTime(seqNo, type, ciphertext, offset, macInputLen,
+ blocks_length - macSize, randomData);
- boolean badMac = !Arrays.constantTimeAreEqual(calculatedMac, decryptedMac);
+ boolean badMac = !Arrays.constantTimeAreEqual(calculatedMac, receivedMac);
- if (badMac || totalPad == 0)
- {
- throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ if (badMac || totalPad == 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ }
}
- return Arrays.copyOfRange(ciphertext, offset, offset + macInputLen);
+ return Arrays.copyOfRange(ciphertext, offset, offset + dec_output_length);
}
protected int checkPaddingConstantTime(byte[] buf, int off, int len, int blockSize, int macSize)
@@ -251,7 +324,7 @@ public class TlsBlockCipher
int dummyIndex = 0;
byte padDiff = 0;
- if ((context.getServerVersion().isSSL() && totalPad > blockSize) || (macSize + totalPad > len))
+ if ((TlsUtils.isSSL(context) && totalPad > blockSize) || (macSize + totalPad > len))
{
totalPad = 0;
}
@@ -310,4 +383,4 @@ public class TlsBlockCipher
}
return n;
}
-} \ No newline at end of file
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java
index 62444fa..7db86cd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java
@@ -7,9 +7,18 @@ import java.util.Vector;
public interface TlsClient
extends TlsPeer
{
-
void init(TlsClientContext context);
+ /**
+ * Return the session this client wants to resume, if any. Note that the peer's certificate
+ * chain for the session (if any) may need to be periodically revalidated.
+ *
+ * @return A {@link TlsSession} representing the resumable session to be used for this
+ * connection, or null to use a new session.
+ * @see SessionParameters#getPeerCertificate()
+ */
+ TlsSession getSessionToResume();
+
ProtocolVersion getClientHelloRecordLayerVersion();
ProtocolVersion getClientVersion();
@@ -25,15 +34,18 @@ public interface TlsClient
void notifyServerVersion(ProtocolVersion selectedVersion)
throws IOException;
+ /**
+ * Notifies the client of the session_id sent in the ServerHello.
+ *
+ * @param sessionID
+ * @see {@link TlsContext#getResumableSession()}
+ */
void notifySessionID(byte[] sessionID);
void notifySelectedCipherSuite(int selectedCipherSuite);
void notifySelectedCompressionMethod(short selectedCompressionMethod);
- void notifySecureRenegotiation(boolean secureNegotiation)
- throws IOException;
-
// Hashtable is (Integer -> byte[])
void processServerExtensions(Hashtable serverExtensions)
throws IOException;
@@ -52,12 +64,6 @@ public interface TlsClient
Vector getClientSupplementalData()
throws IOException;
- TlsCompression getCompression()
- throws IOException;
-
- TlsCipher getCipher()
- throws IOException;
-
/**
* RFC 5077 3.3. NewSessionTicket Handshake Message
* <p/>
@@ -70,7 +76,4 @@ public interface TlsClient
*/
void notifyNewSessionTicket(NewSessionTicket newSessionTicket)
throws IOException;
-
- void notifyHandshakeComplete()
- throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientContextImpl.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientContextImpl.java
index d91f7f8..b320144 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientContextImpl.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientContextImpl.java
@@ -6,7 +6,6 @@ class TlsClientContextImpl
extends AbstractTlsContext
implements TlsClientContext
{
-
TlsClientContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
{
super(secureRandom, securityParameters);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java
index 33cd914..506560f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java
@@ -1,7 +1,6 @@
package org.bouncycastle.crypto.tls;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -16,19 +15,15 @@ import org.bouncycastle.util.Arrays;
public class TlsClientProtocol
extends TlsProtocol
{
-
protected TlsClient tlsClient = null;
protected TlsClientContextImpl tlsClientContext = null;
- protected int[] offeredCipherSuites = null;
- protected short[] offeredCompressionMethods = null;
- protected Hashtable clientExtensions = null;
-
- protected int selectedCipherSuite;
- protected short selectedCompressionMethod;
+ protected byte[] selectedSessionID = null;
protected TlsKeyExchange keyExchange = null;
protected TlsAuthentication authentication = null;
+
+ protected CertificateStatus certificateStatus = null;
protected CertificateRequest certificateRequest = null;
private static SecureRandom createSecureRandom()
@@ -61,11 +56,10 @@ public class TlsClientProtocol
/**
* Initiates a TLS handshake in the role of client
*
- * @param tlsClient
+ * @param tlsClient The {@link TlsClient} to use for the handshake.
* @throws IOException If handshake was not successful.
*/
- public void connect(TlsClient tlsClient)
- throws IOException
+ public void connect(TlsClient tlsClient) throws IOException
{
if (tlsClient == null)
{
@@ -73,7 +67,7 @@ public class TlsClientProtocol
}
if (this.tlsClient != null)
{
- throw new IllegalStateException("connect can only be called once");
+ throw new IllegalStateException("'connect' can only be called once");
}
this.tlsClient = tlsClient;
@@ -86,12 +80,32 @@ public class TlsClientProtocol
this.tlsClient.init(tlsClientContext);
this.recordStream.init(tlsClientContext);
+ TlsSession sessionToResume = tlsClient.getSessionToResume();
+ if (sessionToResume != null)
+ {
+ SessionParameters sessionParameters = sessionToResume.exportSessionParameters();
+ if (sessionParameters != null)
+ {
+ this.tlsSession = sessionToResume;
+ this.sessionParameters = sessionParameters;
+ }
+ }
+
sendClientHelloMessage();
this.connection_state = CS_CLIENT_HELLO;
completeHandshake();
+ }
- this.tlsClient.notifyHandshakeComplete();
+ protected void cleanupHandshake()
+ {
+ super.cleanupHandshake();
+
+ this.selectedSessionID = null;
+ this.keyExchange = null;
+ this.authentication = null;
+ this.certificateStatus = null;
+ this.certificateRequest = null;
}
protected AbstractTlsContext getContext()
@@ -104,36 +118,27 @@ public class TlsClientProtocol
return tlsClient;
}
- protected void handleChangeCipherSpecMessage()
+ protected void handleHandshakeMessage(short type, byte[] data)
throws IOException
{
+ ByteArrayInputStream buf = new ByteArrayInputStream(data);
- switch (this.connection_state)
+ if (this.resumedSession)
{
- case CS_CLIENT_FINISHED:
- {
- if (this.expectSessionTicket)
+ if (type != HandshakeType.finished || this.connection_state != CS_SERVER_HELLO)
{
- /*
- * RFC 5077 3.3. This message MUST be sent if the server included a SessionTicket
- * extension in the ServerHello.
- */
- this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- // NB: Fall through to next case label
- }
- case CS_SERVER_SESSION_TICKET:
- this.connection_state = CS_SERVER_CHANGE_CIPHER_SPEC;
- break;
- default:
- this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
- }
- }
- protected void handleHandshakeMessage(short type, byte[] data)
- throws IOException
- {
- ByteArrayInputStream buf = new ByteArrayInputStream(data);
+ processFinishedMessage(buf);
+ this.connection_state = CS_SERVER_FINISHED;
+
+ sendFinishedMessage();
+ this.connection_state = CS_CLIENT_FINISHED;
+ this.connection_state = CS_END;
+
+ return;
+ }
switch (type)
{
@@ -150,72 +155,143 @@ public class TlsClientProtocol
{
// Parse the Certificate message and send to cipher suite
- Certificate serverCertificate = Certificate.parse(buf);
+ this.peerCertificate = Certificate.parse(buf);
assertEmpty(buf);
- this.keyExchange.processServerCertificate(serverCertificate);
+ // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus
+ if (this.peerCertificate == null || this.peerCertificate.isEmpty())
+ {
+ this.allowCertificateStatus = false;
+ }
+
+ this.keyExchange.processServerCertificate(this.peerCertificate);
this.authentication = tlsClient.getAuthentication();
- this.authentication.notifyServerCertificate(serverCertificate);
+ this.authentication.notifyServerCertificate(this.peerCertificate);
break;
}
default:
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
this.connection_state = CS_SERVER_CERTIFICATE;
break;
}
+ case HandshakeType.certificate_status:
+ {
+ switch (this.connection_state)
+ {
+ case CS_SERVER_CERTIFICATE:
+ {
+ if (!this.allowCertificateStatus)
+ {
+ /*
+ * RFC 3546 3.6. If a server returns a "CertificateStatus" message, then the
+ * server MUST have included an extension of type "status_request" with empty
+ * "extension_data" in the extended server hello..
+ */
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ this.certificateStatus = CertificateStatus.parse(buf);
+
+ assertEmpty(buf);
+
+ // TODO[RFC 3546] Figure out how to provide this to the client/authentication.
+
+ this.connection_state = CS_CERTIFICATE_STATUS;
+ break;
+ }
+ default:
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ break;
+ }
case HandshakeType.finished:
+ {
switch (this.connection_state)
{
- case CS_SERVER_CHANGE_CIPHER_SPEC:
+ case CS_CLIENT_FINISHED:
+ {
processFinishedMessage(buf);
this.connection_state = CS_SERVER_FINISHED;
+ this.connection_state = CS_END;
break;
+ }
default:
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
break;
+ }
case HandshakeType.server_hello:
+ {
switch (this.connection_state)
{
case CS_CLIENT_HELLO:
+ {
receiveServerHelloMessage(buf);
this.connection_state = CS_SERVER_HELLO;
- securityParameters.prfAlgorithm = getPRFAlgorithm(selectedCipherSuite);
- securityParameters.compressionAlgorithm = this.selectedCompressionMethod;
+ if (this.securityParameters.maxFragmentLength >= 0)
+ {
+ int plainTextLimit = 1 << (8 + this.securityParameters.maxFragmentLength);
+ recordStream.setPlaintextLimit(plainTextLimit);
+ }
+
+ this.securityParameters.prfAlgorithm = getPRFAlgorithm(getContext(),
+ this.securityParameters.getCipherSuite());
/*
* RFC 5264 7.4.9. Any cipher suite which does not explicitly specify
* verify_data_length has a verify_data_length equal to 12. This includes all
* existing cipher suites.
*/
- securityParameters.verifyDataLength = 12;
+ this.securityParameters.verifyDataLength = 12;
- recordStream.notifyHelloComplete();
+ this.recordStream.notifyHelloComplete();
+
+ if (this.resumedSession)
+ {
+ this.securityParameters.masterSecret = Arrays.clone(this.sessionParameters.getMasterSecret());
+ this.recordStream.setPendingConnectionState(getPeer().getCompression(), getPeer().getCipher());
+
+ sendChangeCipherSpecMessage();
+ }
+ else
+ {
+ invalidateSession();
+
+ if (this.selectedSessionID.length > 0)
+ {
+ this.tlsSession = new TlsSessionImpl(this.selectedSessionID, null);
+ }
+ }
break;
+ }
default:
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
break;
+ }
case HandshakeType.supplemental_data:
{
switch (this.connection_state)
{
case CS_SERVER_HELLO:
+ {
handleSupplementalData(readSupplementalDataMessage(buf));
break;
+ }
default:
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
break;
}
case HandshakeType.server_hello_done:
+ {
switch (this.connection_state)
{
case CS_SERVER_HELLO:
@@ -225,7 +301,6 @@ public class TlsClientProtocol
}
case CS_SERVER_SUPPLEMENTAL_DATA:
{
-
// There was no server certificate message; check it's OK
this.keyExchange.skipServerCredentials();
this.authentication = null;
@@ -233,19 +308,22 @@ public class TlsClientProtocol
// NB: Fall through to next case label
}
case CS_SERVER_CERTIFICATE:
-
+ case CS_CERTIFICATE_STATUS:
+ {
// There was no server key exchange message; check it's OK
this.keyExchange.skipServerKeyExchange();
// NB: Fall through to next case label
-
+ }
case CS_SERVER_KEY_EXCHANGE:
case CS_CERTIFICATE_REQUEST:
-
+ {
assertEmpty(buf);
this.connection_state = CS_SERVER_HELLO_DONE;
+ this.recordStream.getHandshakeHash().sealHashAlgorithms();
+
Vector clientSupplementalData = tlsClient.getClientSupplementalData();
if (clientSupplementalData != null)
{
@@ -289,40 +367,56 @@ public class TlsClientProtocol
* in our CipherSuite.
*/
sendClientKeyExchangeMessage();
+ this.connection_state = CS_CLIENT_KEY_EXCHANGE;
establishMasterSecret(getContext(), keyExchange);
+ recordStream.setPendingConnectionState(getPeer().getCompression(), getPeer().getCipher());
- /*
- * Initialize our cipher suite
- */
- recordStream.setPendingConnectionState(tlsClient.getCompression(), tlsClient.getCipher());
-
- this.connection_state = CS_CLIENT_KEY_EXCHANGE;
+ TlsHandshakeHash prepareFinishHash = recordStream.prepareToFinish();
if (clientCreds != null && clientCreds instanceof TlsSignerCredentials)
{
+ TlsSignerCredentials signerCredentials = (TlsSignerCredentials)clientCreds;
+
/*
- * TODO RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm
- * prepended from TLS 1.2
+ * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
*/
- TlsSignerCredentials signerCreds = (TlsSignerCredentials)clientCreds;
- byte[] md5andsha1 = recordStream.getCurrentHash(null);
- byte[] clientCertificateSignature = signerCreds.generateCertificateSignature(md5andsha1);
- sendCertificateVerifyMessage(clientCertificateSignature);
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm;
+ byte[] hash;
+
+ if (TlsUtils.isTLSv12(getContext()))
+ {
+ signatureAndHashAlgorithm = signerCredentials.getSignatureAndHashAlgorithm();
+ if (signatureAndHashAlgorithm == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ hash = prepareFinishHash.getFinalHash(signatureAndHashAlgorithm.getHash());
+ }
+ else
+ {
+ signatureAndHashAlgorithm = null;
+ hash = getCurrentPRFHash(getContext(), prepareFinishHash, null);
+ }
+
+ byte[] signature = signerCredentials.generateCertificateSignature(hash);
+ DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature);
+ sendCertificateVerifyMessage(certificateVerify);
this.connection_state = CS_CERTIFICATE_VERIFY;
}
sendChangeCipherSpecMessage();
- this.connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC;
-
sendFinishedMessage();
this.connection_state = CS_CLIENT_FINISHED;
break;
+ }
default:
- this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
break;
+ }
case HandshakeType.server_key_exchange:
{
switch (this.connection_state)
@@ -334,7 +428,6 @@ public class TlsClientProtocol
}
case CS_SERVER_SUPPLEMENTAL_DATA:
{
-
// There was no server certificate message; check it's OK
this.keyExchange.skipServerCredentials();
this.authentication = null;
@@ -342,14 +435,15 @@ public class TlsClientProtocol
// NB: Fall through to next case label
}
case CS_SERVER_CERTIFICATE:
-
+ case CS_CERTIFICATE_STATUS:
+ {
this.keyExchange.processServerKeyExchange(buf);
assertEmpty(buf);
break;
-
+ }
default:
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
this.connection_state = CS_SERVER_KEY_EXCHANGE;
@@ -360,12 +454,13 @@ public class TlsClientProtocol
switch (this.connection_state)
{
case CS_SERVER_CERTIFICATE:
-
+ case CS_CERTIFICATE_STATUS:
+ {
// There was no server key exchange message; check it's OK
this.keyExchange.skipServerKeyExchange();
// NB: Fall through to next case label
-
+ }
case CS_SERVER_KEY_EXCHANGE:
{
if (this.authentication == null)
@@ -374,19 +469,26 @@ public class TlsClientProtocol
* RFC 2246 7.4.4. It is a fatal handshake_failure alert for an anonymous server
* to request client identification.
*/
- this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
- this.certificateRequest = CertificateRequest.parse(buf);
+ this.certificateRequest = CertificateRequest.parse(getContext(), buf);
assertEmpty(buf);
this.keyExchange.validateCertificateRequest(this.certificateRequest);
+ /*
+ * TODO Give the client a chance to immediately select the CertificateVerify hash
+ * algorithm here to avoid tracking the other hash algorithms unnecessarily?
+ */
+ TlsUtils.trackHashAlgorithms(this.recordStream.getHandshakeHash(),
+ this.certificateRequest.getSupportedSignatureAlgorithms());
+
break;
}
default:
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
this.connection_state = CS_CERTIFICATE_REQUEST;
@@ -397,23 +499,32 @@ public class TlsClientProtocol
switch (this.connection_state)
{
case CS_CLIENT_FINISHED:
+ {
if (!this.expectSessionTicket)
{
/*
* RFC 5077 3.3. This message MUST NOT be sent if the server did not include a
* SessionTicket extension in the ServerHello.
*/
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
+
+ /*
+ * RFC 5077 3.4. If the client receives a session ticket from the server, then it
+ * discards any Session ID that was sent in the ServerHello.
+ */
+ invalidateSession();
+
receiveNewSessionTicketMessage(buf);
this.connection_state = CS_SERVER_SESSION_TICKET;
break;
+ }
default:
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
}
case HandshakeType.hello_request:
-
+ {
assertEmpty(buf);
/*
@@ -422,27 +533,34 @@ public class TlsClientProtocol
* if it does not wish to renegotiate a session, or the client may, if it wishes,
* respond with a no_renegotiation alert.
*/
- if (this.connection_state == CS_SERVER_FINISHED)
+ if (this.connection_state == CS_END)
{
+ /*
+ * RFC 5746 4.5 SSLv3 clients that refuse renegotiation SHOULD use a fatal
+ * handshake_failure alert.
+ */
+ if (TlsUtils.isSSL(getContext()))
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+
String message = "Renegotiation not supported";
raiseWarning(AlertDescription.no_renegotiation, message);
}
break;
+ }
+ case HandshakeType.client_hello:
case HandshakeType.client_key_exchange:
case HandshakeType.certificate_verify:
- case HandshakeType.client_hello:
case HandshakeType.hello_verify_request:
default:
- // We do not support this!
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
- break;
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
}
protected void handleSupplementalData(Vector serverSupplementalData)
throws IOException
{
-
this.tlsClient.processServerSupplementalData(serverSupplementalData);
this.connection_state = CS_SERVER_SUPPLEMENTAL_DATA;
@@ -453,7 +571,6 @@ public class TlsClientProtocol
protected void receiveNewSessionTicketMessage(ByteArrayInputStream buf)
throws IOException
{
-
NewSessionTicket newSessionTicket = NewSessionTicket.parse(buf);
TlsProtocol.assertEmpty(buf);
@@ -464,23 +581,22 @@ public class TlsClientProtocol
protected void receiveServerHelloMessage(ByteArrayInputStream buf)
throws IOException
{
-
ProtocolVersion server_version = TlsUtils.readVersion(buf);
if (server_version.isDTLS())
{
- this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
// Check that this matches what the server is sending in the record layer
- if (!server_version.equals(recordStream.getReadVersion()))
+ if (!server_version.equals(this.recordStream.getReadVersion()))
{
- this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
ProtocolVersion client_version = getContext().getClientVersion();
if (!server_version.isEqualOrEarlierVersionOf(client_version))
{
- this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
this.recordStream.setWriteVersion(server_version);
@@ -490,38 +606,41 @@ public class TlsClientProtocol
/*
* Read the server random
*/
- securityParameters.serverRandom = TlsUtils.readFully(32, buf);
+ this.securityParameters.serverRandom = TlsUtils.readFully(32, buf);
- byte[] sessionID = TlsUtils.readOpaque8(buf);
- if (sessionID.length > 32)
+ this.selectedSessionID = TlsUtils.readOpaque8(buf);
+ if (this.selectedSessionID.length > 32)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
- this.tlsClient.notifySessionID(sessionID);
+ this.tlsClient.notifySessionID(this.selectedSessionID);
+
+ this.resumedSession = this.selectedSessionID.length > 0 && this.tlsSession != null
+ && Arrays.areEqual(this.selectedSessionID, this.tlsSession.getSessionID());
/*
* Find out which CipherSuite the server has chosen and check that it was one of the offered
* ones.
*/
- this.selectedCipherSuite = TlsUtils.readUint16(buf);
- if (!arrayContains(offeredCipherSuites, this.selectedCipherSuite)
- || this.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
- || this.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
+ int selectedCipherSuite = TlsUtils.readUint16(buf);
+ if (!Arrays.contains(this.offeredCipherSuites, selectedCipherSuite)
+ || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
+ || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
- this.tlsClient.notifySelectedCipherSuite(this.selectedCipherSuite);
+ this.tlsClient.notifySelectedCipherSuite(selectedCipherSuite);
/*
* Find out which CompressionMethod the server has chosen and check that it was one of the
* offered ones.
*/
short selectedCompressionMethod = TlsUtils.readUint8(buf);
- if (!arrayContains(offeredCompressionMethods, selectedCompressionMethod))
+ if (!Arrays.contains(this.offeredCompressionMethods, selectedCompressionMethod))
{
- this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
this.tlsClient.notifySelectedCompressionMethod(selectedCompressionMethod);
@@ -534,15 +653,7 @@ public class TlsClientProtocol
* possibility that the extended server hello message could "break" existing TLS 1.0
* clients.
*/
-
- /*
- * TODO RFC 3546 2.3 If [...] the older session is resumed, then the server MUST ignore
- * extensions appearing in the client hello, and send a server hello containing no
- * extensions.
- */
-
- // Integer -> byte[]
- Hashtable serverExtensions = readExtensions(buf);
+ this.serverExtensions = readExtensions(buf);
/*
* RFC 3546 2.2 Note that the extended server hello message is only sent in response to an
@@ -551,9 +662,9 @@ public class TlsClientProtocol
* However, see RFC 5746 exception below. We always include the SCSV, so an Extended Server
* Hello is always allowed.
*/
- if (serverExtensions != null)
+ if (this.serverExtensions != null)
{
- Enumeration e = serverExtensions.keys();
+ Enumeration e = this.serverExtensions.keys();
while (e.hasMoreElements())
{
Integer extType = (Integer)e.nextElement();
@@ -565,107 +676,169 @@ public class TlsClientProtocol
* only allowed because the client is signaling its willingness to receive the
* extension via the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
*/
- if (!extType.equals(EXT_RenegotiationInfo)
- && (clientExtensions == null || clientExtensions.get(extType) == null))
+ if (extType.equals(EXT_RenegotiationInfo))
{
- /*
- * RFC 5246 7.4.1.4 An extension type MUST NOT appear in the ServerHello unless
- * the same extension type appeared in the corresponding ClientHello. If a
- * client receives an extension type in ServerHello that it did not request in
- * the associated ClientHello, it MUST abort the handshake with an
- * unsupported_extension fatal alert.
- */
- this.failWithError(AlertLevel.fatal, AlertDescription.unsupported_extension);
+ continue;
+ }
+
+ /*
+ * RFC 3546 2.3. If [...] the older session is resumed, then the server MUST ignore
+ * extensions appearing in the client hello, and send a server hello containing no
+ * extensions[.]
+ */
+ if (this.resumedSession)
+ {
+ // TODO[compat-gnutls] GnuTLS test server sends server extensions e.g. ec_point_formats
+ // TODO[compat-openssl] OpenSSL test server sends server extensions e.g. ec_point_formats
+ // TODO[compat-polarssl] PolarSSL test server sends server extensions e.g. ec_point_formats
+// throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ /*
+ * RFC 5246 7.4.1.4 An extension type MUST NOT appear in the ServerHello unless the
+ * same extension type appeared in the corresponding ClientHello. If a client
+ * receives an extension type in ServerHello that it did not request in the
+ * associated ClientHello, it MUST abort the handshake with an unsupported_extension
+ * fatal alert.
+ */
+ if (null == TlsUtils.getExtensionData(this.clientExtensions, extType))
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_extension);
}
}
+ }
+ /*
+ * RFC 5746 3.4. Client Behavior: Initial Handshake
+ */
+ {
/*
- * RFC 5746 3.4. Client Behavior: Initial Handshake
+ * When a ServerHello is received, the client MUST check if it includes the
+ * "renegotiation_info" extension:
*/
+ byte[] renegExtData = TlsUtils.getExtensionData(this.serverExtensions, EXT_RenegotiationInfo);
+ if (renegExtData != null)
{
/*
- * When a ServerHello is received, the client MUST check if it includes the
- * "renegotiation_info" extension:
+ * If the extension is present, set the secure_renegotiation flag to TRUE. The
+ * client MUST then verify that the length of the "renegotiated_connection"
+ * field is zero, and if it is not, MUST abort the handshake (by sending a fatal
+ * handshake_failure alert).
*/
- byte[] renegExtValue = (byte[])serverExtensions.get(EXT_RenegotiationInfo);
- if (renegExtValue != null)
- {
- /*
- * If the extension is present, set the secure_renegotiation flag to TRUE. The
- * client MUST then verify that the length of the "renegotiated_connection"
- * field is zero, and if it is not, MUST abort the handshake (by sending a fatal
- * handshake_failure alert).
- */
- this.secure_renegotiation = true;
+ this.secure_renegotiation = true;
- if (!Arrays.constantTimeAreEqual(renegExtValue, createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
- }
+ if (!Arrays.constantTimeAreEqual(renegExtData, createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
+ {
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
}
+ }
+
+ // TODO[compat-gnutls] GnuTLS test server fails to send renegotiation_info extension when resuming
+ this.tlsClient.notifySecureRenegotiation(this.secure_renegotiation);
- this.expectSessionTicket = serverExtensions.containsKey(EXT_SessionTicket);
+ Hashtable sessionClientExtensions = clientExtensions, sessionServerExtensions = serverExtensions;
+ if (this.resumedSession)
+ {
+ if (selectedCipherSuite != this.sessionParameters.getCipherSuite()
+ || selectedCompressionMethod != this.sessionParameters.getCompressionAlgorithm())
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ sessionClientExtensions = null;
+ sessionServerExtensions = this.sessionParameters.readServerExtensions();
}
- tlsClient.notifySecureRenegotiation(this.secure_renegotiation);
+ this.securityParameters.cipherSuite = selectedCipherSuite;
+ this.securityParameters.compressionAlgorithm = selectedCompressionMethod;
- if (clientExtensions != null)
+ if (sessionServerExtensions != null)
+ {
+ this.securityParameters.maxFragmentLength = processMaxFragmentLengthExtension(sessionClientExtensions,
+ sessionServerExtensions, AlertDescription.illegal_parameter);
+
+ this.securityParameters.truncatedHMac = TlsExtensionsUtils.hasTruncatedHMacExtension(sessionServerExtensions);
+
+ /*
+ * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in
+ * a session resumption handshake.
+ */
+ this.allowCertificateStatus = !this.resumedSession
+ && TlsUtils.hasExpectedEmptyExtensionData(sessionServerExtensions,
+ TlsExtensionsUtils.EXT_status_request, AlertDescription.illegal_parameter);
+
+ this.expectSessionTicket = !this.resumedSession
+ && TlsUtils.hasExpectedEmptyExtensionData(sessionServerExtensions, TlsProtocol.EXT_SessionTicket,
+ AlertDescription.illegal_parameter);
+ }
+
+ if (sessionClientExtensions != null)
{
- tlsClient.processServerExtensions(serverExtensions);
+ this.tlsClient.processServerExtensions(sessionServerExtensions);
}
}
- protected void sendCertificateVerifyMessage(byte[] data)
+ protected void sendCertificateVerifyMessage(DigitallySigned certificateVerify)
throws IOException
{
- /*
- * Send signature of handshake messages so far to prove we are the owner of the cert See RFC
- * 2246 sections 4.7, 7.4.3 and 7.4.8
- */
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- TlsUtils.writeUint8(HandshakeType.certificate_verify, bos);
- TlsUtils.writeUint24(data.length + 2, bos);
- TlsUtils.writeOpaque16(data, bos);
- byte[] message = bos.toByteArray();
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_verify);
+
+ certificateVerify.encode(message);
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.writeToRecordStream();
}
protected void sendClientHelloMessage()
throws IOException
{
-
- recordStream.setWriteVersion(this.tlsClient.getClientHelloRecordLayerVersion());
-
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeUint8(HandshakeType.client_hello, buf);
-
- // Reserve space for length
- TlsUtils.writeUint24(0, buf);
+ this.recordStream.setWriteVersion(this.tlsClient.getClientHelloRecordLayerVersion());
ProtocolVersion client_version = this.tlsClient.getClientVersion();
if (client_version.isDTLS())
{
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
getContext().setClientVersion(client_version);
- TlsUtils.writeVersion(client_version, buf);
-
- buf.write(securityParameters.clientRandom);
-
- // Session id
- TlsUtils.writeOpaque8(TlsUtils.EMPTY_BYTES, buf);
/*
- * Cipher suites
+ * TODO RFC 5077 3.4. When presenting a ticket, the client MAY generate and include a
+ * Session ID in the TLS ClientHello.
*/
+ byte[] session_id = TlsUtils.EMPTY_BYTES;
+ if (this.tlsSession != null)
+ {
+ session_id = this.tlsSession.getSessionID();
+ if (session_id == null || session_id.length > 32)
+ {
+ session_id = TlsUtils.EMPTY_BYTES;
+ }
+ }
+
this.offeredCipherSuites = this.tlsClient.getCipherSuites();
- // Integer -> byte[]
+ this.offeredCompressionMethods = this.tlsClient.getCompressionMethods();
+
+ if (session_id.length > 0 && this.sessionParameters != null)
+ {
+ if (!Arrays.contains(this.offeredCipherSuites, sessionParameters.getCipherSuite())
+ || !Arrays.contains(this.offeredCompressionMethods, sessionParameters.getCompressionAlgorithm()))
+ {
+ session_id = TlsUtils.EMPTY_BYTES;
+ }
+ }
+
this.clientExtensions = this.tlsClient.getClientExtensions();
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.client_hello);
+
+ TlsUtils.writeVersion(client_version, message);
+
+ message.write(this.securityParameters.getClientRandom());
+
+ TlsUtils.writeOpaque8(session_id, message);
+
// Cipher Suites (and SCSV)
{
/*
@@ -673,60 +846,39 @@ public class TlsClientProtocol
* or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
* ClientHello. Including both is NOT RECOMMENDED.
*/
- boolean noRenegExt = clientExtensions == null || clientExtensions.get(EXT_RenegotiationInfo) == null;
+ byte[] renegExtData = TlsUtils.getExtensionData(clientExtensions, EXT_RenegotiationInfo);
+ boolean noRenegExt = (null == renegExtData);
- int count = offeredCipherSuites.length;
- if (noRenegExt)
- {
- // Note: 1 extra slot for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- ++count;
- }
+ boolean noSCSV = !Arrays.contains(offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
- TlsUtils.writeUint16(2 * count, buf);
- TlsUtils.writeUint16Array(offeredCipherSuites, buf);
-
- if (noRenegExt)
+ if (noRenegExt && noSCSV)
{
- TlsUtils.writeUint16(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV, buf);
+ // TODO Consider whether to default to a client extension instead
+// this.clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(this.clientExtensions);
+// this.clientExtensions.put(EXT_RenegotiationInfo, createRenegotiationInfo(TlsUtils.EMPTY_BYTES));
+ this.offeredCipherSuites = Arrays.append(offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
}
- }
- // Compression methods
- this.offeredCompressionMethods = this.tlsClient.getCompressionMethods();
+ TlsUtils.writeUint16ArrayWithUint16Length(offeredCipherSuites, message);
+ }
- TlsUtils.writeUint8((short)offeredCompressionMethods.length, buf);
- TlsUtils.writeUint8Array(offeredCompressionMethods, buf);
+ TlsUtils.writeUint8ArrayWithUint8Length(offeredCompressionMethods, message);
- // Extensions
if (clientExtensions != null)
{
- writeExtensions(buf, clientExtensions);
+ writeExtensions(message, clientExtensions);
}
- byte[] message = buf.toByteArray();
-
- // Patch actual length back in
- TlsUtils.writeUint24(message.length - 4, message, 1);
-
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.writeToRecordStream();
}
protected void sendClientKeyExchangeMessage()
throws IOException
{
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
-
- TlsUtils.writeUint8(HandshakeType.client_key_exchange, bos);
-
- // Reserve space for length
- TlsUtils.writeUint24(0, bos);
-
- this.keyExchange.generateClientKeyExchange(bos);
- byte[] message = bos.toByteArray();
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.client_key_exchange);
- // Patch actual length back in
- TlsUtils.writeUint24(message.length - 4, message, 1);
+ this.keyExchange.generateClientKeyExchange(message);
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.writeToRecordStream();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsContext.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsContext.java
index dfb1052..04781ef 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsContext.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsContext.java
@@ -4,7 +4,6 @@ import java.security.SecureRandom;
public interface TlsContext
{
-
SecureRandom getSecureRandom();
SecurityParameters getSecurityParameters();
@@ -15,6 +14,16 @@ public interface TlsContext
ProtocolVersion getServerVersion();
+ /**
+ * Used to get the resumable session, if any, used by this connection. Only available after the
+ * handshake has successfully completed.
+ *
+ * @return A {@link TlsSession} representing the resumable session used by this connection, or
+ * null if no resumable session available.
+ * @see {@link TlsPeer#notifyHandshakeComplete()}
+ */
+ TlsSession getResumableSession();
+
Object getUserObject();
void setUserObject(Object userObject);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java
index 5737659..0abaee6 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java
@@ -1,24 +1,17 @@
package org.bouncycastle.crypto.tls;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.math.BigInteger;
import java.util.Vector;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.generators.DHKeyPairGenerator;
-import org.bouncycastle.crypto.io.SignerInputStream;
-import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
+import org.bouncycastle.util.io.TeeInputStream;
public class TlsDHEKeyExchange
extends TlsDHKeyExchange
{
-
protected TlsSignerCredentials serverCredentials = null;
public TlsDHEKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, DHParameters dhParameters)
@@ -29,7 +22,6 @@ public class TlsDHEKeyExchange
public void processServerCredentials(TlsCredentials serverCredentials)
throws IOException
{
-
if (!(serverCredentials instanceof TlsSignerCredentials))
{
throw new TlsFatalAlert(AlertDescription.internal_error);
@@ -43,40 +35,50 @@ public class TlsDHEKeyExchange
public byte[] generateServerKeyExchange()
throws IOException
{
-
if (this.dhParameters == null)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ DigestInputBuffer buf = new DigestInputBuffer();
- DHKeyPairGenerator kpg = new DHKeyPairGenerator();
- kpg.init(new DHKeyGenerationParameters(context.getSecureRandom(), this.dhParameters));
- AsymmetricCipherKeyPair kp = kpg.generateKeyPair();
+ this.dhAgreeServerPrivateKey = TlsDHUtils.generateEphemeralServerKeyExchange(context.getSecureRandom(),
+ this.dhParameters, buf);
- BigInteger Ys = ((DHPublicKeyParameters)kp.getPublic()).getY();
+ /*
+ * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
+ */
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm;
+ Digest d;
- TlsDHUtils.writeDHParameter(dhParameters.getP(), buf);
- TlsDHUtils.writeDHParameter(dhParameters.getG(), buf);
- TlsDHUtils.writeDHParameter(Ys, buf);
+ if (TlsUtils.isTLSv12(context))
+ {
+ signatureAndHashAlgorithm = serverCredentials.getSignatureAndHashAlgorithm();
+ if (signatureAndHashAlgorithm == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
- byte[] digestInput = buf.toByteArray();
+ d = TlsUtils.createHash(signatureAndHashAlgorithm.getHash());
+ }
+ else
+ {
+ signatureAndHashAlgorithm = null;
+ d = new CombinedHash();
+ }
- Digest d = new CombinedHash();
SecurityParameters securityParameters = context.getSecurityParameters();
d.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
d.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
- d.update(digestInput, 0, digestInput.length);
+ buf.updateDigest(d);
byte[] hash = new byte[d.getDigestSize()];
d.doFinal(hash, 0);
- byte[] sigBytes = serverCredentials.generateCertificateSignature(hash);
- /*
- * TODO RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm prepended from TLS 1.2
- */
- TlsUtils.writeOpaque16(sigBytes, buf);
+ byte[] signature = serverCredentials.generateCertificateSignature(hash);
+
+ DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature);
+ signed_params.encode(buf);
return buf.toByteArray();
}
@@ -84,28 +86,28 @@ public class TlsDHEKeyExchange
public void processServerKeyExchange(InputStream input)
throws IOException
{
-
SecurityParameters securityParameters = context.getSecurityParameters();
- Signer signer = initVerifyer(tlsSigner, securityParameters);
- InputStream sigIn = new SignerInputStream(input, signer);
+ SignerInputBuffer buf = new SignerInputBuffer();
+ InputStream teeIn = new TeeInputStream(input, buf);
+
+ ServerDHParams params = ServerDHParams.parse(teeIn);
- BigInteger p = TlsDHUtils.readDHParameter(sigIn);
- BigInteger g = TlsDHUtils.readDHParameter(sigIn);
- BigInteger Ys = TlsDHUtils.readDHParameter(sigIn);
+ DigitallySigned signed_params = DigitallySigned.parse(context, input);
- byte[] sigBytes = TlsUtils.readOpaque16(input);
- if (!signer.verifySignature(sigBytes))
+ Signer signer = initVerifyer(tlsSigner, signed_params.getAlgorithm(), securityParameters);
+ buf.updateSigner(signer);
+ if (!signer.verifySignature(signed_params.getSignature()))
{
throw new TlsFatalAlert(AlertDescription.decrypt_error);
}
- this.dhAgreeServerPublicKey = validateDHPublicKey(new DHPublicKeyParameters(Ys, new DHParameters(p, g)));
+ this.dhAgreeServerPublicKey = TlsDHUtils.validateDHPublicKey(params.getPublicKey());
}
- protected Signer initVerifyer(TlsSigner tlsSigner, SecurityParameters securityParameters)
+ protected Signer initVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, SecurityParameters securityParameters)
{
- Signer signer = tlsSigner.createVerifyer(this.serverPublicKey);
+ Signer signer = tlsSigner.createVerifyer(algorithm, this.serverPublicKey);
signer.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
signer.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
return signer;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java
index 60e5105..7d79f6a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java
@@ -7,7 +7,6 @@ import java.util.Vector;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
@@ -20,7 +19,6 @@ import org.bouncycastle.crypto.util.PublicKeyFactory;
public class TlsDHKeyExchange
extends AbstractTlsKeyExchange
{
-
protected static final BigInteger ONE = BigInteger.valueOf(1);
protected static final BigInteger TWO = BigInteger.valueOf(2);
@@ -32,11 +30,11 @@ public class TlsDHKeyExchange
protected TlsAgreementCredentials agreementCredentials;
protected DHPrivateKeyParameters dhAgreeClientPrivateKey;
+ protected DHPrivateKeyParameters dhAgreeServerPrivateKey;
protected DHPublicKeyParameters dhAgreeClientPublicKey;
public TlsDHKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, DHParameters dhParameters)
{
-
super(keyExchange, supportedSignatureAlgorithms);
switch (keyExchange)
@@ -77,7 +75,6 @@ public class TlsDHKeyExchange
public void processServerCertificate(Certificate serverCertificate)
throws IOException
{
-
if (serverCertificate.isEmpty())
{
throw new TlsFatalAlert(AlertDescription.bad_certificate);
@@ -99,7 +96,7 @@ public class TlsDHKeyExchange
{
try
{
- this.dhAgreeServerPublicKey = validateDHPublicKey((DHPublicKeyParameters)this.serverPublicKey);
+ this.dhAgreeServerPublicKey = TlsDHUtils.validateDHPublicKey((DHPublicKeyParameters)this.serverPublicKey);
}
catch (ClassCastException e)
{
@@ -196,27 +193,16 @@ public class TlsDHKeyExchange
return agreementCredentials.generateAgreement(dhAgreeServerPublicKey);
}
- return calculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
- }
-
- protected boolean areCompatibleParameters(DHParameters a, DHParameters b)
- {
- return a.getP().equals(b.getP()) && a.getG().equals(b.getG());
- }
-
- protected byte[] calculateDHBasicAgreement(DHPublicKeyParameters publicKey, DHPrivateKeyParameters privateKey)
- {
- return TlsDHUtils.calculateDHBasicAgreement(publicKey, privateKey);
- }
+ if (dhAgreeServerPrivateKey != null)
+ {
+ return TlsDHUtils.calculateDHBasicAgreement(dhAgreeClientPublicKey, dhAgreeServerPrivateKey);
+ }
- protected AsymmetricCipherKeyPair generateDHKeyPair(DHParameters dhParams)
- {
- return TlsDHUtils.generateDHKeyPair(context.getSecureRandom(), dhParams);
- }
+ if (dhAgreeClientPrivateKey != null)
+ {
+ return TlsDHUtils.calculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
+ }
- protected DHPublicKeyParameters validateDHPublicKey(DHPublicKeyParameters key)
- throws IOException
- {
- return TlsDHUtils.validateDHPublicKey(key);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHUtils.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHUtils.java
index 014e40f..748c879 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHUtils.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDHUtils.java
@@ -17,14 +17,16 @@ import org.bouncycastle.util.BigIntegers;
public class TlsDHUtils
{
-
static final BigInteger ONE = BigInteger.valueOf(1);
static final BigInteger TWO = BigInteger.valueOf(2);
- public static byte[] calculateDHBasicAgreement(DHPublicKeyParameters publicKey,
- DHPrivateKeyParameters privateKey)
+ public static boolean areCompatibleParameters(DHParameters a, DHParameters b)
{
+ return a.getP().equals(b.getP()) && a.getG().equals(b.getG());
+ }
+ public static byte[] calculateDHBasicAgreement(DHPublicKeyParameters publicKey, DHPrivateKeyParameters privateKey)
+ {
DHBasicAgreement basicAgreement = new DHBasicAgreement();
basicAgreement.init(privateKey);
BigInteger agreementValue = basicAgreement.calculateAgreement(publicKey);
@@ -36,32 +38,37 @@ public class TlsDHUtils
return BigIntegers.asUnsignedByteArray(agreementValue);
}
- public static AsymmetricCipherKeyPair generateDHKeyPair(SecureRandom random,
- DHParameters dhParams)
+ public static AsymmetricCipherKeyPair generateDHKeyPair(SecureRandom random, DHParameters dhParams)
{
DHBasicKeyPairGenerator dhGen = new DHBasicKeyPairGenerator();
dhGen.init(new DHKeyGenerationParameters(random, dhParams));
return dhGen.generateKeyPair();
}
- public static DHPrivateKeyParameters generateEphemeralClientKeyExchange(SecureRandom random,
- DHParameters dhParams, OutputStream output)
- throws IOException
+ public static DHPrivateKeyParameters generateEphemeralClientKeyExchange(SecureRandom random, DHParameters dhParams,
+ OutputStream output) throws IOException
{
+ AsymmetricCipherKeyPair kp = generateDHKeyPair(random, dhParams);
+
+ DHPublicKeyParameters dh_public = (DHPublicKeyParameters) kp.getPublic();
+ writeDHParameter(dh_public.getY(), output);
- AsymmetricCipherKeyPair dhAgreeClientKeyPair = generateDHKeyPair(random, dhParams);
- DHPrivateKeyParameters dhAgreeClientPrivateKey = (DHPrivateKeyParameters)dhAgreeClientKeyPair
- .getPrivate();
+ return (DHPrivateKeyParameters) kp.getPrivate();
+ }
+
+ public static DHPrivateKeyParameters generateEphemeralServerKeyExchange(SecureRandom random, DHParameters dhParams,
+ OutputStream output) throws IOException
+ {
+ AsymmetricCipherKeyPair kp = TlsDHUtils.generateDHKeyPair(random, dhParams);
- BigInteger Yc = ((DHPublicKeyParameters)dhAgreeClientKeyPair.getPublic()).getY();
- byte[] keData = BigIntegers.asUnsignedByteArray(Yc);
- TlsUtils.writeOpaque16(keData, output);
+ DHPublicKeyParameters dhPublicKey = (DHPublicKeyParameters)kp.getPublic();
+ ServerDHParams params = new ServerDHParams(dhPublicKey);
+ params.encode(output);
- return dhAgreeClientPrivateKey;
+ return (DHPrivateKeyParameters)kp.getPrivate();
}
- public static DHPublicKeyParameters validateDHPublicKey(DHPublicKeyParameters key)
- throws IOException
+ public static DHPublicKeyParameters validateDHPublicKey(DHPublicKeyParameters key) throws IOException
{
BigInteger Y = key.getY();
DHParameters params = key.getParameters();
@@ -86,14 +93,12 @@ public class TlsDHUtils
return key;
}
- public static BigInteger readDHParameter(InputStream input)
- throws IOException
+ public static BigInteger readDHParameter(InputStream input) throws IOException
{
return new BigInteger(1, TlsUtils.readOpaque16(input));
}
- public static void writeDHParameter(BigInteger x, OutputStream output)
- throws IOException
+ public static void writeDHParameter(BigInteger x, OutputStream output) throws IOException
{
TlsUtils.writeOpaque16(BigIntegers.asUnsignedByteArray(x), output);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSASigner.java
index b0e8957..4cb8004 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSASigner.java
@@ -6,7 +6,6 @@ import org.bouncycastle.crypto.DSA;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Signer;
import org.bouncycastle.crypto.digests.NullDigest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.DSADigestSigner;
@@ -14,44 +13,73 @@ import org.bouncycastle.crypto.signers.DSADigestSigner;
public abstract class TlsDSASigner
extends AbstractTlsSigner
{
-
- public byte[] generateRawSignature(AsymmetricKeyParameter privateKey, byte[] md5AndSha1)
+ public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm,
+ AsymmetricKeyParameter privateKey, byte[] hash)
throws CryptoException
{
-
- // Note: Only use the SHA1 part of the hash
- Signer signer = makeSigner(new NullDigest(), true,
+ Signer signer = makeSigner(algorithm, true, true,
new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
- signer.update(md5AndSha1, 16, 20);
+ if (algorithm == null)
+ {
+ // Note: Only use the SHA1 part of the (MD5/SHA1) hash
+ signer.update(hash, 16, 20);
+ }
+ else
+ {
+ signer.update(hash, 0, hash.length);
+ }
return signer.generateSignature();
}
- public boolean verifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5AndSha1)
+ public boolean verifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+ AsymmetricKeyParameter publicKey, byte[] hash)
throws CryptoException
{
-
- // Note: Only use the SHA1 part of the hash
- Signer signer = makeSigner(new NullDigest(), false, publicKey);
- signer.update(md5AndSha1, 16, 20);
+ Signer signer = makeSigner(algorithm, true, false, publicKey);
+ if (algorithm == null)
+ {
+ // Note: Only use the SHA1 part of the (MD5/SHA1) hash
+ signer.update(hash, 16, 20);
+ }
+ else
+ {
+ signer.update(hash, 0, hash.length);
+ }
return signer.verifySignature(sigBytes);
}
- public Signer createSigner(AsymmetricKeyParameter privateKey)
+ public Signer createSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
{
- return makeSigner(new SHA1Digest(), true, new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
+ return makeSigner(algorithm, false, true, new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
}
- public Signer createVerifyer(AsymmetricKeyParameter publicKey)
+ public Signer createVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
{
- return makeSigner(new SHA1Digest(), false, publicKey);
+ return makeSigner(algorithm, false, false, publicKey);
}
- protected Signer makeSigner(Digest d, boolean forSigning, CipherParameters cp)
+ protected Signer makeSigner(SignatureAndHashAlgorithm algorithm, boolean raw, boolean forSigning,
+ CipherParameters cp)
{
+ if ((algorithm != null) != TlsUtils.isTLSv12(context))
+ {
+ throw new IllegalStateException();
+ }
+
+ if (algorithm != null
+ && (algorithm.getHash() != HashAlgorithm.sha1 || algorithm.getSignature() != getSignatureAlgorithm()))
+ {
+ throw new IllegalStateException();
+ }
+
+ Digest d = raw ? new NullDigest() : TlsUtils.createHash(HashAlgorithm.sha1);
+
Signer s = new DSADigestSigner(createDSAImpl(), d);
s.init(forSigning, cp);
return s;
}
+ protected abstract short getSignatureAlgorithm();
+
protected abstract DSA createDSAImpl();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSSSigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSSSigner.java
index e0eeca9..cb698bf 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSSSigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsDSSSigner.java
@@ -8,7 +8,6 @@ import org.bouncycastle.crypto.signers.DSASigner;
public class TlsDSSSigner
extends TlsDSASigner
{
-
public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
{
return publicKey instanceof DSAPublicKeyParameters;
@@ -18,4 +17,9 @@ public class TlsDSSSigner
{
return new DSASigner();
}
+
+ protected short getSignatureAlgorithm()
+ {
+ return SignatureAlgorithm.dsa;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java
index a49f83f..3e7ef39 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECCUtils.java
@@ -1,7 +1,6 @@
package org.bouncycastle.crypto.tls;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -9,7 +8,7 @@ import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Hashtable;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
+import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
@@ -19,91 +18,63 @@ import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.Integers;
public class TlsECCUtils
{
-
public static final Integer EXT_elliptic_curves = Integers.valueOf(ExtensionType.elliptic_curves);
public static final Integer EXT_ec_point_formats = Integers.valueOf(ExtensionType.ec_point_formats);
- private static final String[] curveNames = new String[]{"sect163k1", "sect163r1", "sect163r2", "sect193r1",
+ private static final String[] curveNames = new String[] { "sect163k1", "sect163r1", "sect163r2", "sect193r1",
"sect193r2", "sect233k1", "sect233r1", "sect239k1", "sect283k1", "sect283r1", "sect409k1", "sect409r1",
"sect571k1", "sect571r1", "secp160k1", "secp160r1", "secp160r2", "secp192k1", "secp192r1", "secp224k1",
- "secp224r1", "secp256k1", "secp256r1", "secp384r1", "secp521r1",};
+ "secp224r1", "secp256k1", "secp256r1", "secp384r1", "secp521r1",
+ "brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1"};
- public static void addSupportedEllipticCurvesExtension(Hashtable extensions, int[] namedCurves)
- throws IOException
+ public static void addSupportedEllipticCurvesExtension(Hashtable extensions, int[] namedCurves) throws IOException
{
-
extensions.put(EXT_elliptic_curves, createSupportedEllipticCurvesExtension(namedCurves));
}
public static void addSupportedPointFormatsExtension(Hashtable extensions, short[] ecPointFormats)
throws IOException
{
-
extensions.put(EXT_ec_point_formats, createSupportedPointFormatsExtension(ecPointFormats));
}
- public static int[] getSupportedEllipticCurvesExtension(Hashtable extensions)
- throws IOException
+ public static int[] getSupportedEllipticCurvesExtension(Hashtable extensions) throws IOException
{
-
- if (extensions == null)
- {
- return null;
- }
- byte[] extensionValue = (byte[])extensions.get(EXT_elliptic_curves);
- if (extensionValue == null)
- {
- return null;
- }
- return readSupportedEllipticCurvesExtension(extensionValue);
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_elliptic_curves);
+ return extensionData == null ? null : readSupportedEllipticCurvesExtension(extensionData);
}
- public static short[] getSupportedPointFormatsExtension(Hashtable extensions)
- throws IOException
+ public static short[] getSupportedPointFormatsExtension(Hashtable extensions) throws IOException
{
-
- if (extensions == null)
- {
- return null;
- }
- byte[] extensionValue = (byte[])extensions.get(EXT_ec_point_formats);
- if (extensionValue == null)
- {
- return null;
- }
- return readSupportedPointFormatsExtension(extensionValue);
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_ec_point_formats);
+ return extensionData == null ? null : readSupportedPointFormatsExtension(extensionData);
}
- public static byte[] createSupportedEllipticCurvesExtension(int[] namedCurves)
- throws IOException
+ public static byte[] createSupportedEllipticCurvesExtension(int[] namedCurves) throws IOException
{
-
if (namedCurves == null || namedCurves.length < 1)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeUint16(2 * namedCurves.length, buf);
- TlsUtils.writeUint16Array(namedCurves, buf);
- return buf.toByteArray();
+ return TlsUtils.encodeUint16ArrayWithUint16Length(namedCurves);
}
- public static byte[] createSupportedPointFormatsExtension(short[] ecPointFormats)
- throws IOException
+ public static byte[] createSupportedPointFormatsExtension(short[] ecPointFormats) throws IOException
{
-
if (ecPointFormats == null)
{
- ecPointFormats = new short[]{ECPointFormat.uncompressed};
+ ecPointFormats = new short[] { ECPointFormat.uncompressed };
}
- else if (!TlsProtocol.arrayContains(ecPointFormats, ECPointFormat.uncompressed))
+ else if (!Arrays.contains(ecPointFormats, ECPointFormat.uncompressed))
{
/*
* RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
@@ -118,22 +89,17 @@ public class TlsECCUtils
ecPointFormats = tmp;
}
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeUint8((short)ecPointFormats.length, buf);
- TlsUtils.writeUint8Array(ecPointFormats, buf);
- return buf.toByteArray();
+ return TlsUtils.encodeUint8ArrayWithUint8Length(ecPointFormats);
}
- public static int[] readSupportedEllipticCurvesExtension(byte[] extensionValue)
- throws IOException
+ public static int[] readSupportedEllipticCurvesExtension(byte[] extensionData) throws IOException
{
-
- if (extensionValue == null)
+ if (extensionData == null)
{
- throw new IllegalArgumentException("'extensionValue' cannot be null");
+ throw new IllegalArgumentException("'extensionData' cannot be null");
}
- ByteArrayInputStream buf = new ByteArrayInputStream(extensionValue);
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
int length = TlsUtils.readUint16(buf);
if (length < 2 || (length & 1) != 0)
@@ -148,16 +114,14 @@ public class TlsECCUtils
return namedCurves;
}
- public static short[] readSupportedPointFormatsExtension(byte[] extensionValue)
- throws IOException
+ public static short[] readSupportedPointFormatsExtension(byte[] extensionData) throws IOException
{
-
- if (extensionValue == null)
+ if (extensionData == null)
{
- throw new IllegalArgumentException("'extensionValue' cannot be null");
+ throw new IllegalArgumentException("'extensionData' cannot be null");
}
- ByteArrayInputStream buf = new ByteArrayInputStream(extensionValue);
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
short length = TlsUtils.readUint8(buf);
if (length < 1)
@@ -169,7 +133,7 @@ public class TlsECCUtils
TlsProtocol.assertEmpty(buf);
- if (!TlsProtocol.arrayContains(ecPointFormats, ECPointFormat.uncompressed))
+ if (!Arrays.contains(ecPointFormats, ECPointFormat.uncompressed))
{
/*
* RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
@@ -195,7 +159,7 @@ public class TlsECCUtils
}
// Lazily created the first time a particular curve is accessed
- X9ECParameters ecP = SECNamedCurves.getByName(curveName);
+ X9ECParameters ecP = ECNamedCurveTable.getByName(curveName);
if (ecP == null)
{
@@ -227,6 +191,9 @@ public class TlsECCUtils
{
switch (cipherSuite)
{
+ /*
+ * RFC 4492
+ */
case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
@@ -252,6 +219,10 @@ public class TlsECCUtils
case CipherSuite.TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
case CipherSuite.TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
case CipherSuite.TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
+
+ /*
+ * RFC 5289
+ */
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
@@ -268,7 +239,38 @@ public class TlsECCUtils
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+
+ /*
+ * RFC 5489
+ */
+ case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+
+ /*
+ * draft-josefsson-salsa20-tls-02
+ */
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96:
+
return true;
+
default:
return false;
}
@@ -307,17 +309,13 @@ public class TlsECCUtils
return false;
}
- public static byte[] serializeECFieldElement(int fieldSize, BigInteger x)
- throws IOException
+ public static byte[] serializeECFieldElement(int fieldSize, BigInteger x) throws IOException
{
- int requiredLength = (fieldSize + 7) / 8;
- return BigIntegers.asUnsignedByteArray(requiredLength, x);
+ return BigIntegers.asUnsignedByteArray((fieldSize + 7) / 8, x);
}
- public static byte[] serializeECPoint(short[] ecPointFormats, ECPoint point)
- throws IOException
+ public static byte[] serializeECPoint(short[] ecPointFormats, ECPoint point) throws IOException
{
-
ECCurve curve = point.getCurve();
/*
@@ -341,12 +339,10 @@ public class TlsECCUtils
public static byte[] serializeECPublicKey(short[] ecPointFormats, ECPublicKeyParameters keyParameters)
throws IOException
{
-
return serializeECPoint(ecPointFormats, keyParameters.getQ());
}
- public static BigInteger deserializeECFieldElement(int fieldSize, byte[] encoding)
- throws IOException
+ public static BigInteger deserializeECFieldElement(int fieldSize, byte[] encoding) throws IOException
{
int requiredLength = (fieldSize + 7) / 8;
if (encoding.length != requiredLength)
@@ -356,22 +352,20 @@ public class TlsECCUtils
return new BigInteger(1, encoding);
}
- public static ECPoint deserializeECPoint(short[] ecPointFormats, ECCurve curve, byte[] encoding)
- throws IOException
+ public static ECPoint deserializeECPoint(short[] ecPointFormats, ECCurve curve, byte[] encoding) throws IOException
{
/*
* NOTE: Here we implicitly decode compressed or uncompressed encodings. DefaultTlsClient by
* default is set up to advertise that we can parse any encoding so this works fine, but
* extra checks might be needed here if that were changed.
*/
+ // TODO Review handling of infinity and hybrid encodings
return curve.decodePoint(encoding);
}
public static ECPublicKeyParameters deserializeECPublicKey(short[] ecPointFormats, ECDomainParameters curve_params,
- byte[] encoding)
- throws IOException
+ byte[] encoding) throws IOException
{
-
try
{
ECPoint Y = deserializeECPoint(ecPointFormats, curve_params.getCurve(), encoding);
@@ -385,7 +379,6 @@ public class TlsECCUtils
public static byte[] calculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey)
{
-
ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();
basicAgreement.init(privateKey);
BigInteger agreementValue = basicAgreement.calculateAgreement(publicKey);
@@ -400,22 +393,29 @@ public class TlsECCUtils
public static AsymmetricCipherKeyPair generateECKeyPair(SecureRandom random, ECDomainParameters ecParams)
{
-
ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
- ECKeyGenerationParameters keyGenerationParameters = new ECKeyGenerationParameters(ecParams, random);
- keyPairGenerator.init(keyGenerationParameters);
+ keyPairGenerator.init(new ECKeyGenerationParameters(ecParams, random));
return keyPairGenerator.generateKeyPair();
}
- public static ECPublicKeyParameters validateECPublicKey(ECPublicKeyParameters key)
- throws IOException
+ public static ECPrivateKeyParameters generateEphemeralClientKeyExchange(SecureRandom random, short[] ecPointFormats,
+ ECDomainParameters ecParams, OutputStream output) throws IOException
+ {
+ AsymmetricCipherKeyPair kp = TlsECCUtils.generateECKeyPair(random, ecParams);
+
+ ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters) kp.getPublic();
+ writeECPoint(ecPointFormats, ecPublicKey.getQ(), output);
+
+ return (ECPrivateKeyParameters) kp.getPrivate();
+ }
+
+ public static ECPublicKeyParameters validateECPublicKey(ECPublicKeyParameters key) throws IOException
{
// TODO Check RFC 4492 for validation
return key;
}
- public static int readECExponent(int fieldSize, InputStream input)
- throws IOException
+ public static int readECExponent(int fieldSize, InputStream input) throws IOException
{
BigInteger K = readECParameter(input);
if (K.bitLength() < 32)
@@ -429,14 +429,12 @@ public class TlsECCUtils
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
- public static BigInteger readECFieldElement(int fieldSize, InputStream input)
- throws IOException
+ public static BigInteger readECFieldElement(int fieldSize, InputStream input) throws IOException
{
return deserializeECFieldElement(fieldSize, TlsUtils.readOpaque8(input));
}
- public static BigInteger readECParameter(InputStream input)
- throws IOException
+ public static BigInteger readECParameter(InputStream input) throws IOException
{
// TODO Are leading zeroes okay here?
return new BigInteger(1, TlsUtils.readOpaque8(input));
@@ -445,7 +443,6 @@ public class TlsECCUtils
public static ECDomainParameters readECParameters(int[] namedCurves, short[] ecPointFormats, InputStream input)
throws IOException
{
-
try
{
short curveType = TlsUtils.readUint8(input);
@@ -454,6 +451,8 @@ public class TlsECCUtils
{
case ECCurveType.explicit_prime:
{
+ checkNamedCurve(namedCurves, NamedCurve.arbitrary_explicit_prime_curves);
+
BigInteger prime_p = readECParameter(input);
BigInteger a = readECFieldElement(prime_p.bitLength(), input);
BigInteger b = readECFieldElement(prime_p.bitLength(), input);
@@ -465,11 +464,12 @@ public class TlsECCUtils
}
case ECCurveType.explicit_char2:
{
+ checkNamedCurve(namedCurves, NamedCurve.arbitrary_explicit_char2_curves);
+
int m = TlsUtils.readUint16(input);
short basis = TlsUtils.readUint8(input);
ECCurve curve;
- switch (basis)
- {
+ switch (basis) {
case ECBasisType.ec_basis_trinomial:
{
int k = readECExponent(m, input);
@@ -509,15 +509,7 @@ public class TlsECCUtils
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
- if (!TlsProtocol.arrayContains(namedCurves, namedCurve))
- {
- /*
- * RFC 4492 4. [...] servers MUST NOT negotiate the use of an ECC cipher suite
- * unless they can complete the handshake while respecting the choice of curves
- * and compression techniques specified by the client.
- */
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
+ checkNamedCurve(namedCurves, namedCurve);
return TlsECCUtils.getParametersForNamedCurve(namedCurve);
}
@@ -531,47 +523,59 @@ public class TlsECCUtils
}
}
- public static void writeECExponent(int k, OutputStream output)
- throws IOException
+ private static void checkNamedCurve(int[] namedCurves, int namedCurve) throws IOException
+ {
+ if (namedCurves != null && !Arrays.contains(namedCurves, namedCurve))
+ {
+ /*
+ * RFC 4492 4. [...] servers MUST NOT negotiate the use of an ECC cipher suite
+ * unless they can complete the handshake while respecting the choice of curves
+ * and compression techniques specified by the client.
+ */
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ public static void writeECExponent(int k, OutputStream output) throws IOException
{
BigInteger K = BigInteger.valueOf(k);
writeECParameter(K, output);
}
- public static void writeECFieldElement(int fieldSize, BigInteger x, OutputStream output)
- throws IOException
+ public static void writeECFieldElement(ECFieldElement x, OutputStream output) throws IOException
+ {
+ TlsUtils.writeOpaque8(x.getEncoded(), output);
+ }
+
+ public static void writeECFieldElement(int fieldSize, BigInteger x, OutputStream output) throws IOException
{
TlsUtils.writeOpaque8(serializeECFieldElement(fieldSize, x), output);
}
- public static void writeECParameter(BigInteger x, OutputStream output)
- throws IOException
+ public static void writeECParameter(BigInteger x, OutputStream output) throws IOException
{
TlsUtils.writeOpaque8(BigIntegers.asUnsignedByteArray(x), output);
}
public static void writeExplicitECParameters(short[] ecPointFormats, ECDomainParameters ecParameters,
- OutputStream output)
- throws IOException
+ OutputStream output) throws IOException
{
-
ECCurve curve = ecParameters.getCurve();
if (curve instanceof ECCurve.Fp)
{
-
TlsUtils.writeUint8(ECCurveType.explicit_prime, output);
- ECCurve.Fp fp = (ECCurve.Fp)curve;
+ ECCurve.Fp fp = (ECCurve.Fp) curve;
writeECParameter(fp.getQ(), output);
-
}
else if (curve instanceof ECCurve.F2m)
{
-
TlsUtils.writeUint8(ECCurveType.explicit_char2, output);
- ECCurve.F2m f2m = (ECCurve.F2m)curve;
- TlsUtils.writeUint16(f2m.getM(), output);
+ ECCurve.F2m f2m = (ECCurve.F2m) curve;
+ int m = f2m.getM();
+ TlsUtils.checkUint16(m);
+ TlsUtils.writeUint16(m, output);
if (f2m.isTrinomial())
{
@@ -592,17 +596,20 @@ public class TlsECCUtils
throw new IllegalArgumentException("'ecParameters' not a known curve type");
}
- writeECFieldElement(curve.getFieldSize(), curve.getA().toBigInteger(), output);
- writeECFieldElement(curve.getFieldSize(), curve.getB().toBigInteger(), output);
+ writeECFieldElement(curve.getA(), output);
+ writeECFieldElement(curve.getB(), output);
TlsUtils.writeOpaque8(serializeECPoint(ecPointFormats, ecParameters.getG()), output);
writeECParameter(ecParameters.getN(), output);
writeECParameter(ecParameters.getH(), output);
}
- public static void writeNamedECParameters(int namedCurve, OutputStream output)
- throws IOException
+ public static void writeECPoint(short[] ecPointFormats, ECPoint point, OutputStream output) throws IOException
{
+ TlsUtils.writeOpaque8(TlsECCUtils.serializeECPoint(ecPointFormats, point), output);
+ }
+ public static void writeNamedECParameters(int namedCurve, OutputStream output) throws IOException
+ {
if (!NamedCurve.refersToASpecificNamedCurve(namedCurve))
{
/*
@@ -614,6 +621,7 @@ public class TlsECCUtils
}
TlsUtils.writeUint8(ECCurveType.named_curve, output);
+ TlsUtils.checkUint16(namedCurve);
TlsUtils.writeUint16(namedCurve, output);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java
index 1124560..d346ef4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java
@@ -1,6 +1,5 @@
package org.bouncycastle.crypto.tls;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
@@ -8,10 +7,11 @@ import java.util.Vector;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Signer;
-import org.bouncycastle.crypto.io.SignerInputStream;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.io.TeeInputStream;
/**
* ECDHE key exchange (see RFC 4492)
@@ -19,11 +19,10 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters;
public class TlsECDHEKeyExchange
extends TlsECDHKeyExchange
{
-
protected TlsSignerCredentials serverCredentials = null;
public TlsECDHEKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, int[] namedCurves,
- short[] clientECPointFormats, short[] serverECPointFormats)
+ short[] clientECPointFormats, short[] serverECPointFormats)
{
super(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats, serverECPointFormats);
}
@@ -31,7 +30,6 @@ public class TlsECDHEKeyExchange
public void processServerCredentials(TlsCredentials serverCredentials)
throws IOException
{
-
if (!(serverCredentials instanceof TlsSignerCredentials))
{
throw new TlsFatalAlert(AlertDescription.internal_error);
@@ -45,13 +43,13 @@ public class TlsECDHEKeyExchange
public byte[] generateServerKeyExchange()
throws IOException
{
-
/*
* First we try to find a supported named curve from the client's list.
*/
int namedCurve = -1;
if (namedCurves == null)
{
+ // TODO Let the peer choose the default named curve
namedCurve = NamedCurve.secp256r1;
}
else
@@ -77,13 +75,13 @@ public class TlsECDHEKeyExchange
/*
* If no named curves are suitable, check if the client supports explicit curves.
*/
- if (TlsProtocol.arrayContains(namedCurves, NamedCurve.arbitrary_explicit_prime_curves))
+ if (Arrays.contains(namedCurves, NamedCurve.arbitrary_explicit_prime_curves))
{
curve_params = TlsECCUtils.getParametersForNamedCurve(NamedCurve.secp256r1);
}
- else if (TlsProtocol.arrayContains(namedCurves, NamedCurve.arbitrary_explicit_char2_curves))
+ else if (Arrays.contains(namedCurves, NamedCurve.arbitrary_explicit_char2_curves))
{
- curve_params = TlsECCUtils.getParametersForNamedCurve(NamedCurve.sect233r1);
+ curve_params = TlsECCUtils.getParametersForNamedCurve(NamedCurve.sect283r1);
}
}
@@ -97,12 +95,9 @@ public class TlsECDHEKeyExchange
}
AsymmetricCipherKeyPair kp = TlsECCUtils.generateECKeyPair(context.getSecureRandom(), curve_params);
- this.ecAgreeServerPrivateKey = (ECPrivateKeyParameters)kp.getPrivate();
+ this.ecAgreePrivateKey = (ECPrivateKeyParameters)kp.getPrivate();
- byte[] publicBytes = TlsECCUtils.serializeECPublicKey(clientECPointFormats,
- (ECPublicKeyParameters)kp.getPublic());
-
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ DigestInputBuffer buf = new DigestInputBuffer();
if (namedCurve < 0)
{
@@ -113,25 +108,43 @@ public class TlsECDHEKeyExchange
TlsECCUtils.writeNamedECParameters(namedCurve, buf);
}
- TlsUtils.writeOpaque8(publicBytes, buf);
+ ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters) kp.getPublic();
+ TlsECCUtils.writeECPoint(clientECPointFormats, ecPublicKey.getQ(), buf);
+
+ /*
+ * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
+ */
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm;
+ Digest d;
+
+ if (TlsUtils.isTLSv12(context))
+ {
+ signatureAndHashAlgorithm = serverCredentials.getSignatureAndHashAlgorithm();
+ if (signatureAndHashAlgorithm == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
- byte[] digestInput = buf.toByteArray();
+ d = TlsUtils.createHash(signatureAndHashAlgorithm.getHash());
+ }
+ else
+ {
+ signatureAndHashAlgorithm = null;
+ d = new CombinedHash();
+ }
- Digest d = new CombinedHash();
SecurityParameters securityParameters = context.getSecurityParameters();
d.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
d.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
- d.update(digestInput, 0, digestInput.length);
+ buf.updateDigest(d);
byte[] hash = new byte[d.getDigestSize()];
d.doFinal(hash, 0);
- byte[] sigBytes = serverCredentials.generateCertificateSignature(hash);
- /*
- * TODO RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm prepended
- * from TLS 1.2
- */
- TlsUtils.writeOpaque16(sigBytes, buf);
+ byte[] signature = serverCredentials.generateCertificateSignature(hash);
+
+ DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature);
+ signed_params.encode(buf);
return buf.toByteArray();
}
@@ -139,23 +152,25 @@ public class TlsECDHEKeyExchange
public void processServerKeyExchange(InputStream input)
throws IOException
{
-
SecurityParameters securityParameters = context.getSecurityParameters();
- Signer signer = initVerifyer(tlsSigner, securityParameters);
- InputStream sigIn = new SignerInputStream(input, signer);
+ SignerInputBuffer buf = new SignerInputBuffer();
+ InputStream teeIn = new TeeInputStream(input, buf);
+
+ ECDomainParameters curve_params = TlsECCUtils.readECParameters(namedCurves, clientECPointFormats, teeIn);
- ECDomainParameters curve_params = TlsECCUtils.readECParameters(namedCurves, clientECPointFormats, sigIn);
+ byte[] point = TlsUtils.readOpaque8(teeIn);
- byte[] point = TlsUtils.readOpaque8(sigIn);
+ DigitallySigned signed_params = DigitallySigned.parse(context, input);
- byte[] sigByte = TlsUtils.readOpaque16(input);
- if (!signer.verifySignature(sigByte))
+ Signer signer = initVerifyer(tlsSigner, signed_params.getAlgorithm(), securityParameters);
+ buf.updateSigner(signer);
+ if (!signer.verifySignature(signed_params.getSignature()))
{
throw new TlsFatalAlert(AlertDescription.decrypt_error);
}
- this.ecAgreeServerPublicKey = TlsECCUtils.validateECPublicKey(TlsECCUtils.deserializeECPublicKey(
+ this.ecAgreePublicKey = TlsECCUtils.validateECPublicKey(TlsECCUtils.deserializeECPublicKey(
clientECPointFormats, curve_params, point));
}
@@ -196,9 +211,9 @@ public class TlsECDHEKeyExchange
}
}
- protected Signer initVerifyer(TlsSigner tlsSigner, SecurityParameters securityParameters)
+ protected Signer initVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, SecurityParameters securityParameters)
{
- Signer signer = tlsSigner.createVerifyer(this.serverPublicKey);
+ Signer signer = tlsSigner.createVerifyer(algorithm, this.serverPublicKey);
signer.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
signer.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
return signer;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java
index 26c0975..9456352 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java
@@ -7,7 +7,6 @@ import java.util.Vector;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
@@ -17,26 +16,21 @@ import org.bouncycastle.crypto.util.PublicKeyFactory;
/**
* ECDH key exchange (see RFC 4492)
*/
-public class TlsECDHKeyExchange
- extends AbstractTlsKeyExchange
+public class TlsECDHKeyExchange extends AbstractTlsKeyExchange
{
-
protected TlsSigner tlsSigner;
protected int[] namedCurves;
protected short[] clientECPointFormats, serverECPointFormats;
protected AsymmetricKeyParameter serverPublicKey;
- protected ECPublicKeyParameters ecAgreeServerPublicKey;
protected TlsAgreementCredentials agreementCredentials;
- protected ECPrivateKeyParameters ecAgreeClientPrivateKey;
- protected ECPrivateKeyParameters ecAgreeServerPrivateKey;
- protected ECPublicKeyParameters ecAgreeClientPublicKey;
+ protected ECPrivateKeyParameters ecAgreePrivateKey;
+ protected ECPublicKeyParameters ecAgreePublicKey;
public TlsECDHKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, int[] namedCurves,
- short[] clientECPointFormats, short[] serverECPointFormats)
+ short[] clientECPointFormats, short[] serverECPointFormats)
{
-
super(keyExchange, supportedSignatureAlgorithms);
switch (keyExchange)
@@ -71,16 +65,13 @@ public class TlsECDHKeyExchange
}
}
- public void skipServerCredentials()
- throws IOException
+ public void skipServerCredentials() throws IOException
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- public void processServerCertificate(Certificate serverCertificate)
- throws IOException
+ public void processServerCertificate(Certificate serverCertificate) throws IOException
{
-
if (serverCertificate.isEmpty())
{
throw new TlsFatalAlert(AlertDescription.bad_certificate);
@@ -102,8 +93,7 @@ public class TlsECDHKeyExchange
{
try
{
- this.ecAgreeServerPublicKey = TlsECCUtils
- .validateECPublicKey((ECPublicKeyParameters)this.serverPublicKey);
+ this.ecAgreePublicKey = TlsECCUtils.validateECPublicKey((ECPublicKeyParameters) this.serverPublicKey);
}
catch (ClassCastException e)
{
@@ -138,8 +128,7 @@ public class TlsECDHKeyExchange
}
}
- public void validateCertificateRequest(CertificateRequest certificateRequest)
- throws IOException
+ public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException
{
/*
* RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with
@@ -164,14 +153,13 @@ public class TlsECDHKeyExchange
}
}
- public void processClientCredentials(TlsCredentials clientCredentials)
- throws IOException
+ public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
{
if (clientCredentials instanceof TlsAgreementCredentials)
{
// TODO Validate client cert has matching parameters (see 'TlsECCUtils.areOnSameCurve')?
- this.agreementCredentials = (TlsAgreementCredentials)clientCredentials;
+ this.agreementCredentials = (TlsAgreementCredentials) clientCredentials;
}
else if (clientCredentials instanceof TlsSignerCredentials)
{
@@ -183,37 +171,24 @@ public class TlsECDHKeyExchange
}
}
- public void generateClientKeyExchange(OutputStream output)
- throws IOException
+ public void generateClientKeyExchange(OutputStream output) throws IOException
{
- if (agreementCredentials != null)
+ if (agreementCredentials == null)
{
- return;
+ this.ecAgreePrivateKey = TlsECCUtils.generateEphemeralClientKeyExchange(context.getSecureRandom(),
+ serverECPointFormats, ecAgreePublicKey.getParameters(), output);
}
-
- AsymmetricCipherKeyPair ecAgreeClientKeyPair = TlsECCUtils.generateECKeyPair(context.getSecureRandom(),
- ecAgreeServerPublicKey.getParameters());
- this.ecAgreeClientPrivateKey = (ECPrivateKeyParameters)ecAgreeClientKeyPair.getPrivate();
-
- byte[] point = TlsECCUtils.serializeECPublicKey(serverECPointFormats,
- (ECPublicKeyParameters)ecAgreeClientKeyPair.getPublic());
-
- TlsUtils.writeOpaque8(point, output);
}
- public void processClientCertificate(Certificate clientCertificate)
- throws IOException
+ public void processClientCertificate(Certificate clientCertificate) throws IOException
{
-
// TODO Extract the public key
// TODO If the certificate is 'fixed', take the public key as ecAgreeClientPublicKey
}
- public void processClientKeyExchange(InputStream input)
- throws IOException
+ public void processClientKeyExchange(InputStream input) throws IOException
{
-
- if (ecAgreeClientPublicKey != null)
+ if (ecAgreePublicKey != null)
{
// For ecdsa_fixed_ecdh and rsa_fixed_ecdh, the key arrived in the client certificate
return;
@@ -221,28 +196,22 @@ public class TlsECDHKeyExchange
byte[] point = TlsUtils.readOpaque8(input);
- ECDomainParameters curve_params = this.ecAgreeServerPrivateKey.getParameters();
+ ECDomainParameters curve_params = this.ecAgreePrivateKey.getParameters();
- this.ecAgreeClientPublicKey = TlsECCUtils.validateECPublicKey(TlsECCUtils.deserializeECPublicKey(
+ this.ecAgreePublicKey = TlsECCUtils.validateECPublicKey(TlsECCUtils.deserializeECPublicKey(
serverECPointFormats, curve_params, point));
}
- public byte[] generatePremasterSecret()
- throws IOException
+ public byte[] generatePremasterSecret() throws IOException
{
if (agreementCredentials != null)
{
- return agreementCredentials.generateAgreement(ecAgreeServerPublicKey);
- }
-
- if (ecAgreeServerPrivateKey != null)
- {
- return TlsECCUtils.calculateECDHBasicAgreement(ecAgreeClientPublicKey, ecAgreeServerPrivateKey);
+ return agreementCredentials.generateAgreement(ecAgreePublicKey);
}
- if (ecAgreeClientPrivateKey != null)
+ if (ecAgreePrivateKey != null)
{
- return TlsECCUtils.calculateECDHBasicAgreement(ecAgreeServerPublicKey, ecAgreeClientPrivateKey);
+ return TlsECCUtils.calculateECDHBasicAgreement(ecAgreePublicKey, ecAgreePrivateKey);
}
throw new TlsFatalAlert(AlertDescription.internal_error);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDSASigner.java
index 6809815..d7f8064 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsECDSASigner.java
@@ -8,7 +8,6 @@ import org.bouncycastle.crypto.signers.ECDSASigner;
public class TlsECDSASigner
extends TlsDSASigner
{
-
public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
{
return publicKey instanceof ECPublicKeyParameters;
@@ -18,4 +17,9 @@ public class TlsECDSASigner
{
return new ECDSASigner();
}
+
+ protected short getSignatureAlgorithm()
+ {
+ return SignatureAlgorithm.ecdsa;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsEncryptionCredentials.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsEncryptionCredentials.java
index 2680136..eddf684 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsEncryptionCredentials.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsEncryptionCredentials.java
@@ -5,7 +5,6 @@ import java.io.IOException;
public interface TlsEncryptionCredentials
extends TlsCredentials
{
-
byte[] decryptPreMasterSecret(byte[] encryptedPreMasterSecret)
throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java
new file mode 100644
index 0000000..fbc39dd
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java
@@ -0,0 +1,240 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.bouncycastle.util.Integers;
+
+public class TlsExtensionsUtils
+{
+ public static final Integer EXT_heartbeat = Integers.valueOf(ExtensionType.heartbeat);
+ public static final Integer EXT_max_fragment_length = Integers.valueOf(ExtensionType.max_fragment_length);
+ public static final Integer EXT_server_name = Integers.valueOf(ExtensionType.server_name);
+ public static final Integer EXT_status_request = Integers.valueOf(ExtensionType.status_request);
+ public static final Integer EXT_truncated_hmac = Integers.valueOf(ExtensionType.truncated_hmac);
+
+ public static Hashtable ensureExtensionsInitialised(Hashtable extensions)
+ {
+ return extensions == null ? new Hashtable() : extensions;
+ }
+
+ public static void addHeartbeatExtension(Hashtable extensions, HeartbeatExtension heartbeatExtension)
+ throws IOException
+ {
+ extensions.put(EXT_heartbeat, createHeartbeatExtension(heartbeatExtension));
+ }
+
+ public static void addMaxFragmentLengthExtension(Hashtable extensions, short maxFragmentLength)
+ throws IOException
+ {
+ extensions.put(EXT_max_fragment_length, createMaxFragmentLengthExtension(maxFragmentLength));
+ }
+
+ public static void addServerNameExtension(Hashtable extensions, ServerNameList serverNameList)
+ throws IOException
+ {
+ extensions.put(EXT_server_name, createServerNameExtension(serverNameList));
+ }
+
+ public static void addStatusRequestExtension(Hashtable extensions, CertificateStatusRequest statusRequest)
+ throws IOException
+ {
+ extensions.put(EXT_status_request, createStatusRequestExtension(statusRequest));
+ }
+
+ public static void addTruncatedHMacExtension(Hashtable extensions)
+ {
+ extensions.put(EXT_truncated_hmac, createTruncatedHMacExtension());
+ }
+
+ public static HeartbeatExtension getHeartbeatExtension(Hashtable extensions)
+ throws IOException
+ {
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_heartbeat);
+ return extensionData == null ? null : readHeartbeatExtension(extensionData);
+ }
+
+ public static short getMaxFragmentLengthExtension(Hashtable extensions)
+ throws IOException
+ {
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_max_fragment_length);
+ return extensionData == null ? -1 : readMaxFragmentLengthExtension(extensionData);
+ }
+
+ public static ServerNameList getServerNameExtension(Hashtable extensions)
+ throws IOException
+ {
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_server_name);
+ return extensionData == null ? null : readServerNameExtension(extensionData);
+ }
+
+ public static CertificateStatusRequest getStatusRequestExtension(Hashtable extensions)
+ throws IOException
+ {
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_status_request);
+ return extensionData == null ? null : readStatusRequestExtension(extensionData);
+ }
+
+ public static boolean hasTruncatedHMacExtension(Hashtable extensions) throws IOException
+ {
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_truncated_hmac);
+ return extensionData == null ? false : readTruncatedHMacExtension(extensionData);
+ }
+
+ public static byte[] createEmptyExtensionData()
+ {
+ return TlsUtils.EMPTY_BYTES;
+ }
+
+ public static byte[] createHeartbeatExtension(HeartbeatExtension heartbeatExtension)
+ throws IOException
+ {
+ if (heartbeatExtension == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ heartbeatExtension.encode(buf);
+
+ return buf.toByteArray();
+ }
+
+ public static byte[] createMaxFragmentLengthExtension(short maxFragmentLength)
+ throws IOException
+ {
+ if (!MaxFragmentLength.isValid(maxFragmentLength))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ return new byte[]{ (byte)maxFragmentLength };
+ }
+
+ public static byte[] createServerNameExtension(ServerNameList serverNameList)
+ throws IOException
+ {
+ if (serverNameList == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ serverNameList.encode(buf);
+
+ return buf.toByteArray();
+ }
+
+ public static byte[] createStatusRequestExtension(CertificateStatusRequest statusRequest)
+ throws IOException
+ {
+ if (statusRequest == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ statusRequest.encode(buf);
+
+ return buf.toByteArray();
+ }
+
+ public static byte[] createTruncatedHMacExtension()
+ {
+ return createEmptyExtensionData();
+ }
+
+ public static HeartbeatExtension readHeartbeatExtension(byte[] extensionData)
+ throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
+
+ HeartbeatExtension heartbeatExtension = HeartbeatExtension.parse(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ return heartbeatExtension;
+ }
+
+ public static short readMaxFragmentLengthExtension(byte[] extensionData)
+ throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ if (extensionData.length != 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ short maxFragmentLength = (short)extensionData[0];
+
+ if (!MaxFragmentLength.isValid(maxFragmentLength))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return maxFragmentLength;
+ }
+
+ public static ServerNameList readServerNameExtension(byte[] extensionData)
+ throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
+
+ ServerNameList serverNameList = ServerNameList.parse(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ return serverNameList;
+ }
+
+ public static CertificateStatusRequest readStatusRequestExtension(byte[] extensionData)
+ throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
+
+ CertificateStatusRequest statusRequest = CertificateStatusRequest.parse(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ return statusRequest;
+ }
+
+ private static boolean readTruncatedHMacExtension(byte[] extensionData) throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ if (extensionData.length != 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return true;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsHandshakeHash.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsHandshakeHash.java
index b17b8d7..1cb0f4d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsHandshakeHash.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsHandshakeHash.java
@@ -5,10 +5,17 @@ import org.bouncycastle.crypto.Digest;
interface TlsHandshakeHash
extends Digest
{
-
void init(TlsContext context);
- TlsHandshakeHash commit();
+ TlsHandshakeHash notifyPRFDetermined();
+
+ void trackHashAlgorithm(short hashAlgorithm);
+
+ void sealHashAlgorithms();
+
+ TlsHandshakeHash stopTracking();
+
+ Digest forkPRFHash();
- TlsHandshakeHash fork();
+ byte[] getFinalHash(short hashAlgorithm);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsMac.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsMac.java
index ec11130..20dfef8 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsMac.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsMac.java
@@ -1,8 +1,5 @@
package org.bouncycastle.crypto.tls;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.digests.LongDigest;
@@ -15,19 +12,19 @@ import org.bouncycastle.util.Arrays;
*/
public class TlsMac
{
-
protected TlsContext context;
protected byte[] secret;
protected Mac mac;
protected int digestBlockSize;
protected int digestOverhead;
+ protected int macLength;
/**
* Generate a new instance of an TlsMac.
*
* @param context the TLS client context
* @param digest The digest to use.
- * @param key A byte-array where the key for this mac is located.
+ * @param key A byte-array where the key for this MAC is located.
* @param keyOff The number of bytes to skip, before the key starts in the buffer.
* @param len The length of the key.
*/
@@ -51,7 +48,7 @@ public class TlsMac
this.digestOverhead = 8;
}
- if (context.getServerVersion().isSSL())
+ if (TlsUtils.isSSL(context))
{
this.mac = new SSL3Mac(digest);
@@ -73,6 +70,12 @@ public class TlsMac
}
this.mac.init(keyParameter);
+
+ this.macLength = mac.getMacSize();
+ if (context.getSecurityParameters().truncatedHMac)
+ {
+ this.macLength = Math.min(this.macLength, 10);
+ }
}
/**
@@ -84,11 +87,11 @@ public class TlsMac
}
/**
- * @return The Keysize of the mac.
+ * @return The output length of this MAC.
*/
public int getSize()
{
- return mac.getMacSize();
+ return macLength;
}
/**
@@ -102,42 +105,38 @@ public class TlsMac
*/
public byte[] calculateMac(long seqNo, short type, byte[] message, int offset, int length)
{
+ /*
+ * TODO[draft-josefsson-salsa20-tls-02] 3. Moreover, in order to accommodate MAC algorithms
+ * like UMAC that require a nonce as part of their operation, the document extends the MAC
+ * algorithm as specified in the TLS protocol. The extended MAC includes a nonce as a second
+ * parameter. MAC algorithms that do not require a nonce, such as HMAC, are assumed to
+ * ignore the nonce input value. The MAC in a GenericStreamCipher is then calculated as
+ * follows.
+ */
ProtocolVersion serverVersion = context.getServerVersion();
boolean isSSL = serverVersion.isSSL();
- ByteArrayOutputStream bosMac = new ByteArrayOutputStream(isSSL ? 11 : 13);
- try
+ byte[] macHeader = new byte[isSSL ? 11 : 13];
+ TlsUtils.writeUint64(seqNo, macHeader, 0);
+ TlsUtils.writeUint8(type, macHeader, 8);
+ if (!isSSL)
{
- TlsUtils.writeUint64(seqNo, bosMac);
- TlsUtils.writeUint8(type, bosMac);
-
- if (!isSSL)
- {
- TlsUtils.writeVersion(serverVersion, bosMac);
- }
-
- TlsUtils.writeUint16(length, bosMac);
- }
- catch (IOException e)
- {
- // This should never happen
- throw new IllegalStateException("Internal error during mac calculation");
+ TlsUtils.writeVersion(serverVersion, macHeader, 9);
}
+ TlsUtils.writeUint16(length, macHeader, macHeader.length - 2);
- byte[] macHeader = bosMac.toByteArray();
mac.update(macHeader, 0, macHeader.length);
mac.update(message, offset, length);
byte[] result = new byte[mac.getMacSize()];
mac.doFinal(result, 0);
- return result;
+ return truncate(result);
}
public byte[] calculateMacConstantTime(long seqNo, short type, byte[] message, int offset, int length,
- int fullLength, byte[] dummyData)
+ int fullLength, byte[] dummyData)
{
-
/*
* Actual MAC only calculated on 'length' bytes...
*/
@@ -147,7 +146,7 @@ public class TlsMac
* ...but ensure a constant number of complete digest blocks are processed (as many as would
* be needed for 'fullLength' bytes of input).
*/
- int headerLength = context.getServerVersion().isSSL() ? 11 : 13;
+ int headerLength = TlsUtils.isSSL(context) ? 11 : 13;
// How many extra full blocks do we need to calculate?
int extra = getDigestBlockCount(headerLength + fullLength) - getDigestBlockCount(headerLength + length);
@@ -164,9 +163,19 @@ public class TlsMac
return result;
}
- private int getDigestBlockCount(int inputLength)
+ protected int getDigestBlockCount(int inputLength)
{
// NOTE: This calculation assumes a minimum of 1 pad byte
return (inputLength + digestOverhead) / digestBlockSize;
}
+
+ protected byte[] truncate(byte[] bs)
+ {
+ if (bs.length <= macLength)
+ {
+ return bs;
+ }
+
+ return Arrays.copyOf(bs, macLength);
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNullCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNullCipher.java
index d5b2b98..d1f6986 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNullCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNullCipher.java
@@ -26,7 +26,6 @@ public class TlsNullCipher
public TlsNullCipher(TlsContext context, Digest clientWriteDigest, Digest serverWriteDigest)
throws IOException
{
-
if ((clientWriteDigest == null) != (serverWriteDigest == null))
{
throw new TlsFatalAlert(AlertDescription.internal_error);
@@ -38,7 +37,6 @@ public class TlsNullCipher
if (clientWriteDigest != null)
{
-
int key_block_size = clientWriteDigest.getDigestSize()
+ serverWriteDigest.getDigestSize();
byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
@@ -84,7 +82,6 @@ public class TlsNullCipher
public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len)
throws IOException
{
-
if (writeMac == null)
{
return Arrays.copyOfRange(plaintext, offset, offset + len);
@@ -100,7 +97,6 @@ public class TlsNullCipher
public byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len)
throws IOException
{
-
if (readMac == null)
{
return Arrays.copyOfRange(ciphertext, offset, offset + len);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java
index cfabb76..7217bac 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java
@@ -4,7 +4,6 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.math.BigInteger;
import java.util.Vector;
import org.bouncycastle.asn1.x509.KeyUsage;
@@ -22,33 +21,42 @@ import org.bouncycastle.crypto.util.PublicKeyFactory;
public class TlsPSKKeyExchange
extends AbstractTlsKeyExchange
{
-
protected TlsPSKIdentity pskIdentity;
+ protected DHParameters dhParameters;
+ protected int[] namedCurves;
+ protected short[] clientECPointFormats, serverECPointFormats;
protected byte[] psk_identity_hint = null;
- protected DHPublicKeyParameters dhAgreeServerPublicKey = null;
- protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null;
+ protected DHPrivateKeyParameters dhAgreePrivateKey = null;
+ protected DHPublicKeyParameters dhAgreePublicKey = null;
protected AsymmetricKeyParameter serverPublicKey = null;
protected RSAKeyParameters rsaServerPublicKey = null;
+ protected TlsEncryptionCredentials serverCredentials = null;
protected byte[] premasterSecret;
- public TlsPSKKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, TlsPSKIdentity pskIdentity)
+ public TlsPSKKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, TlsPSKIdentity pskIdentity,
+ DHParameters dhParameters, int[] namedCurves, short[] clientECPointFormats, short[] serverECPointFormats)
{
super(keyExchange, supportedSignatureAlgorithms);
switch (keyExchange)
{
+ case KeyExchangeAlgorithm.DHE_PSK:
+ case KeyExchangeAlgorithm.ECDHE_PSK:
case KeyExchangeAlgorithm.PSK:
case KeyExchangeAlgorithm.RSA_PSK:
- case KeyExchangeAlgorithm.DHE_PSK:
break;
default:
throw new IllegalArgumentException("unsupported key exchange algorithm");
}
this.pskIdentity = pskIdentity;
+ this.dhParameters = dhParameters;
+ this.namedCurves = namedCurves;
+ this.clientECPointFormats = clientECPointFormats;
+ this.serverECPointFormats = serverECPointFormats;
}
public void skipServerCredentials()
@@ -60,10 +68,61 @@ public class TlsPSKKeyExchange
}
}
- public void processServerCertificate(Certificate serverCertificate)
+ public void processServerCredentials(TlsCredentials serverCredentials)
throws IOException
{
+ if (!(serverCredentials instanceof TlsEncryptionCredentials))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ processServerCertificate(serverCredentials.getCertificate());
+
+ this.serverCredentials = (TlsEncryptionCredentials)serverCredentials;
+ }
+
+ public byte[] generateServerKeyExchange() throws IOException
+ {
+ // TODO[RFC 4279] Need a server-side PSK API to determine hint and resolve identities to keys
+ this.psk_identity_hint = null;
+
+ if (this.psk_identity_hint == null && !requiresServerKeyExchange())
+ {
+ return null;
+ }
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+ if (this.psk_identity_hint == null)
+ {
+ TlsUtils.writeOpaque16(TlsUtils.EMPTY_BYTES, buf);
+ }
+ else
+ {
+ TlsUtils.writeOpaque16(this.psk_identity_hint, buf);
+ }
+
+ if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ if (this.dhParameters == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ this.dhAgreePrivateKey = TlsDHUtils.generateEphemeralServerKeyExchange(context.getSecureRandom(),
+ this.dhParameters, buf);
+ }
+ else if (this.keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+ {
+ // TODO[RFC 5489]
+ }
+
+ return buf.toByteArray();
+ }
+ public void processServerCertificate(Certificate serverCertificate)
+ throws IOException
+ {
if (keyExchange != KeyExchangeAlgorithm.RSA_PSK)
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
@@ -100,27 +159,30 @@ public class TlsPSKKeyExchange
public boolean requiresServerKeyExchange()
{
- return keyExchange == KeyExchangeAlgorithm.DHE_PSK;
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.DHE_PSK:
+ case KeyExchangeAlgorithm.ECDHE_PSK:
+ return true;
+ default:
+ return false;
+ }
}
public void processServerKeyExchange(InputStream input)
throws IOException
{
-
this.psk_identity_hint = TlsUtils.readOpaque16(input);
if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
{
- byte[] pBytes = TlsUtils.readOpaque16(input);
- byte[] gBytes = TlsUtils.readOpaque16(input);
- byte[] YsBytes = TlsUtils.readOpaque16(input);
+ ServerDHParams serverDHParams = ServerDHParams.parse(input);
- BigInteger p = new BigInteger(1, pBytes);
- BigInteger g = new BigInteger(1, gBytes);
- BigInteger Ys = new BigInteger(1, YsBytes);
-
- this.dhAgreeServerPublicKey = TlsDHUtils.validateDHPublicKey(new DHPublicKeyParameters(Ys,
- new DHParameters(p, g)));
+ this.dhAgreePublicKey = TlsDHUtils.validateDHPublicKey(serverDHParams.getPublicKey());
+ }
+ else if (this.keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+ {
+ // TODO[RFC 5489]
}
}
@@ -139,7 +201,6 @@ public class TlsPSKKeyExchange
public void generateClientKeyExchange(OutputStream output)
throws IOException
{
-
if (psk_identity_hint == null)
{
pskIdentity.skipIdentityHint();
@@ -153,22 +214,26 @@ public class TlsPSKKeyExchange
TlsUtils.writeOpaque16(psk_identity, output);
- if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
+ if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
{
- this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context, this.rsaServerPublicKey,
- output);
+ this.dhAgreePrivateKey = TlsDHUtils.generateEphemeralClientKeyExchange(context.getSecureRandom(),
+ dhAgreePublicKey.getParameters(), output);
+ }
+ else if (this.keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+ {
+ // TODO[RFC 5489]
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
- else if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ else if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
{
- this.dhAgreeClientPrivateKey = TlsDHUtils.generateEphemeralClientKeyExchange(context.getSecureRandom(),
- dhAgreeServerPublicKey.getParameters(), output);
+ this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context, this.rsaServerPublicKey,
+ output);
}
}
public byte[] generatePremasterSecret()
throws IOException
{
-
byte[] psk = pskIdentity.getPSK();
byte[] other_secret = generateOtherSecret(psk.length);
@@ -178,12 +243,22 @@ public class TlsPSKKeyExchange
return buf.toByteArray();
}
- protected byte[] generateOtherSecret(int pskLength)
+ protected byte[] generateOtherSecret(int pskLength) throws IOException
{
-
if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
{
- return TlsDHUtils.calculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
+ if (dhAgreePrivateKey != null)
+ {
+ return TlsDHUtils.calculateDHBasicAgreement(dhAgreePublicKey, dhAgreePrivateKey);
+ }
+
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ if (this.keyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+ {
+ // TODO[RFC 5489]
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPeer.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPeer.java
index e408002..88780ea 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPeer.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsPeer.java
@@ -1,7 +1,14 @@
package org.bouncycastle.crypto.tls;
+import java.io.IOException;
+
public interface TlsPeer
{
+ void notifySecureRenegotiation(boolean secureNegotiation) throws IOException;
+
+ TlsCompression getCompression() throws IOException;
+
+ TlsCipher getCipher() throws IOException;
/**
* This method will be called when an alert is raised by the protocol.
@@ -20,4 +27,9 @@ public interface TlsPeer
* @param alertDescription {@link AlertDescription}
*/
void notifyAlertReceived(short alertLevel, short alertDescription);
+
+ /**
+ * Notifies the peer that the handshake has been successfully completed.
+ */
+ void notifyHandshakeComplete() throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsProtocol.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsProtocol.java
index 6d8e3d3..2c3b094 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsProtocol.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsProtocol.java
@@ -2,6 +2,7 @@ package org.bouncycastle.crypto.tls;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -10,6 +11,7 @@ import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
+import org.bouncycastle.crypto.Digest;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Integers;
@@ -18,7 +20,6 @@ import org.bouncycastle.util.Integers;
*/
public abstract class TlsProtocol
{
-
protected static final Integer EXT_RenegotiationInfo = Integers.valueOf(ExtensionType.renegotiation_info);
protected static final Integer EXT_SessionTicket = Integers.valueOf(ExtensionType.session_ticket);
@@ -32,25 +33,24 @@ public abstract class TlsProtocol
protected static final short CS_SERVER_HELLO = 2;
protected static final short CS_SERVER_SUPPLEMENTAL_DATA = 3;
protected static final short CS_SERVER_CERTIFICATE = 4;
- protected static final short CS_SERVER_KEY_EXCHANGE = 5;
- protected static final short CS_CERTIFICATE_REQUEST = 6;
- protected static final short CS_SERVER_HELLO_DONE = 7;
- protected static final short CS_CLIENT_SUPPLEMENTAL_DATA = 8;
- protected static final short CS_CLIENT_CERTIFICATE = 9;
- protected static final short CS_CLIENT_KEY_EXCHANGE = 10;
- protected static final short CS_CERTIFICATE_VERIFY = 11;
- protected static final short CS_CLIENT_CHANGE_CIPHER_SPEC = 12;
+ protected static final short CS_CERTIFICATE_STATUS = 5;
+ protected static final short CS_SERVER_KEY_EXCHANGE = 6;
+ protected static final short CS_CERTIFICATE_REQUEST = 7;
+ protected static final short CS_SERVER_HELLO_DONE = 8;
+ protected static final short CS_CLIENT_SUPPLEMENTAL_DATA = 9;
+ protected static final short CS_CLIENT_CERTIFICATE = 10;
+ protected static final short CS_CLIENT_KEY_EXCHANGE = 11;
+ protected static final short CS_CERTIFICATE_VERIFY = 12;
protected static final short CS_CLIENT_FINISHED = 13;
protected static final short CS_SERVER_SESSION_TICKET = 14;
- protected static final short CS_SERVER_CHANGE_CIPHER_SPEC = 15;
- protected static final short CS_SERVER_FINISHED = 16;
+ protected static final short CS_SERVER_FINISHED = 15;
+ protected static final short CS_END = 16;
/*
* Queues for data from some protocols.
*/
private ByteQueue applicationDataQueue = new ByteQueue();
- private ByteQueue changeCipherSpecQueue = new ByteQueue();
- private ByteQueue alertQueue = new ByteQueue();
+ private ByteQueue alertQueue = new ByteQueue(2);
private ByteQueue handshakeQueue = new ByteQueue();
/*
@@ -65,13 +65,24 @@ public abstract class TlsProtocol
private volatile boolean closed = false;
private volatile boolean failedWithError = false;
private volatile boolean appDataReady = false;
- private volatile boolean writeExtraEmptyRecords = true;
+ private volatile boolean splitApplicationDataRecords = true;
private byte[] expected_verify_data = null;
+ protected TlsSession tlsSession = null;
+ protected SessionParameters sessionParameters = null;
protected SecurityParameters securityParameters = null;
+ protected Certificate peerCertificate = null;
+
+ protected int[] offeredCipherSuites = null;
+ protected short[] offeredCompressionMethods = null;
+ protected Hashtable clientExtensions = null;
+ protected Hashtable serverExtensions = null;
protected short connection_state = CS_START;
+ protected boolean resumedSession = false;
+ protected boolean receivedChangeCipherSpec = false;
protected boolean secure_renegotiation = false;
+ protected boolean allowCertificateStatus = false;
protected boolean expectSessionTicket = false;
public TlsProtocol(InputStream input, OutputStream output, SecureRandom secureRandom)
@@ -84,8 +95,9 @@ public abstract class TlsProtocol
protected abstract TlsPeer getPeer();
- protected abstract void handleChangeCipherSpecMessage()
- throws IOException;
+ protected void handleChangeCipherSpecMessage() throws IOException
+ {
+ }
protected abstract void handleHandshakeMessage(short type, byte[] buf)
throws IOException;
@@ -93,37 +105,88 @@ public abstract class TlsProtocol
protected void handleWarningMessage(short description)
throws IOException
{
+ }
+
+ protected void cleanupHandshake()
+ {
+ if (this.expected_verify_data != null)
+ {
+ Arrays.fill(this.expected_verify_data, (byte)0);
+ this.expected_verify_data = null;
+ }
+
+ this.securityParameters.clear();
+ this.peerCertificate = null;
+ this.offeredCipherSuites = null;
+ this.offeredCompressionMethods = null;
+ this.clientExtensions = null;
+ this.serverExtensions = null;
+
+ this.resumedSession = false;
+ this.receivedChangeCipherSpec = false;
+ this.secure_renegotiation = false;
+ this.allowCertificateStatus = false;
+ this.expectSessionTicket = false;
}
protected void completeHandshake()
throws IOException
{
+ try
+ {
+ /*
+ * We will now read data, until we have completed the handshake.
+ */
+ while (this.connection_state != CS_END)
+ {
+ if (this.closed)
+ {
+ // TODO What kind of exception/alert?
+ }
- this.expected_verify_data = null;
+ safeReadRecord();
+ }
- /*
- * We will now read data, until we have completed the handshake.
- */
- while (this.connection_state != CS_SERVER_FINISHED)
- {
- safeReadRecord();
- }
+ this.recordStream.finaliseHandshake();
- this.recordStream.finaliseHandshake();
+ this.splitApplicationDataRecords = !TlsUtils.isTLSv11(getContext());
- ProtocolVersion version = getContext().getServerVersion();
- this.writeExtraEmptyRecords = version.isEqualOrEarlierVersionOf(ProtocolVersion.TLSv10);
+ /*
+ * If this was an initial handshake, we are now ready to send and receive application data.
+ */
+ if (!appDataReady)
+ {
+ this.appDataReady = true;
- /*
- * If this was an initial handshake, we are now ready to send and receive application data.
- */
- if (!appDataReady)
- {
- this.appDataReady = true;
+ this.tlsInputStream = new TlsInputStream(this);
+ this.tlsOutputStream = new TlsOutputStream(this);
+ }
- this.tlsInputStream = new TlsInputStream(this);
- this.tlsOutputStream = new TlsOutputStream(this);
+ if (this.tlsSession != null)
+ {
+ if (this.sessionParameters == null)
+ {
+ this.sessionParameters = new SessionParameters.Builder()
+ .setCipherSuite(this.securityParameters.cipherSuite)
+ .setCompressionAlgorithm(this.securityParameters.compressionAlgorithm)
+ .setMasterSecret(this.securityParameters.masterSecret)
+ .setPeerCertificate(this.peerCertificate)
+ // TODO Consider filtering extensions that aren't relevant to resumed sessions
+ .setServerExtensions(this.serverExtensions)
+ .build();
+
+ this.tlsSession = new TlsSessionImpl(this.tlsSession.getSessionID(), this.sessionParameters);
+ }
+
+ getContext().setResumableSession(this.tlsSession);
+ }
+
+ getPeer().notifyHandshakeComplete();
+ }
+ finally
+ {
+ cleanupHandshake();
}
}
@@ -135,26 +198,37 @@ public abstract class TlsProtocol
*/
switch (protocol)
{
- case ContentType.change_cipher_spec:
- changeCipherSpecQueue.addData(buf, offset, len);
- processChangeCipherSpec();
- break;
case ContentType.alert:
+ {
alertQueue.addData(buf, offset, len);
processAlert();
break;
- case ContentType.handshake:
- handshakeQueue.addData(buf, offset, len);
- processHandshake();
- break;
+ }
case ContentType.application_data:
+ {
if (!appDataReady)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
applicationDataQueue.addData(buf, offset, len);
processApplicationData();
break;
+ }
+ case ContentType.change_cipher_spec:
+ {
+ processChangeCipherSpec(buf, offset, len);
+ break;
+ }
+ case ContentType.handshake:
+ {
+ handshakeQueue.addData(buf, offset, len);
+ processHandshake();
+ break;
+ }
+ case ContentType.heartbeat:
+ {
+ // TODO[RFC 6520]
+ }
default:
/*
* Uh, we don't know this protocol.
@@ -190,9 +264,7 @@ public abstract class TlsProtocol
/*
* Read the message.
*/
- byte[] buf = new byte[len];
- handshakeQueue.read(buf, 0, len, 4);
- handshakeQueue.removeData(len + 4);
+ byte[] buf = handshakeQueue.removeData(len, 4);
/*
* RFC 2246 7.4.9. The value handshake_messages includes all handshake messages
@@ -205,7 +277,6 @@ public abstract class TlsProtocol
break;
case HandshakeType.finished:
{
-
if (this.expected_verify_data == null)
{
this.expected_verify_data = createVerifyData(!getContext().isServer());
@@ -247,9 +318,7 @@ public abstract class TlsProtocol
/*
* An alert is always 2 bytes. Read the alert.
*/
- byte[] tmp = new byte[2];
- alertQueue.read(tmp, 0, 2, 0);
- alertQueue.removeData(2);
+ byte[] tmp = alertQueue.removeData(2, 0);
short level = tmp[0];
short description = tmp[1];
@@ -257,20 +326,17 @@ public abstract class TlsProtocol
if (level == AlertLevel.fatal)
{
+ /*
+ * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated
+ * without proper close_notify messages with level equal to warning.
+ */
+ invalidateSession();
this.failedWithError = true;
this.closed = true;
- /*
- * Now try to close the stream, ignore errors.
- */
- try
- {
- recordStream.close();
- }
- catch (Exception e)
- {
- }
+ recordStream.safeClose();
+
throw new IOException(TLS_ERROR_MESSAGE);
}
else
@@ -300,27 +366,27 @@ public abstract class TlsProtocol
* @throws IOException If the message has an invalid content or the handshake is not in the correct
* state.
*/
- private void processChangeCipherSpec()
+ private void processChangeCipherSpec(byte[] buf, int off, int len)
throws IOException
{
- while (changeCipherSpecQueue.size() > 0)
+ for (int i = 0; i < len; ++i)
{
- /*
- * A change cipher spec message is only one byte with the value 1.
- */
- byte[] b = new byte[1];
- changeCipherSpecQueue.read(b, 0, 1, 0);
- changeCipherSpecQueue.removeData(1);
- if (b[0] != 1)
+ short message = TlsUtils.readUint8(buf, off + i);
+
+ if (message != ChangeCipherSpec.change_cipher_spec)
{
- /*
- * This should never happen.
- */
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.decode_error);
}
- recordStream.receivedReadCipherSpec();
+ if (this.receivedChangeCipherSpec)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ this.receivedChangeCipherSpec = true;
+
+ recordStream.receivedReadCipherSpec();
+
handleChangeCipherSpecMessage();
}
}
@@ -338,7 +404,6 @@ public abstract class TlsProtocol
protected int readApplicationData(byte[] buf, int offset, int len)
throws IOException
{
-
if (len < 1)
{
return 0;
@@ -367,9 +432,9 @@ public abstract class TlsProtocol
safeReadRecord();
}
+
len = Math.min(len, applicationDataQueue.size());
- applicationDataQueue.read(buf, offset, len, 0);
- applicationDataQueue.removeData(len);
+ applicationDataQueue.removeData(buf, offset, len, 0);
return len;
}
@@ -378,13 +443,18 @@ public abstract class TlsProtocol
{
try
{
- recordStream.readRecord();
+ if (!recordStream.readRecord())
+ {
+ // TODO It would be nicer to allow graceful connection close if between records
+// this.failWithError(AlertLevel.warning, AlertDescription.close_notify);
+ throw new EOFException();
+ }
}
catch (TlsFatalAlert e)
{
if (!this.closed)
{
- this.failWithError(AlertLevel.fatal, e.getAlertDescription());
+ this.failWithError(AlertLevel.fatal, e.getAlertDescription(), "Failed to read record", e);
}
throw e;
}
@@ -392,7 +462,7 @@ public abstract class TlsProtocol
{
if (!this.closed)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
}
throw e;
}
@@ -400,7 +470,7 @@ public abstract class TlsProtocol
{
if (!this.closed)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
}
throw e;
}
@@ -417,7 +487,7 @@ public abstract class TlsProtocol
{
if (!this.closed)
{
- this.failWithError(AlertLevel.fatal, e.getAlertDescription());
+ this.failWithError(AlertLevel.fatal, e.getAlertDescription(), "Failed to write record", e);
}
throw e;
}
@@ -425,7 +495,7 @@ public abstract class TlsProtocol
{
if (!closed)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e);
}
throw e;
}
@@ -433,7 +503,7 @@ public abstract class TlsProtocol
{
if (!closed)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e);
}
throw e;
}
@@ -467,25 +537,41 @@ public abstract class TlsProtocol
/*
* RFC 5246 6.2.1. Zero-length fragments of Application data MAY be sent as they are
* potentially useful as a traffic analysis countermeasure.
+ *
+ * NOTE: Actually, implementations appear to have settled on 1/n-1 record splitting.
*/
- if (this.writeExtraEmptyRecords)
+
+ if (this.splitApplicationDataRecords)
{
/*
* Protect against known IV attack!
*
- * DO NOT REMOVE THIS LINE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
+ * DO NOT REMOVE THIS CODE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
*/
- safeWriteRecord(ContentType.application_data, TlsUtils.EMPTY_BYTES, 0, 0);
+ safeWriteRecord(ContentType.application_data, buf, offset, 1);
+ ++offset;
+ --len;
}
- /*
- * We are only allowed to write fragments up to 2^14 bytes.
- */
- int toWrite = Math.min(len, 1 << 14);
-
- safeWriteRecord(ContentType.application_data, buf, offset, toWrite);
+ if (len > 0)
+ {
+ // Fragment data according to the current fragment limit.
+ int toWrite = Math.min(len, recordStream.getPlaintextLimit());
+ safeWriteRecord(ContentType.application_data, buf, offset, toWrite);
+ offset += toWrite;
+ len -= toWrite;
+ }
+ }
+ }
- offset += toWrite;
+ protected void writeHandshakeMessage(byte[] buf, int off, int len) throws IOException
+ {
+ while (len > 0)
+ {
+ // Fragment data according to the current fragment limit.
+ int toWrite = Math.min(len, recordStream.getPlaintextLimit());
+ safeWriteRecord(ContentType.handshake, buf, off, toWrite);
+ off += toWrite;
len -= toWrite;
}
}
@@ -507,15 +593,16 @@ public abstract class TlsProtocol
}
/**
- * Terminate this connection with an alert.
- * <p/>
- * Can be used for normal closure too.
- *
- * @param alertLevel The level of the alert, an be AlertLevel.fatal or AL_warning.
- * @param alertDescription The exact alert message.
- * @throws IOException If alert was fatal.
+ * Terminate this connection with an alert. Can be used for normal closure too.
+ *
+ * @param alertLevel
+ * See {@link AlertLevel} for values.
+ * @param alertDescription
+ * See {@link AlertDescription} for values.
+ * @throws IOException
+ * If alert was fatal.
*/
- protected void failWithError(short alertLevel, short alertDescription)
+ protected void failWithError(short alertLevel, short alertDescription, String message, Exception cause)
throws IOException
{
/*
@@ -531,27 +618,43 @@ public abstract class TlsProtocol
if (alertLevel == AlertLevel.fatal)
{
/*
- * This is a fatal message.
+ * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated
+ * without proper close_notify messages with level equal to warning.
*/
+ // TODO This isn't quite in the right place. Also, as of TLS 1.1 the above is obsolete.
+ invalidateSession();
+
this.failedWithError = true;
}
- raiseAlert(alertLevel, alertDescription, null, null);
- recordStream.close();
- if (alertLevel == AlertLevel.fatal)
+ raiseAlert(alertLevel, alertDescription, message, cause);
+ recordStream.safeClose();
+ if (alertLevel != AlertLevel.fatal)
{
- throw new IOException(TLS_ERROR_MESSAGE);
+ return;
}
}
- else
+
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+
+ protected void invalidateSession()
+ {
+ if (this.sessionParameters != null)
{
- throw new IOException(TLS_ERROR_MESSAGE);
+ this.sessionParameters.clear();
+ this.sessionParameters = null;
+ }
+
+ if (this.tlsSession != null)
+ {
+ this.tlsSession.invalidate();
+ this.tlsSession = null;
}
}
protected void processFinishedMessage(ByteArrayInputStream buf)
throws IOException
{
-
byte[] verify_data = TlsUtils.readFully(expected_verify_data.length, buf);
assertEmpty(buf);
@@ -564,14 +667,13 @@ public abstract class TlsProtocol
/*
* Wrong checksum in the finished message.
*/
- this.failWithError(AlertLevel.fatal, AlertDescription.decrypt_error);
+ throw new TlsFatalAlert(AlertDescription.decrypt_error);
}
}
protected void raiseAlert(short alertLevel, short alertDescription, String message, Exception cause)
throws IOException
{
-
getPeer().notifyAlertRaised(alertLevel, alertDescription, message, cause);
byte[] error = new byte[2];
@@ -590,7 +692,6 @@ public abstract class TlsProtocol
protected void sendCertificateMessage(Certificate certificate)
throws IOException
{
-
if (certificate == null)
{
certificate = Certificate.EMPTY_CHAIN;
@@ -611,25 +712,17 @@ public abstract class TlsProtocol
}
}
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- TlsUtils.writeUint8(HandshakeType.certificate, bos);
-
- // Reserve space for length
- TlsUtils.writeUint24(0, bos);
-
- certificate.encode(bos);
- byte[] message = bos.toByteArray();
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate);
- // Patch actual length back in
- TlsUtils.writeUint24(message.length - 4, message, 1);
+ certificate.encode(message);
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.writeToRecordStream();
}
protected void sendChangeCipherSpecMessage()
throws IOException
{
- byte[] message = new byte[]{1};
+ byte[] message = new byte[]{ 1 };
safeWriteRecord(ContentType.change_cipher_spec, message, 0, message.length);
recordStream.sentWriteCipherSpec();
}
@@ -639,33 +732,21 @@ public abstract class TlsProtocol
{
byte[] verify_data = createVerifyData(getContext().isServer());
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- TlsUtils.writeUint8(HandshakeType.finished, bos);
- TlsUtils.writeUint24(verify_data.length, bos);
- bos.write(verify_data);
- byte[] message = bos.toByteArray();
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.finished, verify_data.length);
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.write(verify_data);
+
+ message.writeToRecordStream();
}
protected void sendSupplementalDataMessage(Vector supplementalData)
throws IOException
{
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.supplemental_data);
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeUint8(HandshakeType.supplemental_data, buf);
-
- // Reserve space for length
- TlsUtils.writeUint24(0, buf);
+ writeSupplementalData(message, supplementalData);
- writeSupplementalData(buf, supplementalData);
-
- byte[] message = buf.toByteArray();
-
- // Patch actual length back in
- TlsUtils.writeUint24(message.length - 4, message, 1);
-
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.writeToRecordStream();
}
protected byte[] createVerifyData(boolean isServer)
@@ -674,12 +755,12 @@ public abstract class TlsProtocol
if (isServer)
{
- return TlsUtils.calculateVerifyData(context, "server finished",
- recordStream.getCurrentHash(TlsUtils.SSL_SERVER));
+ return TlsUtils.calculateVerifyData(context, ExporterLabel.server_finished,
+ getCurrentPRFHash(getContext(), recordStream.getHandshakeHash(), TlsUtils.SSL_SERVER));
}
- return TlsUtils.calculateVerifyData(context, "client finished",
- recordStream.getCurrentHash(TlsUtils.SSL_CLIENT));
+ return TlsUtils.calculateVerifyData(context, ExporterLabel.client_finished,
+ getCurrentPRFHash(getContext(), recordStream.getHandshakeHash(), TlsUtils.SSL_CLIENT));
}
/**
@@ -702,7 +783,7 @@ public abstract class TlsProtocol
{
raiseWarning(AlertDescription.user_canceled, "User canceled handshake");
}
- this.failWithError(AlertLevel.warning, AlertDescription.close_notify);
+ this.failWithError(AlertLevel.warning, AlertDescription.close_notify, "Connection closed", null);
}
}
@@ -712,28 +793,18 @@ public abstract class TlsProtocol
recordStream.flush();
}
- protected static boolean arrayContains(short[] a, short n)
- {
- for (int i = 0; i < a.length; ++i)
- {
- if (a[i] == n)
- {
- return true;
- }
- }
- return false;
- }
-
- protected static boolean arrayContains(int[] a, int n)
+ protected short processMaxFragmentLengthExtension(Hashtable clientExtensions, Hashtable serverExtensions, short alertDescription)
+ throws IOException
{
- for (int i = 0; i < a.length; ++i)
+ short maxFragmentLength = TlsExtensionsUtils.getMaxFragmentLengthExtension(serverExtensions);
+ if (maxFragmentLength >= 0 && !this.resumedSession)
{
- if (a[i] == n)
+ if (maxFragmentLength != TlsExtensionsUtils.getMaxFragmentLengthExtension(clientExtensions))
{
- return true;
+ throw new TlsFatalAlert(alertDescription);
}
}
- return false;
+ return maxFragmentLength;
}
/**
@@ -753,25 +824,28 @@ public abstract class TlsProtocol
protected static byte[] createRandomBlock(SecureRandom random)
{
+ random.setSeed(System.currentTimeMillis());
+
byte[] result = new byte[32];
random.nextBytes(result);
- TlsUtils.writeGMTUnixTime(result, 0);
+ /*
+ * The consensus seems to be that using the time here is neither all that useful, nor
+ * secure. Perhaps there could be an option to (re-)enable it. Instead, we seed the random
+ * source with the current time to retain it's main benefit.
+ */
+// TlsUtils.writeGMTUnixTime(result, 0);
return result;
}
protected static byte[] createRenegotiationInfo(byte[] renegotiated_connection)
throws IOException
{
-
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeOpaque8(renegotiated_connection, buf);
- return buf.toByteArray();
+ return TlsUtils.encodeOpaque8(renegotiated_connection);
}
protected static void establishMasterSecret(TlsContext context, TlsKeyExchange keyExchange)
throws IOException
{
-
byte[] pre_master_secret = keyExchange.generatePremasterSecret();
try
@@ -792,10 +866,26 @@ public abstract class TlsProtocol
}
}
+ /**
+ * 'sender' only relevant to SSLv3
+ */
+ protected static byte[] getCurrentPRFHash(TlsContext context, TlsHandshakeHash handshakeHash, byte[] sslSender)
+ {
+ Digest d = handshakeHash.forkPRFHash();
+
+ if (sslSender != null && TlsUtils.isSSL(context))
+ {
+ d.update(sslSender, 0, sslSender.length);
+ }
+
+ byte[] bs = new byte[d.getDigestSize()];
+ d.doFinal(bs, 0);
+ return bs;
+ }
+
protected static Hashtable readExtensions(ByteArrayInputStream input)
throws IOException
{
-
if (input.available() < 1)
{
return null;
@@ -812,13 +902,13 @@ public abstract class TlsProtocol
while (buf.available() > 0)
{
- Integer extType = Integers.valueOf(TlsUtils.readUint16(buf));
- byte[] extValue = TlsUtils.readOpaque16(buf);
+ Integer extension_type = Integers.valueOf(TlsUtils.readUint16(buf));
+ byte[] extension_data = TlsUtils.readOpaque16(buf);
/*
* RFC 3546 2.3 There MUST NOT be more than one extension of the same type.
*/
- if (null != extensions.put(extType, extValue))
+ if (null != extensions.put(extension_type, extension_data))
{
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
@@ -830,7 +920,6 @@ public abstract class TlsProtocol
protected static Vector readSupplementalDataMessage(ByteArrayInputStream input)
throws IOException
{
-
byte[] supp_data = TlsUtils.readOpaque24(input);
assertEmpty(input);
@@ -853,17 +942,18 @@ public abstract class TlsProtocol
protected static void writeExtensions(OutputStream output, Hashtable extensions)
throws IOException
{
-
ByteArrayOutputStream buf = new ByteArrayOutputStream();
Enumeration keys = extensions.keys();
while (keys.hasMoreElements())
{
- Integer extType = (Integer)keys.nextElement();
- byte[] extValue = (byte[])extensions.get(extType);
+ Integer key = (Integer)keys.nextElement();
+ int extension_type = key.intValue();
+ byte[] extension_data = (byte[])extensions.get(key);
- TlsUtils.writeUint16(extType.intValue(), buf);
- TlsUtils.writeOpaque16(extValue, buf);
+ TlsUtils.checkUint16(extension_type);
+ TlsUtils.writeUint16(extension_type, buf);
+ TlsUtils.writeOpaque16(extension_data, buf);
}
byte[] extBytes = buf.toByteArray();
@@ -874,14 +964,15 @@ public abstract class TlsProtocol
protected static void writeSupplementalData(OutputStream output, Vector supplementalData)
throws IOException
{
-
ByteArrayOutputStream buf = new ByteArrayOutputStream();
for (int i = 0; i < supplementalData.size(); ++i)
{
SupplementalDataEntry entry = (SupplementalDataEntry)supplementalData.elementAt(i);
- TlsUtils.writeUint16(entry.getDataType(), buf);
+ int supp_data_type = entry.getDataType();
+ TlsUtils.checkUint16(supp_data_type);
+ TlsUtils.writeUint16(supp_data_type, buf);
TlsUtils.writeOpaque16(entry.getData(), buf);
}
@@ -890,54 +981,137 @@ public abstract class TlsProtocol
TlsUtils.writeOpaque24(supp_data, output);
}
- protected static int getPRFAlgorithm(int ciphersuite)
+ protected static int getPRFAlgorithm(TlsContext context, int ciphersuite) throws IOException
{
+ boolean isTLSv12 = TlsUtils.isTLSv12(context);
switch (ciphersuite)
{
case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
- case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
- case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
- return PRFAlgorithm.tls_prf_sha256;
+ {
+ if (isTLSv12)
+ {
+ return PRFAlgorithm.tls_prf_sha256;
+ }
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
- case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
- case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
- return PRFAlgorithm.tls_prf_sha384;
+ {
+ if (isTLSv12)
+ {
+ return PRFAlgorithm.tls_prf_sha384;
+ }
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+ {
+ if (isTLSv12)
+ {
+ return PRFAlgorithm.tls_prf_sha384;
+ }
+ return PRFAlgorithm.tls_prf_legacy;
+ }
default:
+ {
+ if (isTLSv12)
+ {
+ return PRFAlgorithm.tls_prf_sha256;
+ }
return PRFAlgorithm.tls_prf_legacy;
}
+ }
+ }
+
+ class HandshakeMessage extends ByteArrayOutputStream
+ {
+ HandshakeMessage(short handshakeType) throws IOException
+ {
+ this(handshakeType, 60);
+ }
+
+ HandshakeMessage(short handshakeType, int length) throws IOException
+ {
+ super(length + 4);
+ TlsUtils.writeUint8(handshakeType, this);
+ // Reserve space for length
+ count += 3;
+ }
+
+ void writeToRecordStream() throws IOException
+ {
+ // Patch actual length back in
+ int length = count - 4;
+ TlsUtils.checkUint24(length);
+ TlsUtils.writeUint24(length, buf, 1);
+ writeHandshakeMessage(buf, 0, count);
+ buf = null;
+ }
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java
index 24eec53..8970968 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java
@@ -40,7 +40,6 @@ public class TlsRSAKeyExchange
public void processServerCredentials(TlsCredentials serverCredentials)
throws IOException
{
-
if (!(serverCredentials instanceof TlsEncryptionCredentials))
{
throw new TlsFatalAlert(AlertDescription.internal_error);
@@ -54,7 +53,6 @@ public class TlsRSAKeyExchange
public void processServerCertificate(Certificate serverCertificate)
throws IOException
{
-
if (serverCertificate.isEmpty())
{
throw new TlsFatalAlert(AlertDescription.bad_certificate);
@@ -115,15 +113,14 @@ public class TlsRSAKeyExchange
public void generateClientKeyExchange(OutputStream output)
throws IOException
{
- this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context, this.rsaServerPublicKey, output);
+ this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context, rsaServerPublicKey, output);
}
public void processClientKeyExchange(InputStream input)
throws IOException
{
-
byte[] encryptedPreMasterSecret;
- if (context.getServerVersion().isSSL())
+ if (TlsUtils.isSSL(context))
{
// TODO Do any SSLv3 clients actually include the length?
encryptedPreMasterSecret = Streams.readAll(input);
@@ -133,68 +130,7 @@ public class TlsRSAKeyExchange
encryptedPreMasterSecret = TlsUtils.readOpaque16(input);
}
- ProtocolVersion clientVersion = context.getClientVersion();
-
- /*
- * RFC 5246 7.4.7.1.
- */
- {
- // TODO Provide as configuration option?
- boolean versionNumberCheckDisabled = false;
-
- /*
- * See notes regarding Bleichenbacher/Klima attack. The code here implements the first
- * construction proposed there, which is RECOMMENDED.
- */
- byte[] R = new byte[48];
- this.context.getSecureRandom().nextBytes(R);
-
- byte[] M = TlsUtils.EMPTY_BYTES;
- try
- {
- M = serverCredentials.decryptPreMasterSecret(encryptedPreMasterSecret);
- }
- catch (Exception e)
- {
- /*
- * In any case, a TLS server MUST NOT generate an alert if processing an
- * RSA-encrypted premaster secret message fails, or the version number is not as
- * expected. Instead, it MUST continue the handshake with a randomly generated
- * premaster secret.
- */
- }
-
- if (M.length != 48)
- {
- TlsUtils.writeVersion(clientVersion, R, 0);
- this.premasterSecret = R;
- }
- else
- {
- /*
- * If ClientHello.client_version is TLS 1.1 or higher, server implementations MUST
- * check the version number [..].
- */
- if (versionNumberCheckDisabled && clientVersion.isEqualOrEarlierVersionOf(ProtocolVersion.TLSv10))
- {
- /*
- * If the version number is TLS 1.0 or earlier, server implementations SHOULD
- * check the version number, but MAY have a configuration option to disable the
- * check.
- */
- }
- else
- {
- /*
- * Note that explicitly constructing the pre_master_secret with the
- * ClientHello.client_version produces an invalid master_secret if the client
- * has sent the wrong version in the original pre_master_secret.
- */
- TlsUtils.writeVersion(clientVersion, M, 0);
- }
- this.premasterSecret = M;
- }
- }
+ this.premasterSecret = TlsRSAUtils.safeDecryptPreMasterSecret(context, serverCredentials, encryptedPreMasterSecret);
}
public byte[] generatePremasterSecret()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSASigner.java
index d9f7975..35538a7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSASigner.java
@@ -5,6 +5,7 @@ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Signer;
+import org.bouncycastle.crypto.digests.NullDigest;
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
import org.bouncycastle.crypto.engines.RSABlindedEngine;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
@@ -12,40 +13,37 @@ import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.signers.GenericSigner;
import org.bouncycastle.crypto.signers.RSADigestSigner;
-import org.bouncycastle.util.Arrays;
public class TlsRSASigner
extends AbstractTlsSigner
{
-
- public byte[] generateRawSignature(AsymmetricKeyParameter privateKey, byte[] md5AndSha1)
+ public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm,
+ AsymmetricKeyParameter privateKey, byte[] hash)
throws CryptoException
{
-
- AsymmetricBlockCipher engine = createRSAImpl();
- engine.init(true, new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
- return engine.processBlock(md5AndSha1, 0, md5AndSha1.length);
+ Signer signer = makeSigner(algorithm, true, true,
+ new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
+ signer.update(hash, 0, hash.length);
+ return signer.generateSignature();
}
- public boolean verifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5AndSha1)
+ public boolean verifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+ AsymmetricKeyParameter publicKey, byte[] hash)
throws CryptoException
{
-
- AsymmetricBlockCipher engine = createRSAImpl();
- engine.init(false, publicKey);
- byte[] signed = engine.processBlock(sigBytes, 0, sigBytes.length);
- return Arrays.constantTimeAreEqual(signed, md5AndSha1);
+ Signer signer = makeSigner(algorithm, true, false, publicKey);
+ signer.update(hash, 0, hash.length);
+ return signer.verifySignature(sigBytes);
}
- public Signer createSigner(AsymmetricKeyParameter privateKey)
+ public Signer createSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
{
- return makeSigner(new CombinedHash(), true,
- new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
+ return makeSigner(algorithm, false, true, new ParametersWithRandom(privateKey, this.context.getSecureRandom()));
}
- public Signer createVerifyer(AsymmetricKeyParameter publicKey)
+ public Signer createVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
{
- return makeSigner(new CombinedHash(), false, publicKey);
+ return makeSigner(algorithm, false, false, publicKey);
}
public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
@@ -53,16 +51,41 @@ public class TlsRSASigner
return publicKey instanceof RSAKeyParameters && !publicKey.isPrivate();
}
- protected Signer makeSigner(Digest d, boolean forSigning, CipherParameters cp)
+ protected Signer makeSigner(SignatureAndHashAlgorithm algorithm, boolean raw, boolean forSigning,
+ CipherParameters cp)
{
+ if ((algorithm != null) != TlsUtils.isTLSv12(context))
+ {
+ throw new IllegalStateException();
+ }
+
+ if (algorithm != null && algorithm.getSignature() != SignatureAlgorithm.rsa)
+ {
+ throw new IllegalStateException();
+ }
+
+ Digest d;
+ if (raw)
+ {
+ d = new NullDigest();
+ }
+ else if (algorithm == null)
+ {
+ d = new CombinedHash();
+ }
+ else
+ {
+ d = TlsUtils.createHash(algorithm.getHash());
+ }
+
Signer s;
- if (ProtocolVersion.TLSv12.isEqualOrEarlierVersionOf(context.getServerVersion().getEquivalentTLSVersion()))
+ if (algorithm != null)
{
/*
* RFC 5246 4.7. In RSA signing, the opaque vector contains the signature generated
* using the RSASSA-PKCS1-v1_5 signature scheme defined in [PKCS1].
*/
- s = new RSADigestSigner(d);
+ s = new RSADigestSigner(d, TlsUtils.getOIDForHashAlgorithm(algorithm.getHash()));
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAUtils.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAUtils.java
index f67e572..e3856bd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAUtils.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsRSAUtils.java
@@ -12,8 +12,7 @@ import org.bouncycastle.crypto.params.RSAKeyParameters;
public class TlsRSAUtils
{
public static byte[] generateEncryptedPreMasterSecret(TlsContext context, RSAKeyParameters rsaServerPublicKey,
- OutputStream output)
- throws IOException
+ OutputStream output) throws IOException
{
/*
* Choose a PremasterSecret and send it encrypted to the server
@@ -29,7 +28,7 @@ public class TlsRSAUtils
{
byte[] encryptedPreMasterSecret = encoding.processBlock(premasterSecret, 0, premasterSecret.length);
- if (context.getServerVersion().isSSL())
+ if (TlsUtils.isSSL(context))
{
// TODO Do any SSLv3 servers actually expect the length?
output.write(encryptedPreMasterSecret);
@@ -49,4 +48,69 @@ public class TlsRSAUtils
return premasterSecret;
}
+
+ public static byte[] safeDecryptPreMasterSecret(TlsContext context, TlsEncryptionCredentials encryptionCredentials,
+ byte[] encryptedPreMasterSecret)
+ {
+ /*
+ * RFC 5246 7.4.7.1.
+ */
+
+ ProtocolVersion clientVersion = context.getClientVersion();
+
+ // TODO Provide as configuration option?
+ boolean versionNumberCheckDisabled = false;
+
+ /*
+ * See notes regarding Bleichenbacher/Klima attack. The code here implements the first
+ * construction proposed there, which is RECOMMENDED.
+ */
+ byte[] R = new byte[48];
+ context.getSecureRandom().nextBytes(R);
+
+ byte[] M = TlsUtils.EMPTY_BYTES;
+ try
+ {
+ M = encryptionCredentials.decryptPreMasterSecret(encryptedPreMasterSecret);
+ }
+ catch (Exception e)
+ {
+ /*
+ * In any case, a TLS server MUST NOT generate an alert if processing an
+ * RSA-encrypted premaster secret message fails, or the version number is not as
+ * expected. Instead, it MUST continue the handshake with a randomly generated
+ * premaster secret.
+ */
+ }
+
+ if (M.length != 48)
+ {
+ TlsUtils.writeVersion(clientVersion, R, 0);
+ return R;
+ }
+
+ /*
+ * If ClientHello.client_version is TLS 1.1 or higher, server implementations MUST
+ * check the version number [..].
+ */
+ if (versionNumberCheckDisabled && clientVersion.isEqualOrEarlierVersionOf(ProtocolVersion.TLSv10))
+ {
+ /*
+ * If the version number is TLS 1.0 or earlier, server implementations SHOULD
+ * check the version number, but MAY have a configuration option to disable the
+ * check.
+ */
+ }
+ else
+ {
+ /*
+ * Note that explicitly constructing the pre_master_secret with the
+ * ClientHello.client_version produces an invalid master_secret if the client
+ * has sent the wrong version in the original pre_master_secret.
+ */
+ TlsUtils.writeVersion(clientVersion, M, 0);
+ }
+
+ return M;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java
index b928b91..452fbf9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java
@@ -13,18 +13,16 @@ import org.bouncycastle.crypto.Signer;
import org.bouncycastle.crypto.agreement.srp.SRP6Client;
import org.bouncycastle.crypto.agreement.srp.SRP6Util;
import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.io.SignerInputStream;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.util.BigIntegers;
+import org.bouncycastle.util.io.TeeInputStream;
/**
* TLS 1.1 SRP key exchange (RFC 5054).
*/
-public class TlsSRPKeyExchange
- extends AbstractTlsKeyExchange
+public class TlsSRPKeyExchange extends AbstractTlsKeyExchange
{
-
protected TlsSigner tlsSigner;
protected byte[] identity;
protected byte[] password;
@@ -37,7 +35,6 @@ public class TlsSRPKeyExchange
public TlsSRPKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms, byte[] identity, byte[] password)
{
-
super(keyExchange, supportedSignatureAlgorithms);
switch (keyExchange)
@@ -64,14 +61,12 @@ public class TlsSRPKeyExchange
{
super.init(context);
- if (this.tlsSigner != null)
- {
+ if (this.tlsSigner != null) {
this.tlsSigner.init(context);
}
}
- public void skipServerCredentials()
- throws IOException
+ public void skipServerCredentials() throws IOException
{
if (tlsSigner != null)
{
@@ -79,10 +74,8 @@ public class TlsSRPKeyExchange
}
}
- public void processServerCertificate(Certificate serverCertificate)
- throws IOException
+ public void processServerCertificate(Certificate serverCertificate) throws IOException
{
-
if (tlsSigner == null)
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
@@ -119,31 +112,31 @@ public class TlsSRPKeyExchange
return true;
}
- public void processServerKeyExchange(InputStream input)
- throws IOException
+ public void processServerKeyExchange(InputStream input) throws IOException
{
-
SecurityParameters securityParameters = context.getSecurityParameters();
- InputStream sigIn = input;
- Signer signer = null;
+ SignerInputBuffer buf = null;
+ InputStream teeIn = input;
if (tlsSigner != null)
{
- signer = initVerifyer(tlsSigner, securityParameters);
- sigIn = new SignerInputStream(input, signer);
+ buf = new SignerInputBuffer();
+ teeIn = new TeeInputStream(input, buf);
}
- byte[] NBytes = TlsUtils.readOpaque16(sigIn);
- byte[] gBytes = TlsUtils.readOpaque16(sigIn);
- byte[] sBytes = TlsUtils.readOpaque8(sigIn);
- byte[] BBytes = TlsUtils.readOpaque16(sigIn);
+ byte[] NBytes = TlsUtils.readOpaque16(teeIn);
+ byte[] gBytes = TlsUtils.readOpaque16(teeIn);
+ byte[] sBytes = TlsUtils.readOpaque8(teeIn);
+ byte[] BBytes = TlsUtils.readOpaque16(teeIn);
- if (signer != null)
+ if (buf != null)
{
- byte[] sigByte = TlsUtils.readOpaque16(input);
+ DigitallySigned signed_params = DigitallySigned.parse(context, input);
- if (!signer.verifySignature(sigByte))
+ Signer signer = initVerifyer(tlsSigner, signed_params.getAlgorithm(), securityParameters);
+ buf.updateSigner(signer);
+ if (!signer.verifySignature(signed_params.getSignature()))
{
throw new TlsFatalAlert(AlertDescription.decrypt_error);
}
@@ -153,7 +146,7 @@ public class TlsSRPKeyExchange
BigInteger g = new BigInteger(1, gBytes);
// TODO Validate group parameters (see RFC 5054)
- // handler.failWithError(AlertLevel.fatal, AlertDescription.insufficient_security);
+// throw new TlsFatalAlert(AlertDescription.insufficient_security);
this.s = sBytes;
@@ -173,28 +166,23 @@ public class TlsSRPKeyExchange
this.srpClient.init(N, g, new SHA1Digest(), context.getSecureRandom());
}
- public void validateCertificateRequest(CertificateRequest certificateRequest)
- throws IOException
+ public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- public void processClientCredentials(TlsCredentials clientCredentials)
- throws IOException
+ public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
- public void generateClientKeyExchange(OutputStream output)
- throws IOException
+ public void generateClientKeyExchange(OutputStream output) throws IOException
{
- byte[] keData = BigIntegers.asUnsignedByteArray(srpClient.generateClientCredentials(s, this.identity,
- this.password));
- TlsUtils.writeOpaque16(keData, output);
+ BigInteger A = srpClient.generateClientCredentials(s, this.identity, this.password);
+ TlsUtils.writeOpaque16(BigIntegers.asUnsignedByteArray(A), output);
}
- public byte[] generatePremasterSecret()
- throws IOException
+ public byte[] generatePremasterSecret() throws IOException
{
try
{
@@ -207,9 +195,9 @@ public class TlsSRPKeyExchange
}
}
- protected Signer initVerifyer(TlsSigner tlsSigner, SecurityParameters securityParameters)
+ protected Signer initVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, SecurityParameters securityParameters)
{
- Signer signer = tlsSigner.createVerifyer(this.serverPublicKey);
+ Signer signer = tlsSigner.createVerifyer(algorithm, this.serverPublicKey);
signer.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
signer.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
return signer;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRPUtils.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRPUtils.java
new file mode 100644
index 0000000..7fe5fb8
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRPUtils.java
@@ -0,0 +1,49 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.bouncycastle.util.Integers;
+
+public class TlsSRPUtils
+{
+ public static final Integer EXT_SRP = Integers.valueOf(ExtensionType.srp);
+
+ public static void addSRPExtension(Hashtable extensions, byte[] identity) throws IOException
+ {
+ extensions.put(EXT_SRP, createSRPExtension(identity));
+ }
+
+ public static byte[] getSRPExtension(Hashtable extensions) throws IOException
+ {
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_SRP);
+ return extensionData == null ? null : readSRPExtension(extensionData);
+ }
+
+ public static byte[] createSRPExtension(byte[] identity) throws IOException
+ {
+ if (identity == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ return TlsUtils.encodeOpaque8(identity);
+ }
+
+ public static byte[] readSRPExtension(byte[] extensionData) throws IOException
+ {
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
+ byte[] identity = TlsUtils.readOpaque8(buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ return identity;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRTPUtils.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRTPUtils.java
index f82f94d..da98b7a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRTPUtils.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSRTPUtils.java
@@ -12,36 +12,24 @@ import org.bouncycastle.util.Integers;
*/
public class TlsSRTPUtils
{
-
public static final Integer EXT_use_srtp = Integers.valueOf(ExtensionType.use_srtp);
public static void addUseSRTPExtension(Hashtable extensions, UseSRTPData useSRTPData)
throws IOException
{
-
extensions.put(EXT_use_srtp, createUseSRTPExtension(useSRTPData));
}
public static UseSRTPData getUseSRTPExtension(Hashtable extensions)
throws IOException
{
-
- if (extensions == null)
- {
- return null;
- }
- byte[] extensionValue = (byte[])extensions.get(EXT_use_srtp);
- if (extensionValue == null)
- {
- return null;
- }
- return readUseSRTPExtension(extensionValue);
+ byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_use_srtp);
+ return extensionData == null ? null : readUseSRTPExtension(extensionData);
}
public static byte[] createUseSRTPExtension(UseSRTPData useSRTPData)
throws IOException
{
-
if (useSRTPData == null)
{
throw new IllegalArgumentException("'useSRTPData' cannot be null");
@@ -50,9 +38,7 @@ public class TlsSRTPUtils
ByteArrayOutputStream buf = new ByteArrayOutputStream();
// SRTPProtectionProfiles
- int[] protectionProfiles = useSRTPData.getProtectionProfiles();
- TlsUtils.writeUint16(2 * protectionProfiles.length, buf);
- TlsUtils.writeUint16Array(protectionProfiles, buf);
+ TlsUtils.writeUint16ArrayWithUint16Length(useSRTPData.getProtectionProfiles(), buf);
// srtp_mki
TlsUtils.writeOpaque8(useSRTPData.getMki(), buf);
@@ -60,16 +46,15 @@ public class TlsSRTPUtils
return buf.toByteArray();
}
- public static UseSRTPData readUseSRTPExtension(byte[] extensionValue)
+ public static UseSRTPData readUseSRTPExtension(byte[] extensionData)
throws IOException
{
-
- if (extensionValue == null)
+ if (extensionData == null)
{
- throw new IllegalArgumentException("'extensionValue' cannot be null");
+ throw new IllegalArgumentException("'extensionData' cannot be null");
}
- ByteArrayInputStream buf = new ByteArrayInputStream(extensionValue);
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
// SRTPProtectionProfiles
int length = TlsUtils.readUint16(buf);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServer.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServer.java
index 0b46391..85c0a9a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServer.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServer.java
@@ -7,11 +7,9 @@ import java.util.Vector;
public interface TlsServer
extends TlsPeer
{
-
void init(TlsServerContext context);
- void notifyClientVersion(ProtocolVersion clientVersion)
- throws IOException;
+ void notifyClientVersion(ProtocolVersion clientVersion) throws IOException;
void notifyOfferedCipherSuites(int[] offeredCipherSuites)
throws IOException;
@@ -19,9 +17,6 @@ public interface TlsServer
void notifyOfferedCompressionMethods(short[] offeredCompressionMethods)
throws IOException;
- void notifySecureRenegotiation(boolean secureNegotiation)
- throws IOException;
-
// Hashtable is (Integer -> byte[])
void processClientExtensions(Hashtable clientExtensions)
throws IOException;
@@ -46,32 +41,41 @@ public interface TlsServer
TlsCredentials getCredentials()
throws IOException;
+ /**
+ * This method will be called (only) if the server included an extension of type
+ * "status_request" with empty "extension_data" in the extended server hello. See <i>RFC 3546
+ * 3.6. Certificate Status Request</i>. If a non-null {@link CertificateStatus} is returned, it
+ * is sent to the client as a handshake message of type "certificate_status".
+ *
+ * @return A {@link CertificateStatus} to be sent to the client (or null for none).
+ * @throws IOException
+ */
+ CertificateStatus getCertificateStatus()
+ throws IOException;
+
TlsKeyExchange getKeyExchange()
throws IOException;
- CertificateRequest getCertificateRequest();
+ CertificateRequest getCertificateRequest()
+ throws IOException;
// Vector is (SupplementalDataEntry)
void processClientSupplementalData(Vector clientSupplementalData)
throws IOException;
/**
- * Called by the protocol handler to report the client certificate, only if a Certificate
- * {@link #getCertificateRequest()} returned non-null. Note: this method is responsible for
- * certificate verification and validation.
- *
- * @param clientCertificate the effective client certificate (may be an empty chain).
+ * Called by the protocol handler to report the client certificate, only if
+ * {@link #getCertificateRequest()} returned non-null.
+ *
+ * Note: this method is responsible for certificate verification and validation.
+ *
+ * @param clientCertificate
+ * the effective client certificate (may be an empty chain).
* @throws IOException
*/
void notifyClientCertificate(Certificate clientCertificate)
throws IOException;
- TlsCompression getCompression()
- throws IOException;
-
- TlsCipher getCipher()
- throws IOException;
-
/**
* RFC 5077 3.3. NewSessionTicket Handshake Message.
* <p/>
@@ -83,7 +87,4 @@ public interface TlsServer
*/
NewSessionTicket getNewSessionTicket()
throws IOException;
-
- void notifyHandshakeComplete()
- throws IOException;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerContextImpl.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerContextImpl.java
index 2fa4029..48f028a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerContextImpl.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerContextImpl.java
@@ -6,7 +6,6 @@ class TlsServerContextImpl
extends AbstractTlsContext
implements TlsServerContext
{
-
TlsServerContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
{
super(secureRandom, securityParameters);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerProtocol.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerProtocol.java
index 961669f..056d22a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerProtocol.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsServerProtocol.java
@@ -1,12 +1,10 @@
package org.bouncycastle.crypto.tls;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.SecureRandom;
-import java.util.Hashtable;
import java.util.Vector;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
@@ -17,25 +15,15 @@ import org.bouncycastle.util.Arrays;
public class TlsServerProtocol
extends TlsProtocol
{
-
protected TlsServer tlsServer = null;
protected TlsServerContextImpl tlsServerContext = null;
- protected int[] offeredCipherSuites;
- protected short[] offeredCompressionMethods;
- protected Hashtable clientExtensions;
-
- protected int selectedCipherSuite;
- protected short selectedCompressionMethod;
- protected Hashtable serverExtensions;
-
protected TlsKeyExchange keyExchange = null;
protected TlsCredentials serverCredentials = null;
protected CertificateRequest certificateRequest = null;
protected short clientCertificateType = -1;
- protected Certificate clientCertificate = null;
- protected byte[] certificateVerifyHash = null;
+ protected TlsHandshakeHash prepareFinishHash = null;
public TlsServerProtocol(InputStream input, OutputStream output, SecureRandom secureRandom)
{
@@ -51,14 +39,13 @@ public class TlsServerProtocol
public void accept(TlsServer tlsServer)
throws IOException
{
-
if (tlsServer == null)
{
throw new IllegalArgumentException("'tlsServer' cannot be null");
}
if (this.tlsServer != null)
{
- throw new IllegalStateException("accept can only be called once");
+ throw new IllegalStateException("'accept' can only be called once");
}
this.tlsServer = tlsServer;
@@ -74,8 +61,16 @@ public class TlsServerProtocol
this.recordStream.setRestrictReadVersion(false);
completeHandshake();
+ }
- this.tlsServer.notifyHandshakeComplete();
+ protected void cleanupHandshake()
+ {
+ super.cleanupHandshake();
+
+ this.keyExchange = null;
+ this.serverCredentials = null;
+ this.certificateRequest = null;
+ this.prepareFinishHash = null;
}
protected AbstractTlsContext getContext()
@@ -88,36 +83,9 @@ public class TlsServerProtocol
return tlsServer;
}
- protected void handleChangeCipherSpecMessage()
- throws IOException
- {
-
- switch (this.connection_state)
- {
- case CS_CLIENT_KEY_EXCHANGE:
- {
- if (this.certificateVerifyHash != null)
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
- }
- // NB: Fall through to next case label
- }
- case CS_CERTIFICATE_VERIFY:
- {
- this.connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC;
- break;
- }
- default:
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
- }
- }
- }
-
protected void handleHandshakeMessage(short type, byte[] data)
throws IOException
{
-
ByteArrayInputStream buf = new ByteArrayInputStream(data);
switch (type)
@@ -134,21 +102,6 @@ public class TlsServerProtocol
sendServerHelloMessage();
this.connection_state = CS_SERVER_HELLO;
- // TODO This block could really be done before actually sending the hello
- {
- securityParameters.prfAlgorithm = getPRFAlgorithm(selectedCipherSuite);
- securityParameters.compressionAlgorithm = this.selectedCompressionMethod;
-
- /*
- * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify
- * verify_data_length has a verify_data_length equal to 12. This includes all
- * existing cipher suites.
- */
- securityParameters.verifyDataLength = 12;
-
- recordStream.notifyHelloComplete();
- }
-
Vector serverSupplementalData = tlsServer.getServerSupplementalData();
if (serverSupplementalData != null)
{
@@ -160,6 +113,9 @@ public class TlsServerProtocol
this.keyExchange.init(getContext());
this.serverCredentials = tlsServer.getCredentials();
+
+ Certificate serverCertificate = null;
+
if (this.serverCredentials == null)
{
this.keyExchange.skipServerCredentials();
@@ -167,10 +123,29 @@ public class TlsServerProtocol
else
{
this.keyExchange.processServerCredentials(this.serverCredentials);
- sendCertificateMessage(this.serverCredentials.getCertificate());
+
+ serverCertificate = this.serverCredentials.getCertificate();
+ sendCertificateMessage(serverCertificate);
}
this.connection_state = CS_SERVER_CERTIFICATE;
+ // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus
+ if (serverCertificate == null || serverCertificate.isEmpty())
+ {
+ this.allowCertificateStatus = false;
+ }
+
+ if (this.allowCertificateStatus)
+ {
+ CertificateStatus certificateStatus = tlsServer.getCertificateStatus();
+ if (certificateStatus != null)
+ {
+ sendCertificateStatusMessage(certificateStatus);
+ }
+ }
+
+ this.connection_state = CS_CERTIFICATE_STATUS;
+
byte[] serverKeyExchange = this.keyExchange.generateServerKeyExchange();
if (serverKeyExchange != null)
{
@@ -184,7 +159,11 @@ public class TlsServerProtocol
if (this.certificateRequest != null)
{
this.keyExchange.validateCertificateRequest(certificateRequest);
+
sendCertificateRequestMessage(certificateRequest);
+
+ TlsUtils.trackHashAlgorithms(this.recordStream.getHandshakeHash(),
+ this.certificateRequest.getSupportedSignatureAlgorithms());
}
}
this.connection_state = CS_CERTIFICATE_REQUEST;
@@ -192,12 +171,12 @@ public class TlsServerProtocol
sendServerHelloDoneMessage();
this.connection_state = CS_SERVER_HELLO_DONE;
+ this.recordStream.getHandshakeHash().sealHashAlgorithms();
+
break;
}
default:
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
- }
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
break;
}
@@ -212,9 +191,7 @@ public class TlsServerProtocol
break;
}
default:
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
- }
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
break;
}
@@ -231,16 +208,14 @@ public class TlsServerProtocol
{
if (this.certificateRequest == null)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
receiveCertificateMessage(buf);
this.connection_state = CS_CLIENT_CERTIFICATE;
break;
}
default:
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
- }
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
break;
}
@@ -261,10 +236,7 @@ public class TlsServerProtocol
}
else
{
-
- ProtocolVersion equivalentTLSVersion = getContext().getServerVersion().getEquivalentTLSVersion();
-
- if (ProtocolVersion.TLSv12.isEqualOrEarlierVersionOf(equivalentTLSVersion))
+ if (TlsUtils.isTLSv12(getContext()))
{
/*
* RFC 5246 If no suitable certificate is available, the client MUST send a
@@ -272,13 +244,13 @@ public class TlsServerProtocol
*
* NOTE: In previous RFCs, this was SHOULD instead of MUST.
*/
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- else if (equivalentTLSVersion.isSSL())
+ else if (TlsUtils.isSSL(getContext()))
{
- if (clientCertificate == null)
+ if (this.peerCertificate == null)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
}
else
@@ -295,9 +267,7 @@ public class TlsServerProtocol
break;
}
default:
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
- }
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
break;
}
@@ -312,18 +282,18 @@ public class TlsServerProtocol
* signing capability (i.e., all certificates except those containing fixed
* Diffie-Hellman parameters).
*/
- if (this.certificateVerifyHash == null)
+ if (!expectCertificateVerifyMessage())
{
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
+
receiveCertificateVerifyMessage(buf);
this.connection_state = CS_CERTIFICATE_VERIFY;
+
break;
}
default:
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
- }
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
break;
}
@@ -331,24 +301,33 @@ public class TlsServerProtocol
{
switch (this.connection_state)
{
- case CS_CLIENT_CHANGE_CIPHER_SPEC:
+ case CS_CLIENT_KEY_EXCHANGE:
+ {
+ if (expectCertificateVerifyMessage())
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ // NB: Fall through to next case label
+ }
+ case CS_CERTIFICATE_VERIFY:
+ {
processFinishedMessage(buf);
this.connection_state = CS_CLIENT_FINISHED;
- if (expectSessionTicket)
+ if (this.expectSessionTicket)
{
sendNewSessionTicketMessage(tlsServer.getNewSessionTicket());
+ sendChangeCipherSpecMessage();
}
this.connection_state = CS_SERVER_SESSION_TICKET;
- sendChangeCipherSpecMessage();
- this.connection_state = CS_SERVER_CHANGE_CIPHER_SPEC;
-
sendFinishedMessage();
this.connection_state = CS_SERVER_FINISHED;
+ this.connection_state = CS_END;
break;
+ }
default:
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
break;
}
@@ -360,9 +339,7 @@ public class TlsServerProtocol
case HandshakeType.server_hello_done:
case HandshakeType.session_ticket:
default:
- // We do not support this!
- this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
- break;
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
}
@@ -377,7 +354,7 @@ public class TlsServerProtocol
* SSL 3.0 If the server has sent a certificate request Message, the client must send
* either the certificate message or a no_certificate alert.
*/
- if (getContext().getServerVersion().isSSL() && certificateRequest != null)
+ if (TlsUtils.isSSL(getContext()) && certificateRequest != null)
{
notifyClientCertificate(Certificate.EMPTY_CHAIN);
}
@@ -393,18 +370,17 @@ public class TlsServerProtocol
protected void notifyClientCertificate(Certificate clientCertificate)
throws IOException
{
-
if (certificateRequest == null)
{
throw new IllegalStateException();
}
- if (this.clientCertificate != null)
+ if (this.peerCertificate != null)
{
throw new TlsFatalAlert(AlertDescription.unexpected_message);
}
- this.clientCertificate = clientCertificate;
+ this.peerCertificate = clientCertificate;
if (clientCertificate.isEmpty())
{
@@ -439,7 +415,6 @@ public class TlsServerProtocol
protected void receiveCertificateMessage(ByteArrayInputStream buf)
throws IOException
{
-
Certificate clientCertificate = Certificate.parse(buf);
assertEmpty(buf);
@@ -450,22 +425,24 @@ public class TlsServerProtocol
protected void receiveCertificateVerifyMessage(ByteArrayInputStream buf)
throws IOException
{
-
- byte[] clientCertificateSignature = TlsUtils.readOpaque16(buf);
+ DigitallySigned clientCertificateVerify = DigitallySigned.parse(getContext(), buf);
assertEmpty(buf);
// Verify the CertificateVerify message contains a correct signature.
try
{
- TlsSigner tlsSigner = TlsUtils.createTlsSigner(this.clientCertificateType);
- tlsSigner.init(getContext());
+ // TODO For TLS 1.2, this needs to be the hash specified in the DigitallySigned
+ byte[] certificateVerifyHash = getCurrentPRFHash(getContext(), prepareFinishHash, null);
- org.bouncycastle.asn1.x509.Certificate x509Cert = this.clientCertificate.getCertificateAt(0);
+ org.bouncycastle.asn1.x509.Certificate x509Cert = this.peerCertificate.getCertificateAt(0);
SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(keyInfo);
- tlsSigner.verifyRawSignature(clientCertificateSignature, publicKey, this.certificateVerifyHash);
+ TlsSigner tlsSigner = TlsUtils.createTlsSigner(this.clientCertificateType);
+ tlsSigner.init(getContext());
+ tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(),
+ clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash);
}
catch (Exception e)
{
@@ -476,42 +453,45 @@ public class TlsServerProtocol
protected void receiveClientHelloMessage(ByteArrayInputStream buf)
throws IOException
{
-
ProtocolVersion client_version = TlsUtils.readVersion(buf);
if (client_version.isDTLS())
{
- this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
- /*
- * Read the client random
- */
byte[] client_random = TlsUtils.readFully(32, buf);
+ /*
+ * TODO RFC 5077 3.4. If a ticket is presented by the client, the server MUST NOT attempt to
+ * use the Session ID in the ClientHello for stateful session resumption.
+ */
byte[] sessionID = TlsUtils.readOpaque8(buf);
if (sessionID.length > 32)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
+ /*
+ * TODO RFC 5246 7.4.1.2. If the session_id field is not empty (implying a session
+ * resumption request), this vector MUST include at least the cipher_suite from that
+ * session.
+ */
int cipher_suites_length = TlsUtils.readUint16(buf);
if (cipher_suites_length < 2 || (cipher_suites_length & 1) != 0)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.decode_error);
+ throw new TlsFatalAlert(AlertDescription.decode_error);
}
+ this.offeredCipherSuites = TlsUtils.readUint16Array(cipher_suites_length / 2, buf);
/*
- * NOTE: "If the session_id field is not empty (implying a session resumption request) this
- * vector must include at least the cipher_suite from that session."
+ * TODO RFC 5246 7.4.1.2. If the session_id field is not empty (implying a session
+ * resumption request), it MUST include the compression_method from that session.
*/
- this.offeredCipherSuites = TlsUtils.readUint16Array(cipher_suites_length / 2, buf);
-
int compression_methods_length = TlsUtils.readUint8(buf);
if (compression_methods_length < 1)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
-
this.offeredCompressionMethods = TlsUtils.readUint8Array(compression_methods_length, buf);
/*
@@ -545,7 +525,7 @@ public class TlsServerProtocol
* TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
* to TRUE.
*/
- if (arrayContains(offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
+ if (Arrays.contains(offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
{
this.secure_renegotiation = true;
}
@@ -554,22 +534,19 @@ public class TlsServerProtocol
* The server MUST check if the "renegotiation_info" extension is included in the
* ClientHello.
*/
- if (clientExtensions != null)
+ byte[] renegExtData = TlsUtils.getExtensionData(clientExtensions, EXT_RenegotiationInfo);
+ if (renegExtData != null)
{
- byte[] renegExtValue = (byte[])clientExtensions.get(EXT_RenegotiationInfo);
- if (renegExtValue != null)
+ /*
+ * If the extension is present, set secure_renegotiation flag to TRUE. The
+ * server MUST then verify that the length of the "renegotiated_connection"
+ * field is zero, and if it is not, MUST abort the handshake.
+ */
+ this.secure_renegotiation = true;
+
+ if (!Arrays.constantTimeAreEqual(renegExtData, createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
{
- /*
- * If the extension is present, set secure_renegotiation flag to TRUE. The
- * server MUST then verify that the length of the "renegotiated_connection"
- * field is zero, and if it is not, MUST abort the handshake.
- */
- this.secure_renegotiation = true;
-
- if (!Arrays.constantTimeAreEqual(renegExtValue, createRenegotiationInfo(TlsUtils.EMPTY_BYTES)))
- {
- this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
- }
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
}
}
@@ -585,81 +562,65 @@ public class TlsServerProtocol
protected void receiveClientKeyExchangeMessage(ByteArrayInputStream buf)
throws IOException
{
-
this.keyExchange.processClientKeyExchange(buf);
assertEmpty(buf);
establishMasterSecret(getContext(), keyExchange);
+ recordStream.setPendingConnectionState(getPeer().getCompression(), getPeer().getCipher());
- /*
- * Initialize our cipher suite
- */
- recordStream.setPendingConnectionState(tlsServer.getCompression(), tlsServer.getCipher());
+ this.prepareFinishHash = recordStream.prepareToFinish();
- if (expectCertificateVerifyMessage())
+ if (!expectSessionTicket)
{
- this.certificateVerifyHash = recordStream.getCurrentHash(null);
+ sendChangeCipherSpecMessage();
}
}
protected void sendCertificateRequestMessage(CertificateRequest certificateRequest)
throws IOException
{
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_request);
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeUint8(HandshakeType.certificate_request, buf);
+ certificateRequest.encode(message);
- // Reserve space for length
- TlsUtils.writeUint24(0, buf);
+ message.writeToRecordStream();
+ }
- certificateRequest.encode(buf);
- byte[] message = buf.toByteArray();
+ protected void sendCertificateStatusMessage(CertificateStatus certificateStatus)
+ throws IOException
+ {
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_status);
- // Patch actual length back in
- TlsUtils.writeUint24(message.length - 4, message, 1);
+ certificateStatus.encode(message);
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.writeToRecordStream();
}
protected void sendNewSessionTicketMessage(NewSessionTicket newSessionTicket)
throws IOException
{
-
if (newSessionTicket == null)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeUint8(HandshakeType.session_ticket, buf);
-
- // Reserve space for length
- TlsUtils.writeUint24(0, buf);
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.session_ticket);
- newSessionTicket.encode(buf);
- byte[] message = buf.toByteArray();
+ newSessionTicket.encode(message);
- // Patch actual length back in
- TlsUtils.writeUint24(message.length - 4, message, 1);
-
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.writeToRecordStream();
}
protected void sendServerHelloMessage()
throws IOException
{
-
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- TlsUtils.writeUint8(HandshakeType.server_hello, buf);
-
- // Reserve space for length
- TlsUtils.writeUint24(0, buf);
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.server_hello);
ProtocolVersion server_version = tlsServer.getServerVersion();
if (!server_version.isEqualOrEarlierVersionOf(getContext().getClientVersion()))
{
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
recordStream.setReadVersion(server_version);
@@ -667,32 +628,34 @@ public class TlsServerProtocol
recordStream.setRestrictReadVersion(true);
getContext().setServerVersion(server_version);
- TlsUtils.writeVersion(server_version, buf);
+ TlsUtils.writeVersion(server_version, message);
- buf.write(this.securityParameters.serverRandom);
+ message.write(this.securityParameters.serverRandom);
/*
* The server may return an empty session_id to indicate that the session will not be cached
* and therefore cannot be resumed.
*/
- TlsUtils.writeOpaque8(TlsUtils.EMPTY_BYTES, buf);
+ TlsUtils.writeOpaque8(TlsUtils.EMPTY_BYTES, message);
- this.selectedCipherSuite = tlsServer.getSelectedCipherSuite();
- if (!arrayContains(this.offeredCipherSuites, this.selectedCipherSuite)
- || this.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
- || this.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
+ int selectedCipherSuite = tlsServer.getSelectedCipherSuite();
+ if (!Arrays.contains(this.offeredCipherSuites, selectedCipherSuite)
+ || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
+ || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
{
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
+ securityParameters.cipherSuite = selectedCipherSuite;
- this.selectedCompressionMethod = tlsServer.getSelectedCompressionMethod();
- if (!arrayContains(this.offeredCompressionMethods, this.selectedCompressionMethod))
+ short selectedCompressionMethod = tlsServer.getSelectedCompressionMethod();
+ if (!Arrays.contains(this.offeredCompressionMethods, selectedCompressionMethod))
{
- this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
+ securityParameters.compressionAlgorithm = selectedCompressionMethod;
- TlsUtils.writeUint16(this.selectedCipherSuite, buf);
- TlsUtils.writeUint8(this.selectedCompressionMethod, buf);
+ TlsUtils.writeUint16(selectedCipherSuite, message);
+ TlsUtils.writeUint8(selectedCompressionMethod, message);
this.serverExtensions = tlsServer.getServerExtensions();
@@ -701,9 +664,8 @@ public class TlsServerProtocol
*/
if (this.secure_renegotiation)
{
-
- boolean noRenegExt = this.serverExtensions == null
- || !this.serverExtensions.containsKey(EXT_RenegotiationInfo);
+ byte[] renegExtData = TlsUtils.getExtensionData(this.serverExtensions, EXT_RenegotiationInfo);
+ boolean noRenegExt = (null == renegExtData);
if (noRenegExt)
{
@@ -714,55 +676,81 @@ public class TlsServerProtocol
* because the client is signaling its willingness to receive the extension via the
* TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
*/
- if (this.serverExtensions == null)
- {
- this.serverExtensions = new Hashtable();
- }
/*
* If the secure_renegotiation flag is set to TRUE, the server MUST include an empty
* "renegotiation_info" extension in the ServerHello message.
*/
+ this.serverExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(this.serverExtensions);
this.serverExtensions.put(EXT_RenegotiationInfo, createRenegotiationInfo(TlsUtils.EMPTY_BYTES));
}
}
+ /*
+ * TODO RFC 3546 2.3 If [...] the older session is resumed, then the server MUST ignore
+ * extensions appearing in the client hello, and send a server hello containing no
+ * extensions.
+ */
+
if (this.serverExtensions != null)
{
- this.expectSessionTicket = serverExtensions.containsKey(EXT_SessionTicket);
- writeExtensions(buf, this.serverExtensions);
+ this.securityParameters.maxFragmentLength = processMaxFragmentLengthExtension(clientExtensions,
+ this.serverExtensions, AlertDescription.internal_error);
+
+ this.securityParameters.truncatedHMac = TlsExtensionsUtils.hasTruncatedHMacExtension(this.serverExtensions);
+
+ /*
+ * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in
+ * a session resumption handshake.
+ */
+ this.allowCertificateStatus = !this.resumedSession
+ && TlsUtils.hasExpectedEmptyExtensionData(this.serverExtensions, TlsExtensionsUtils.EXT_status_request,
+ AlertDescription.internal_error);
+
+ this.expectSessionTicket = !this.resumedSession
+ && TlsUtils.hasExpectedEmptyExtensionData(this.serverExtensions, TlsProtocol.EXT_SessionTicket,
+ AlertDescription.internal_error);
+
+ writeExtensions(message, this.serverExtensions);
+ }
+
+ if (this.securityParameters.maxFragmentLength >= 0)
+ {
+ int plainTextLimit = 1 << (8 + this.securityParameters.maxFragmentLength);
+ recordStream.setPlaintextLimit(plainTextLimit);
}
- byte[] message = buf.toByteArray();
+ securityParameters.prfAlgorithm = getPRFAlgorithm(getContext(), securityParameters.getCipherSuite());
- // Patch actual length back in
- TlsUtils.writeUint24(message.length - 4, message, 1);
+ /*
+ * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length has
+ * a verify_data_length equal to 12. This includes all existing cipher suites.
+ */
+ securityParameters.verifyDataLength = 12;
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.writeToRecordStream();
+
+ this.recordStream.notifyHelloComplete();
}
protected void sendServerHelloDoneMessage()
throws IOException
{
-
byte[] message = new byte[4];
TlsUtils.writeUint8(HandshakeType.server_hello_done, message, 0);
TlsUtils.writeUint24(0, message, 1);
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ writeHandshakeMessage(message, 0, message.length);
}
protected void sendServerKeyExchangeMessage(byte[] serverKeyExchange)
throws IOException
{
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ HandshakeMessage message = new HandshakeMessage(HandshakeType.server_key_exchange, serverKeyExchange.length);
- TlsUtils.writeUint8(HandshakeType.server_key_exchange, bos);
- TlsUtils.writeUint24(serverKeyExchange.length, bos);
- bos.write(serverKeyExchange);
- byte[] message = bos.toByteArray();
+ message.write(serverKeyExchange);
- safeWriteRecord(ContentType.handshake, message, 0, message.length);
+ message.writeToRecordStream();
}
protected boolean expectCertificateVerifyMessage()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSession.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSession.java
new file mode 100644
index 0000000..9b5ad46
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSession.java
@@ -0,0 +1,12 @@
+package org.bouncycastle.crypto.tls;
+
+public interface TlsSession
+{
+ SessionParameters exportSessionParameters();
+
+ byte[] getSessionID();
+
+ void invalidate();
+
+ boolean isResumable();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSessionImpl.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSessionImpl.java
new file mode 100644
index 0000000..615c442
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSessionImpl.java
@@ -0,0 +1,48 @@
+package org.bouncycastle.crypto.tls;
+
+import org.bouncycastle.util.Arrays;
+
+class TlsSessionImpl implements TlsSession
+{
+ final byte[] sessionID;
+ SessionParameters sessionParameters;
+
+ TlsSessionImpl(byte[] sessionID, SessionParameters sessionParameters)
+ {
+ if (sessionID == null)
+ {
+ throw new IllegalArgumentException("'sessionID' cannot be null");
+ }
+ if (sessionID.length < 1 || sessionID.length > 32)
+ {
+ throw new IllegalArgumentException("'sessionID' must have length between 1 and 32 bytes, inclusive");
+ }
+
+ this.sessionID = Arrays.clone(sessionID);
+ this.sessionParameters = sessionParameters;
+ }
+
+ public synchronized SessionParameters exportSessionParameters()
+ {
+ return this.sessionParameters == null ? null : this.sessionParameters.copy();
+ }
+
+ public synchronized byte[] getSessionID()
+ {
+ return sessionID;
+ }
+
+ public synchronized void invalidate()
+ {
+ if (this.sessionParameters != null)
+ {
+ this.sessionParameters.clear();
+ this.sessionParameters = null;
+ }
+ }
+
+ public synchronized boolean isResumable()
+ {
+ return this.sessionParameters != null;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSigner.java
index 2b61507..68826d2 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSigner.java
@@ -6,18 +6,29 @@ import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
public interface TlsSigner
{
-
void init(TlsContext context);
byte[] generateRawSignature(AsymmetricKeyParameter privateKey, byte[] md5AndSha1)
throws CryptoException;
+ byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm,
+ AsymmetricKeyParameter privateKey, byte[] hash)
+ throws CryptoException;
+
boolean verifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5AndSha1)
throws CryptoException;
+ boolean verifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+ AsymmetricKeyParameter publicKey, byte[] hash)
+ throws CryptoException;
+
Signer createSigner(AsymmetricKeyParameter privateKey);
+ Signer createSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey);
+
Signer createVerifyer(AsymmetricKeyParameter publicKey);
+ Signer createVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey);
+
boolean isValidPublicKey(AsymmetricKeyParameter publicKey);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSignerCredentials.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSignerCredentials.java
index 7067fa2..39ee99c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSignerCredentials.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsSignerCredentials.java
@@ -5,6 +5,8 @@ import java.io.IOException;
public interface TlsSignerCredentials
extends TlsCredentials
{
- byte[] generateCertificateSignature(byte[] md5andsha1)
+ byte[] generateCertificateSignature(byte[] hash)
throws IOException;
+
+ SignatureAndHashAlgorithm getSignatureAndHashAlgorithm();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsStreamCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsStreamCipher.java
index 1755c2d..178731d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsStreamCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsStreamCipher.java
@@ -11,6 +11,8 @@ import org.bouncycastle.util.Arrays;
public class TlsStreamCipher
implements TlsCipher
{
+ private static boolean encryptThenMAC = false;
+
protected TlsContext context;
protected StreamCipher encryptCipher;
@@ -20,11 +22,9 @@ public class TlsStreamCipher
protected TlsMac readMac;
public TlsStreamCipher(TlsContext context, StreamCipher clientWriteCipher,
- StreamCipher serverWriteCipher, Digest clientWriteDigest, Digest serverWriteDigest,
- int cipherKeySize)
- throws IOException
+ StreamCipher serverWriteCipher, Digest clientWriteDigest, Digest serverWriteDigest,
+ int cipherKeySize) throws IOException
{
-
boolean isServer = context.isServer();
this.context = context;
@@ -89,38 +89,75 @@ public class TlsStreamCipher
public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len)
{
- byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
+ /*
+ * TODO[draft-josefsson-salsa20-tls-02] Note that Salsa20 requires a 64-bit nonce. That
+ * nonce is updated on the encryption of every TLS record, and is set to be the 64-bit TLS
+ * record sequence number. In case of DTLS the 64-bit nonce is formed as the concatenation
+ * of the 16-bit epoch with the 48-bit sequence number.
+ */
- byte[] outbuf = new byte[len + mac.length];
+ byte[] outBuf = new byte[len + writeMac.getSize()];
- encryptCipher.processBytes(plaintext, offset, len, outbuf, 0);
- encryptCipher.processBytes(mac, 0, mac.length, outbuf, len);
+ encryptCipher.processBytes(plaintext, offset, len, outBuf, 0);
+
+ if (encryptThenMAC)
+ {
+ byte[] mac = writeMac.calculateMac(seqNo, type, outBuf, 0, len);
+ System.arraycopy(mac, 0, outBuf, len, mac.length);
+ }
+ else
+ {
+ byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
+ encryptCipher.processBytes(mac, 0, mac.length, outBuf, len);
+ }
- return outbuf;
+ return outBuf;
}
public byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len)
throws IOException
{
+ /*
+ * TODO[draft-josefsson-salsa20-tls-02] Note that Salsa20 requires a 64-bit nonce. That
+ * nonce is updated on the encryption of every TLS record, and is set to be the 64-bit TLS
+ * record sequence number. In case of DTLS the 64-bit nonce is formed as the concatenation
+ * of the 16-bit epoch with the 48-bit sequence number.
+ */
+
int macSize = readMac.getSize();
if (len < macSize)
{
throw new TlsFatalAlert(AlertDescription.decode_error);
}
- byte[] deciphered = new byte[len];
- decryptCipher.processBytes(ciphertext, offset, len, deciphered, 0);
+ int plaintextLength = len - macSize;
- int macInputLen = len - macSize;
+ if (encryptThenMAC)
+ {
+ int ciphertextEnd = offset + len;
+ checkMAC(seqNo, type, ciphertext, ciphertextEnd - macSize, ciphertextEnd, ciphertext, offset, plaintextLength);
+ byte[] deciphered = new byte[plaintextLength];
+ decryptCipher.processBytes(ciphertext, offset, plaintextLength, deciphered, 0);
+ return deciphered;
+ }
+ else
+ {
+ byte[] deciphered = new byte[len];
+ decryptCipher.processBytes(ciphertext, offset, len, deciphered, 0);
+ checkMAC(seqNo, type, deciphered, plaintextLength, len, deciphered, 0, plaintextLength);
+ return Arrays.copyOfRange(deciphered, 0, plaintextLength);
+ }
+ }
- byte[] receivedMac = Arrays.copyOfRange(deciphered, macInputLen, len);
- byte[] computedMac = readMac.calculateMac(seqNo, type, deciphered, 0, macInputLen);
+ private void checkMAC(long seqNo, short type, byte[] recBuf, int recStart, int recEnd, byte[] calcBuf, int calcOff, int calcLen)
+ throws IOException
+ {
+ byte[] receivedMac = Arrays.copyOfRange(recBuf, recStart, recEnd);
+ byte[] computedMac = readMac.calculateMac(seqNo, type, calcBuf, calcOff, calcLen);
if (!Arrays.constantTimeAreEqual(receivedMac, computedMac))
{
throw new TlsFatalAlert(AlertDescription.bad_record_mac);
}
-
- return Arrays.copyOfRange(deciphered, 0, macInputLen);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsUtils.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsUtils.java
index 8b16210..dae9ff5 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsUtils.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsUtils.java
@@ -9,7 +9,10 @@ import java.io.OutputStream;
import java.util.Hashtable;
import java.util.Vector;
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.Extensions;
@@ -44,11 +47,72 @@ public class TlsUtils
public static final Integer EXT_signature_algorithms = Integers.valueOf(ExtensionType.signature_algorithms);
+ public static void checkUint8(short i) throws IOException
+ {
+ if (!isValidUint8(i))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public static void checkUint8(int i) throws IOException
+ {
+ if (!isValidUint8(i))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public static void checkUint16(int i) throws IOException
+ {
+ if (!isValidUint16(i))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public static void checkUint24(int i) throws IOException
+ {
+ if (!isValidUint24(i))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public static void checkUint32(long i) throws IOException
+ {
+ if (!isValidUint32(i))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public static void checkUint48(long i) throws IOException
+ {
+ if (!isValidUint48(i))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public static void checkUint64(long i) throws IOException
+ {
+ if (!isValidUint64(i))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
public static boolean isValidUint8(short i)
{
return (i & 0xFF) == i;
}
+ public static boolean isValidUint8(int i)
+ {
+ return (i & 0xFF) == i;
+ }
+
public static boolean isValidUint16(int i)
{
return (i & 0xFFFF) == i;
@@ -74,17 +138,43 @@ public class TlsUtils
return true;
}
+ public static boolean isSSL(TlsContext context)
+ {
+ return context.getServerVersion().isSSL();
+ }
+
+ public static boolean isTLSv11(TlsContext context)
+ {
+ return ProtocolVersion.TLSv11.isEqualOrEarlierVersionOf(context.getServerVersion().getEquivalentTLSVersion());
+ }
+
+ public static boolean isTLSv12(TlsContext context)
+ {
+ return ProtocolVersion.TLSv12.isEqualOrEarlierVersionOf(context.getServerVersion().getEquivalentTLSVersion());
+ }
+
public static void writeUint8(short i, OutputStream output)
throws IOException
{
output.write(i);
}
+ public static void writeUint8(int i, OutputStream output)
+ throws IOException
+ {
+ output.write(i);
+ }
+
public static void writeUint8(short i, byte[] buf, int offset)
{
buf[offset] = (byte)i;
}
+ public static void writeUint8(int i, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)i;
+ }
+
public static void writeUint16(int i, OutputStream output)
throws IOException
{
@@ -130,6 +220,17 @@ public class TlsUtils
buf[offset + 3] = (byte)(i);
}
+ public static void writeUint48(long i, OutputStream output)
+ throws IOException
+ {
+ output.write((byte)(i >> 40));
+ output.write((byte)(i >> 32));
+ output.write((byte)(i >> 24));
+ output.write((byte)(i >> 16));
+ output.write((byte)(i >> 8));
+ output.write((byte)(i));
+ }
+
public static void writeUint48(long i, byte[] buf, int offset)
{
buf[offset] = (byte)(i >> 40);
@@ -143,14 +244,14 @@ public class TlsUtils
public static void writeUint64(long i, OutputStream output)
throws IOException
{
- output.write((int)(i >> 56));
- output.write((int)(i >> 48));
- output.write((int)(i >> 40));
- output.write((int)(i >> 32));
- output.write((int)(i >> 24));
- output.write((int)(i >> 16));
- output.write((int)(i >> 8));
- output.write((int)(i));
+ output.write((byte)(i >> 56));
+ output.write((byte)(i >> 48));
+ output.write((byte)(i >> 40));
+ output.write((byte)(i >> 32));
+ output.write((byte)(i >> 24));
+ output.write((byte)(i >> 16));
+ output.write((byte)(i >> 8));
+ output.write((byte)(i));
}
public static void writeUint64(long i, byte[] buf, int offset)
@@ -168,13 +269,15 @@ public class TlsUtils
public static void writeOpaque8(byte[] buf, OutputStream output)
throws IOException
{
- writeUint8((short)buf.length, output);
+ checkUint8(buf.length);
+ writeUint8(buf.length, output);
output.write(buf);
}
public static void writeOpaque16(byte[] buf, OutputStream output)
throws IOException
{
+ checkUint16(buf.length);
writeUint16(buf.length, output);
output.write(buf);
}
@@ -182,6 +285,7 @@ public class TlsUtils
public static void writeOpaque24(byte[] buf, OutputStream output)
throws IOException
{
+ checkUint24(buf.length);
writeUint24(buf.length, output);
output.write(buf);
}
@@ -195,6 +299,32 @@ public class TlsUtils
}
}
+ public static void writeUint8Array(short[] uints, byte[] buf, int offset)
+ throws IOException
+ {
+ for (int i = 0; i < uints.length; ++i)
+ {
+ writeUint8(uints[i], buf, offset);
+ ++offset;
+ }
+ }
+
+ public static void writeUint8ArrayWithUint8Length(short[] uints, OutputStream output)
+ throws IOException
+ {
+ checkUint8(uints.length);
+ writeUint8(uints.length, output);
+ writeUint8Array(uints, output);
+ }
+
+ public static void writeUint8ArrayWithUint8Length(short[] uints, byte[] buf, int offset)
+ throws IOException
+ {
+ checkUint8(uints.length);
+ writeUint8(uints.length, buf, offset);
+ writeUint8Array(uints, buf, offset + 1);
+ }
+
public static void writeUint16Array(int[] uints, OutputStream output)
throws IOException
{
@@ -204,6 +334,56 @@ public class TlsUtils
}
}
+ public static void writeUint16Array(int[] uints, byte[] buf, int offset)
+ throws IOException
+ {
+ for (int i = 0; i < uints.length; ++i)
+ {
+ writeUint16(uints[i], buf, offset);
+ offset += 2;
+ }
+ }
+
+ public static void writeUint16ArrayWithUint16Length(int[] uints, OutputStream output)
+ throws IOException
+ {
+ int length = 2 * uints.length;
+ checkUint16(length);
+ writeUint16(length, output);
+ writeUint16Array(uints, output);
+ }
+
+ public static void writeUint16ArrayWithUint16Length(int[] uints, byte[] buf, int offset)
+ throws IOException
+ {
+ int length = 2 * uints.length;
+ checkUint16(length);
+ writeUint16(length, buf, offset);
+ writeUint16Array(uints, buf, offset + 2);
+ }
+
+ public static byte[] encodeOpaque8(byte[] buf)
+ throws IOException
+ {
+ checkUint8(buf.length);
+ return Arrays.prepend(buf, (byte)buf.length);
+ }
+
+ public static byte[] encodeUint8ArrayWithUint8Length(short[] uints) throws IOException
+ {
+ byte[] result = new byte[1 + uints.length];
+ writeUint8ArrayWithUint8Length(uints, result, 0);
+ return result;
+ }
+
+ public static byte[] encodeUint16ArrayWithUint16Length(int[] uints) throws IOException
+ {
+ int length = 2 * uints.length;
+ byte[] result = new byte[2 + length];
+ writeUint16ArrayWithUint16Length(uints, result, 0);
+ return result;
+ }
+
public static short readUint8(InputStream input)
throws IOException
{
@@ -297,6 +477,26 @@ public class TlsUtils
return ((long)(hi & 0xffffffffL) << 24) | (long)(lo & 0xffffffffL);
}
+ public static byte[] readAllOrNothing(int length, InputStream input)
+ throws IOException
+ {
+ if (length < 1)
+ {
+ return EMPTY_BYTES;
+ }
+ byte[] buf = new byte[length];
+ int read = Streams.readFully(input, buf);
+ if (read == 0)
+ {
+ return null;
+ }
+ if (read != length)
+ {
+ throw new EOFException();
+ }
+ return buf;
+ }
+
public static byte[] readFully(int length, InputStream input)
throws IOException
{
@@ -383,6 +583,12 @@ public class TlsUtils
return ProtocolVersion.get(i1, i2);
}
+ public static int readVersionRaw(byte[] buf, int offset)
+ throws IOException
+ {
+ return (buf[offset] << 8) | buf[offset + 1];
+ }
+
public static int readVersionRaw(InputStream input)
throws IOException
{
@@ -395,6 +601,36 @@ public class TlsUtils
return (i1 << 8) | i2;
}
+ public static ASN1Primitive readASN1Object(byte[] encoding) throws IOException
+ {
+ ASN1InputStream asn1 = new ASN1InputStream(encoding);
+ ASN1Primitive result = asn1.readObject();
+ if (null == result)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ if (null != asn1.readObject())
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ return result;
+ }
+
+ public static ASN1Primitive readDERObject(byte[] encoding) throws IOException
+ {
+ /*
+ * NOTE: The current ASN.1 parsing code can't enforce DER-only parsing, but since DER is
+ * canonical, we can check it by re-encoding the result and comparing to the original.
+ */
+ ASN1Primitive result = readASN1Object(encoding);
+ byte[] check = result.getEncoded(ASN1Encoding.DER);
+ if (!Arrays.areEqual(check, encoding))
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ return result;
+ }
+
public static void writeGMTUnixTime(byte[] buf, int offset)
{
int t = (int)(System.currentTimeMillis() / 1000L);
@@ -412,7 +648,6 @@ public class TlsUtils
}
public static void writeVersion(ProtocolVersion version, byte[] buf, int offset)
- throws IOException
{
buf[offset] = (byte)version.getMajorVersion();
buf[offset + 1] = (byte)version.getMinorVersion();
@@ -433,6 +668,31 @@ public class TlsUtils
return vectorOfOne(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa));
}
+ public static byte[] getExtensionData(Hashtable extensions, Integer extensionType)
+ {
+ return extensions == null ? null : (byte[])extensions.get(extensionType);
+ }
+
+ public static boolean hasExpectedEmptyExtensionData(Hashtable extensions, Integer extensionType,
+ short alertDescription) throws IOException
+ {
+ byte[] extension_data = getExtensionData(extensions, extensionType);
+ if (extension_data == null)
+ {
+ return false;
+ }
+ if (extension_data.length != 0)
+ {
+ throw new TlsFatalAlert(alertDescription);
+ }
+ return true;
+ }
+
+ public static TlsSession importSession(byte[] sessionID, SessionParameters sessionParameters)
+ {
+ return new TlsSessionImpl(sessionID, sessionParameters);
+ }
+
public static boolean isSignatureAlgorithmsExtensionAllowed(ProtocolVersion clientVersion)
{
return ProtocolVersion.TLSv12.isEqualOrEarlierVersionOf(clientVersion.getEquivalentTLSVersion());
@@ -461,17 +721,8 @@ public class TlsUtils
public static Vector getSignatureAlgorithmsExtension(Hashtable extensions)
throws IOException
{
-
- if (extensions == null)
- {
- return null;
- }
- byte[] extensionValue = (byte[])extensions.get(EXT_signature_algorithms);
- if (extensionValue == null)
- {
- return null;
- }
- return readSignatureAlgorithmsExtension(extensionValue);
+ byte[] extensionData = getExtensionData(extensions, EXT_signature_algorithms);
+ return extensionData == null ? null : readSignatureAlgorithmsExtension(extensionData);
}
/**
@@ -484,61 +735,94 @@ public class TlsUtils
public static byte[] createSignatureAlgorithmsExtension(Vector supportedSignatureAlgorithms)
throws IOException
{
-
- if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.size() < 1 || supportedSignatureAlgorithms.size() >= (1 << 15))
- {
- throw new IllegalArgumentException(
- "'supportedSignatureAlgorithms' must have length from 1 to (2^15 - 1)");
- }
-
ByteArrayOutputStream buf = new ByteArrayOutputStream();
// supported_signature_algorithms
- TlsUtils.writeUint16(2 * supportedSignatureAlgorithms.size(), buf);
- for (int i = 0; i < supportedSignatureAlgorithms.size(); ++i)
- {
- SignatureAndHashAlgorithm entry = (SignatureAndHashAlgorithm)supportedSignatureAlgorithms.elementAt(i);
- entry.encode(buf);
- }
+ encodeSupportedSignatureAlgorithms(supportedSignatureAlgorithms, false, buf);
return buf.toByteArray();
}
/**
- * Read a 'signature_algorithms' extension value.
+ * Read 'signature_algorithms' extension data.
*
- * @param extensionValue The extension value.
+ * @param extensionData The extension data.
* @return A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
* @throws IOException
*/
- public static Vector readSignatureAlgorithmsExtension(byte[] extensionValue)
+ public static Vector readSignatureAlgorithmsExtension(byte[] extensionData)
throws IOException
{
+ if (extensionData == null)
+ {
+ throw new IllegalArgumentException("'extensionData' cannot be null");
+ }
+
+ ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
- if (extensionValue == null)
+ // supported_signature_algorithms
+ Vector supported_signature_algorithms = parseSupportedSignatureAlgorithms(false, buf);
+
+ TlsProtocol.assertEmpty(buf);
+
+ return supported_signature_algorithms;
+ }
+
+ public static void encodeSupportedSignatureAlgorithms(Vector supportedSignatureAlgorithms, boolean allowAnonymous,
+ OutputStream output) throws IOException
+ {
+ if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.size() < 1
+ || supportedSignatureAlgorithms.size() >= (1 << 15))
{
- throw new IllegalArgumentException("'extensionValue' cannot be null");
+ throw new IllegalArgumentException(
+ "'supportedSignatureAlgorithms' must have length from 1 to (2^15 - 1)");
}
- ByteArrayInputStream buf = new ByteArrayInputStream(extensionValue);
+ // supported_signature_algorithms
+ int length = 2 * supportedSignatureAlgorithms.size();
+ TlsUtils.checkUint16(length);
+ TlsUtils.writeUint16(length, output);
+ for (int i = 0; i < supportedSignatureAlgorithms.size(); ++i)
+ {
+ SignatureAndHashAlgorithm entry = (SignatureAndHashAlgorithm)supportedSignatureAlgorithms.elementAt(i);
+ if (!allowAnonymous && entry.getSignature() == SignatureAlgorithm.anonymous)
+ {
+ /*
+ * RFC 5246 7.4.1.4.1 The "anonymous" value is meaningless in this context but used
+ * in Section 7.4.3. It MUST NOT appear in this extension.
+ */
+ throw new IllegalArgumentException(
+ "SignatureAlgorithm.anonymous MUST NOT appear in the signature_algorithms extension");
+ }
+ entry.encode(output);
+ }
+ }
+ public static Vector parseSupportedSignatureAlgorithms(boolean allowAnonymous, InputStream input)
+ throws IOException
+ {
// supported_signature_algorithms
- int length = TlsUtils.readUint16(buf);
+ int length = TlsUtils.readUint16(input);
if (length < 2 || (length & 1) != 0)
{
throw new TlsFatalAlert(AlertDescription.decode_error);
}
int count = length / 2;
- Vector result = new Vector(count);
+ Vector supportedSignatureAlgorithms = new Vector(count);
for (int i = 0; i < count; ++i)
{
- SignatureAndHashAlgorithm entry = SignatureAndHashAlgorithm.parse(buf);
- result.addElement(entry);
+ SignatureAndHashAlgorithm entry = SignatureAndHashAlgorithm.parse(input);
+ if (!allowAnonymous && entry.getSignature() == SignatureAlgorithm.anonymous)
+ {
+ /*
+ * RFC 5246 7.4.1.4.1 The "anonymous" value is meaningless in this context but used
+ * in Section 7.4.3. It MUST NOT appear in this extension.
+ */
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ supportedSignatureAlgorithms.addElement(entry);
}
-
- TlsProtocol.assertEmpty(buf);
-
- return result;
+ return supportedSignatureAlgorithms;
}
public static byte[] PRF(TlsContext context, byte[] secret, String asciiLabel, byte[] seed, int size)
@@ -557,12 +841,7 @@ public class TlsUtils
if (prfAlgorithm == PRFAlgorithm.tls_prf_legacy)
{
- if (!ProtocolVersion.TLSv12.isEqualOrEarlierVersionOf(version.getEquivalentTLSVersion()))
- {
- return PRF_legacy(secret, label, labelSeed, size);
- }
-
- prfAlgorithm = PRFAlgorithm.tls_prf_sha256;
+ return PRF_legacy(secret, label, labelSeed, size);
}
Digest prfDigest = createPRFHash(prfAlgorithm);
@@ -646,7 +925,7 @@ public class TlsUtils
byte[] seed = concat(securityParameters.getServerRandom(),
securityParameters.getClientRandom());
- if (context.getServerVersion().isSSL())
+ if (isSSL(context))
{
return calculateKeyBlock_SSL(master_secret, seed, size);
}
@@ -690,7 +969,7 @@ public class TlsUtils
SecurityParameters securityParameters = context.getSecurityParameters();
byte[] seed = concat(securityParameters.getClientRandom(), securityParameters.getServerRandom());
- if (context.getServerVersion().isSSL())
+ if (isSSL(context))
{
return calculateMasterSecret_SSL(pre_master_secret, seed);
}
@@ -729,7 +1008,7 @@ public class TlsUtils
static byte[] calculateVerifyData(TlsContext context, String asciiLabel, byte[] handshakeHash)
{
- if (context.getServerVersion().isSSL())
+ if (isSSL(context))
{
return handshakeHash;
}
@@ -741,7 +1020,7 @@ public class TlsUtils
return PRF(context, master_secret, asciiLabel, handshakeHash, verify_data_length);
}
- public static final Digest createHash(int hashAlgorithm)
+ public static final Digest createHash(short hashAlgorithm)
{
switch (hashAlgorithm)
{
@@ -762,7 +1041,7 @@ public class TlsUtils
}
}
- public static final Digest cloneHash(int hashAlgorithm, Digest hash)
+ public static final Digest cloneHash(short hashAlgorithm, Digest hash)
{
switch (hashAlgorithm)
{
@@ -820,7 +1099,7 @@ public class TlsUtils
}
}
- public static ASN1ObjectIdentifier getOIDForHashAlgorithm(int hashAlgorithm)
+ public static ASN1ObjectIdentifier getOIDForHashAlgorithm(short hashAlgorithm)
{
switch (hashAlgorithm)
{
@@ -912,6 +1191,20 @@ public class TlsUtils
throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
}
+ static void trackHashAlgorithms(TlsHandshakeHash handshakeHash, Vector supportedSignatureAlgorithms)
+ {
+ if (supportedSignatureAlgorithms != null)
+ {
+ for (int i = 0; i < supportedSignatureAlgorithms.size(); ++i)
+ {
+ SignatureAndHashAlgorithm signatureAndHashAlgorithm = (SignatureAndHashAlgorithm)
+ supportedSignatureAlgorithms.elementAt(i);
+ short hashAlgorithm = signatureAndHashAlgorithm.getHash();
+ handshakeHash.trackHashAlgorithm(hashAlgorithm);
+ }
+ }
+ }
+
public static boolean hasSigningCapability(short clientCertificateType)
{
switch (clientCertificateType)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/UDPTransport.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/UDPTransport.java
index f3dd59e..d5f0769 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/tls/UDPTransport.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/UDPTransport.java
@@ -7,18 +7,16 @@ import java.net.DatagramSocket;
public class UDPTransport
implements DatagramTransport
{
+ protected final static int MIN_IP_OVERHEAD = 20;
+ protected final static int MAX_IP_OVERHEAD = MIN_IP_OVERHEAD + 64;
+ protected final static int UDP_OVERHEAD = 8;
- private final static int MIN_IP_OVERHEAD = 20;
- private final static int MAX_IP_OVERHEAD = MIN_IP_OVERHEAD + 64;
- private final static int UDP_OVERHEAD = 8;
-
- private final DatagramSocket socket;
- private final int receiveLimit, sendLimit;
+ protected final DatagramSocket socket;
+ protected final int receiveLimit, sendLimit;
public UDPTransport(DatagramSocket socket, int mtu)
throws IOException
{
-
if (!socket.isBound() || !socket.isConnected())
{
throw new IllegalArgumentException("'socket' must be bound and connected");
@@ -62,7 +60,7 @@ public class UDPTransport
* the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
* which will be fragmented."
*/
- // TODO Exception
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
DatagramPacket packet = new DatagramPacket(buf, off, len);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/URLAndHash.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/URLAndHash.java
new file mode 100644
index 0000000..c32a904
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/URLAndHash.java
@@ -0,0 +1,104 @@
+package org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.bouncycastle.util.Strings;
+
+/**
+ * RFC 6066 5.
+ */
+public class URLAndHash
+{
+ protected String url;
+ protected byte[] sha1Hash;
+
+ public URLAndHash(String url, byte[] sha1Hash)
+ {
+ if (url == null || url.length() < 1 || url.length() >= (1 << 16))
+ {
+ throw new IllegalArgumentException("'url' must have length from 1 to (2^16 - 1)");
+ }
+ if (sha1Hash != null && sha1Hash.length != 20)
+ {
+ throw new IllegalArgumentException("'sha1Hash' must have length == 20, if present");
+ }
+
+ this.url = url;
+ this.sha1Hash = sha1Hash;
+ }
+
+ public String getURL()
+ {
+ return url;
+ }
+
+ public byte[] getSHA1Hash()
+ {
+ return sha1Hash;
+ }
+
+ /**
+ * Encode this {@link URLAndHash} to an {@link OutputStream}.
+ *
+ * @param output the {@link OutputStream} to encode to.
+ * @throws IOException
+ */
+ public void encode(OutputStream output)
+ throws IOException
+ {
+ byte[] urlEncoding = Strings.toByteArray(this.url);
+ TlsUtils.writeOpaque16(urlEncoding, output);
+
+ if (this.sha1Hash == null)
+ {
+ TlsUtils.writeUint8(0, output);
+ }
+ else
+ {
+ TlsUtils.writeUint8(1, output);
+ output.write(this.sha1Hash);
+ }
+ }
+
+ /**
+ * Parse a {@link URLAndHash} from an {@link InputStream}.
+ *
+ * @param context
+ * the {@link TlsContext} of the current connection.
+ * @param input
+ * the {@link InputStream} to parse from.
+ * @return a {@link URLAndHash} object.
+ * @throws IOException
+ */
+ public static URLAndHash parse(TlsContext context, InputStream input)
+ throws IOException
+ {
+ byte[] urlEncoding = TlsUtils.readOpaque16(input);
+ if (urlEncoding.length < 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ String url = Strings.fromByteArray(urlEncoding);
+
+ byte[] sha1Hash = null;
+ short padding = TlsUtils.readUint8(input);
+ switch (padding)
+ {
+ case 0:
+ if (TlsUtils.isTLSv12(context))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ break;
+ case 1:
+ sha1Hash = TlsUtils.readFully(20, input);
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return new URLAndHash(url, sha1Hash);
+ }
+}
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 bfa304b..6bf3399 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
@@ -10,7 +10,6 @@ import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.oiw.ElGamalParameter;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.DHParameter;
@@ -18,11 +17,9 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.sec.ECPrivateKey;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
+import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
@@ -130,22 +127,7 @@ public class PrivateKeyFactory
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
- x9 = X962NamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = SECNamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = NISTNamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = TeleTrusTNamedCurves.getByOID(oid);
- }
- }
- }
+ x9 = ECNamedCurveTable.getByOID(oid);
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java
index ab52802..7b06c3f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java
@@ -2,17 +2,23 @@ package org.bouncycastle.crypto.util;
import java.io.IOException;
+import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
+import org.bouncycastle.asn1.sec.ECPrivateKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
+import org.bouncycastle.asn1.x9.X962Parameters;
+import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
@@ -43,6 +49,31 @@ public class PrivateKeyInfoFactory
return new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(params.getP(), params.getQ(), params.getG())), new ASN1Integer(priv.getX()));
}
+ else if (privateKey instanceof ECPrivateKeyParameters)
+ {
+ ECPrivateKeyParameters priv = (ECPrivateKeyParameters)privateKey;
+ ECDomainParameters domainParams = priv.getParameters();
+ ASN1Encodable params;
+
+ // TODO: need to handle named curves
+ if (domainParams == null)
+ {
+ params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA
+ }
+ else
+ {
+ X9ECParameters ecP = new X9ECParameters(
+ domainParams.getCurve(),
+ domainParams.getG(),
+ domainParams.getN(),
+ domainParams.getH(),
+ domainParams.getSeed());
+
+ params = new X962Parameters(ecP);
+ }
+
+ return new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), new ECPrivateKey(priv.getD(), params));
+ }
else
{
throw new IOException("key parameters not recognised.");
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 343bbd3..2d2927b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
@@ -12,14 +12,11 @@ import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
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.sec.SECNamedCurves;
-import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
@@ -27,7 +24,7 @@ import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.asn1.x9.DHDomainParameters;
import org.bouncycastle.asn1.x9.DHPublicKey;
import org.bouncycastle.asn1.x9.DHValidationParms;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
+import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECPoint;
@@ -160,29 +157,13 @@ public class PublicKeyFactory
}
else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
{
- X962Parameters params = new X962Parameters(
- (ASN1Primitive)algId.getParameters());
+ X962Parameters params = X962Parameters.getInstance(algId.getParameters());
X9ECParameters x9;
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
- x9 = X962NamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = SECNamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = NISTNamedCurves.getByOID(oid);
-
- if (x9 == null)
- {
- x9 = TeleTrusTNamedCurves.getByOID(oid);
- }
- }
- }
+ x9 = ECNamedCurveTable.getByOID(oid);
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/util/package.html
deleted file mode 100644
index 787b892..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Some general utility/conversion classes.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/i18n/LocaleString.java b/bcprov/src/main/java/org/bouncycastle/i18n/LocaleString.java
index b9e2232..ab898a9 100644
--- a/bcprov/src/main/java/org/bouncycastle/i18n/LocaleString.java
+++ b/bcprov/src/main/java/org/bouncycastle/i18n/LocaleString.java
@@ -15,6 +15,12 @@ public class LocaleString extends LocalizedMessage
{
super(resource, id, encoding);
}
+
+ public LocaleString(String resource, String id, String encoding, Object[] arguments)
+ throws NullPointerException, UnsupportedEncodingException
+ {
+ super(resource, id, encoding, arguments);
+ }
public String getLocaleString(Locale locale)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java
new file mode 100644
index 0000000..d7677f3
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/JcaJceUtils.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.jcajce;
+
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Primitive;
+
+public class JcaJceUtils
+{
+ private JcaJceUtils()
+ {
+
+ }
+
+ /**
+ * Extract an ASN.1 encodable from an AlgorithmParameters object.
+ *
+ * @param params the object to get the encoding used to create the return value.
+ * @return an ASN.1 object representing the primitives making up the params parameter.
+ * @throws IOException if an encoding cannot be extracted.
+ */
+ public static ASN1Encodable extractParameters(AlgorithmParameters params)
+ throws IOException
+ {
+ // we try ASN.1 explicitly first just in case and then role back to the default.
+ ASN1Encodable asn1Params;
+ try
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
+ }
+ catch (Exception ex)
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded());
+ }
+
+ return asn1Params;
+ }
+
+ public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams)
+ throws IOException
+ {
+ // we try ASN.1 explicitly first just in case and then role back to the default.
+ try
+ {
+ params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1");
+ }
+ catch (Exception ex)
+ {
+ params.init(sParams.toASN1Primitive().getEncoded());
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/io/CipherInputStream.java b/bcprov/src/main/java/org/bouncycastle/jcajce/io/CipherInputStream.java
new file mode 100644
index 0000000..84291ba
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/io/CipherInputStream.java
@@ -0,0 +1,217 @@
+package org.bouncycastle.jcajce.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+
+import org.bouncycastle.crypto.io.InvalidCipherTextIOException;
+
+/**
+ * A CipherInputStream is composed of an InputStream and a cipher so that read() methods return data
+ * that are read in from the underlying InputStream but have been additionally processed by the
+ * Cipher. The cipher must be fully initialized before being used by a CipherInputStream.
+ * <p/>
+ * For example, if the Cipher is initialized for decryption, the CipherInputStream will attempt to
+ * read in data and decrypt them, before returning the decrypted data.
+ * <p/>
+ * This is a reimplementation of {@link javax.crypto.CipherInputStream} that is safe for use with
+ * AEAD block ciphers, and does not silently catch {@link BadPaddingException} and
+ * {@link IllegalBlockSizeException} errors. Any errors that occur during {@link Cipher#doFinal()
+ * finalisation} are rethrown wrapped in an {@link InvalidCipherTextIOException}.
+ */
+public class CipherInputStream
+ extends FilterInputStream
+{
+ private final Cipher cipher;
+ private final byte[] inputBuffer = new byte[512];
+ private boolean finalized = false;
+ private byte[] buf;
+ private int maxBuf;
+ private int bufOff;
+
+ /**
+ * Constructs a CipherInputStream from an InputStream and an initialised Cipher.
+ */
+ public CipherInputStream(InputStream input, Cipher cipher)
+ {
+ super(input);
+ this.cipher = cipher;
+ }
+
+ /**
+ * Read data from underlying stream and process with cipher until end of stream or some data is
+ * available after cipher processing.
+ *
+ * @return -1 to indicate end of stream, or the number of bytes (> 0) available.
+ */
+ private int nextChunk()
+ throws IOException
+ {
+ if (finalized)
+ {
+ return -1;
+ }
+
+ bufOff = 0;
+ maxBuf = 0;
+
+ // Keep reading until EOF or cipher processing produces data
+ while (maxBuf == 0)
+ {
+ int read = in.read(inputBuffer);
+ if (read == -1)
+ {
+ buf = finaliseCipher();
+ if ((buf == null) || (buf.length == 0))
+ {
+ return -1;
+ }
+ maxBuf = buf.length;
+ return maxBuf;
+ }
+
+ buf = cipher.update(inputBuffer, 0, read);
+ if (buf != null)
+ {
+ maxBuf = buf.length;
+ }
+ }
+ return maxBuf;
+ }
+
+ private byte[] finaliseCipher()
+ throws InvalidCipherTextIOException
+ {
+ try
+ {
+ finalized = true;
+ return cipher.doFinal();
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new InvalidCipherTextIOException("Error finalising cipher", e);
+ }
+ }
+
+ /**
+ * Reads data from the underlying stream and processes it with the cipher until the cipher
+ * outputs data, and returns the next available byte.
+ * <p/>
+ * If the underlying stream is exhausted by this call, the cipher will be finalised.
+ *
+ * @throws IOException if there was an error closing the input stream.
+ * @throws InvalidCipherTextIOException if the data read from the stream was invalid ciphertext
+ * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails).
+ */
+ public int read()
+ throws IOException
+ {
+ if (bufOff >= maxBuf)
+ {
+ if (nextChunk() < 0)
+ {
+ return -1;
+ }
+ }
+
+ return buf[bufOff++] & 0xff;
+ }
+
+ /**
+ * Reads data from the underlying stream and processes it with the cipher until the cipher
+ * outputs data, and then returns up to <code>len</code> bytes in the provided array.
+ * <p/>
+ * If the underlying stream is exhausted by this call, the cipher will be finalised.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in the destination array <code>b</code>
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or <code>-1</code> if there is no
+ * more data because the end of the stream has been reached.
+ * @throws IOException if there was an error closing the input stream.
+ * @throws InvalidCipherTextIOException if the data read from the stream was invalid ciphertext
+ * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails).
+ */
+ public int read(byte[] b, int off, int len)
+ throws IOException
+ {
+ if (bufOff >= maxBuf)
+ {
+ if (nextChunk() < 0)
+ {
+ return -1;
+ }
+ }
+
+ int toSupply = Math.min(len, available());
+ System.arraycopy(buf, bufOff, b, off, toSupply);
+ bufOff += toSupply;
+ return toSupply;
+ }
+
+ public long skip(long n)
+ throws IOException
+ {
+ if (n <= 0)
+ {
+ return 0;
+ }
+
+ int skip = (int)Math.min(n, available());
+ bufOff += skip;
+ return skip;
+ }
+
+ public int available()
+ throws IOException
+ {
+ return maxBuf - bufOff;
+ }
+
+ /**
+ * Closes the underlying input stream, and then finalises the processing of the data by the
+ * cipher.
+ *
+ * @throws IOException if there was an error closing the input stream.
+ * @throws InvalidCipherTextIOException if the data read from the stream was invalid ciphertext
+ * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails).
+ */
+ public void close()
+ throws IOException
+ {
+ try
+ {
+ in.close();
+ }
+ finally
+ {
+ if (!finalized)
+ {
+ // Reset the cipher, discarding any data buffered in it
+ // Errors in cipher finalisation trump I/O error closing input
+ finaliseCipher();
+ }
+ }
+ maxBuf = bufOff = 0;
+ }
+
+ public void mark(int readlimit)
+ {
+ }
+
+ public void reset()
+ throws IOException
+ {
+ }
+
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/io/CipherOutputStream.java b/bcprov/src/main/java/org/bouncycastle/jcajce/io/CipherOutputStream.java
new file mode 100644
index 0000000..814b339
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/io/CipherOutputStream.java
@@ -0,0 +1,147 @@
+package org.bouncycastle.jcajce.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.GeneralSecurityException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+
+import org.bouncycastle.crypto.io.InvalidCipherTextIOException;
+
+/**
+ * A CipherOutputStream is composed of an OutputStream and a cipher so that write() methods process
+ * the written data with the cipher, and the output of the cipher is in turn written to the
+ * underlying OutputStream. The cipher must be fully initialized before being used by a
+ * CipherInputStream.
+ * <p/>
+ * For example, if the cipher is initialized for encryption, the CipherOutputStream will encrypt the
+ * data before writing the encrypted data to the underlying stream.
+ * <p/>
+ * This is a reimplementation of {@link javax.crypto.CipherOutputStream} that is safe for use with
+ * AEAD block ciphers, and does not silently catch {@link BadPaddingException} and
+ * {@link IllegalBlockSizeException} errors. Any errors that occur during {@link Cipher#doFinal()
+ * finalisation} are rethrown wrapped in an {@link InvalidCipherTextIOException}.
+ */
+public class CipherOutputStream
+ extends FilterOutputStream
+{
+ private final Cipher cipher;
+ private final byte[] oneByte = new byte[1];
+
+ /**
+ * Constructs a CipherOutputStream from an OutputStream and a Cipher.
+ */
+ public CipherOutputStream(OutputStream output, Cipher cipher)
+ {
+ super(output);
+ this.cipher = cipher;
+ }
+
+ /**
+ * Writes the specified byte to this output stream.
+ *
+ * @param b the <code>byte</code>.
+ * @throws java.io.IOException if an I/O error occurs.
+ */
+ public void write(int b)
+ throws IOException
+ {
+ oneByte[0] = (byte)b;
+ write(oneByte, 0, 1);
+ }
+
+ /**
+ * Writes <code>len</code> bytes from the specified byte array starting at offset
+ * <code>off</code> to this output stream.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @throws java.io.IOException if an I/O error occurs.
+ */
+ public void write(byte[] b, int off, int len)
+ throws IOException
+ {
+ byte[] outData = cipher.update(b, off, len);
+ if (outData != null)
+ {
+ out.write(outData);
+ }
+ }
+
+ /**
+ * Flushes this output stream by forcing any buffered output bytes that have already been
+ * processed by the encapsulated cipher object to be written out.
+ * <p/>
+ * <p/>
+ * Any bytes buffered by the encapsulated cipher and waiting to be processed by it will not be
+ * written out. For example, if the encapsulated cipher is a block cipher, and the total number
+ * of bytes written using one of the <code>write</code> methods is less than the cipher's block
+ * size, no bytes will be written out.
+ *
+ * @throws java.io.IOException if an I/O error occurs.
+ */
+ public void flush()
+ throws IOException
+ {
+ out.flush();
+ }
+
+ /**
+ * Closes this output stream and releases any system resources associated with this stream.
+ * <p/>
+ * This method invokes the <code>doFinal</code> method of the encapsulated cipher object, which
+ * causes any bytes buffered by the encapsulated cipher to be processed. The result is written
+ * out by calling the <code>flush</code> method of this output stream.
+ * <p/>
+ * This method resets the encapsulated cipher object to its initial state and calls the
+ * <code>close</code> method of the underlying output stream.
+ *
+ * @throws java.io.IOException if an I/O error occurs.
+ * @throws InvalidCipherTextIOException if the data written to this stream was invalid
+ * ciphertext (e.g. the cipher is an AEAD cipher and the ciphertext tag check
+ * fails).
+ */
+ public void close()
+ throws IOException
+ {
+ IOException error = null;
+ try
+ {
+ byte[] outData = cipher.doFinal();
+ if (outData != null)
+ {
+ out.write(outData);
+ }
+ }
+ catch (GeneralSecurityException e)
+ {
+ error = new InvalidCipherTextIOException("Error during cipher finalisation", e);
+ }
+ catch (Exception e)
+ {
+ error = new IOException("Error closing stream: " + e);
+ }
+ try
+ {
+ flush();
+ out.close();
+ }
+ catch (IOException e)
+ {
+ // Invalid ciphertext takes precedence over close error
+ if (error == null)
+ {
+ error = e;
+ }
+ }
+ if (error != null)
+ {
+ throw error;
+ }
+ }
+
+}
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 3e16254..2efffbf 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
@@ -32,6 +32,13 @@ public class DSA
provider.addAlgorithm("Alg.Alias.Signature.RAWDSA", "NONEWITHDSA");
+ provider.addAlgorithm("Signature.DETDSA", PREFIX + "DSASigner$detDSA");
+ provider.addAlgorithm("Signature.SHA1WITHDETDSA", PREFIX + "DSASigner$detDSA");
+ provider.addAlgorithm("Signature.SHA224WITHDETDSA", PREFIX + "DSASigner$detDSA224");
+ provider.addAlgorithm("Signature.SHA256WITHDETDSA", PREFIX + "DSASigner$detDSA256");
+ provider.addAlgorithm("Signature.SHA384WITHDETDSA", PREFIX + "DSASigner$detDSA384");
+ provider.addAlgorithm("Signature.SHA512WITHDETDSA", PREFIX + "DSASigner$detDSA512");
+
addSignatureAlgorithm(provider, "SHA224", "DSA", PREFIX + "DSASigner$dsa224", NISTObjectIdentifiers.dsa_with_sha224);
addSignatureAlgorithm(provider, "SHA256", "DSA", PREFIX + "DSASigner$dsa256", NISTObjectIdentifiers.dsa_with_sha256);
addSignatureAlgorithm(provider, "SHA384", "DSA", PREFIX + "DSASigner$dsa384", NISTObjectIdentifiers.dsa_with_sha384);
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 4c2ca28..d06e05c 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
@@ -67,6 +67,13 @@ public class EC
provider.addAlgorithm("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
provider.addAlgorithm("Alg.Alias.Signature." + TeleTrusTObjectIdentifiers.ecSignWithSha1, "ECDSA");
+ provider.addAlgorithm("Signature.DETECDSA", PREFIX + "SignatureSpi$ecDetDSA");
+ provider.addAlgorithm("Signature.SHA1WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA");
+ provider.addAlgorithm("Signature.SHA224WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA224");
+ provider.addAlgorithm("Signature.SHA256WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA256");
+ provider.addAlgorithm("Signature.SHA384WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA384");
+ provider.addAlgorithm("Signature.SHA512WITHDETECDSA", PREFIX + "SignatureSpi$ecDetDSA512");
+
addSignatureAlgorithm(provider, "SHA224", "ECDSA", PREFIX + "SignatureSpi$ecDSA224", X9ObjectIdentifiers.ecdsa_with_SHA224);
addSignatureAlgorithm(provider, "SHA256", "ECDSA", PREFIX + "SignatureSpi$ecDSA256", X9ObjectIdentifiers.ecdsa_with_SHA256);
addSignatureAlgorithm(provider, "SHA384", "ECDSA", PREFIX + "SignatureSpi$ecDSA384", X9ObjectIdentifiers.ecdsa_with_SHA384);
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 c9462a6..f2b5314 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
@@ -50,17 +50,34 @@ public class KeyAgreementSpi
private byte[] bigIntToBytes(
BigInteger r)
{
+ //
+ // RFC 2631 (2.1.2) specifies that the secret should be padded with leading zeros if necessary
+ // must be the same length as p
+ //
+ int expectedLength = (p.bitLength() + 7) / 8;
+
byte[] tmp = r.toByteArray();
-
- if (tmp[0] == 0)
+
+ if (tmp.length == expectedLength)
+ {
+ return tmp;
+ }
+
+ if (tmp[0] == 0 && tmp.length == expectedLength + 1)
{
- byte[] ntmp = new byte[tmp.length - 1];
+ byte[] rv = new byte[tmp.length - 1];
- System.arraycopy(tmp, 1, ntmp, 0, ntmp.length);
- return ntmp;
+ System.arraycopy(tmp, 1, rv, 0, rv.length);
+ return rv;
}
-
- return tmp;
+
+ // tmp must be shorter than expectedLength
+ // pad to the left with zeros.
+ byte[] rv = new byte[expectedLength];
+
+ System.arraycopy(tmp, 0, rv, rv.length - tmp.length, tmp.length);
+
+ return rv;
}
protected Key engineDoPhase(
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 ef12b4f..ade49b3 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
@@ -29,6 +29,7 @@ import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
public class DSASigner
extends SignatureSpi
@@ -220,6 +221,15 @@ public class DSASigner
}
}
+ static public class detDSA
+ extends DSASigner
+ {
+ public detDSA()
+ {
+ super(new SHA1Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA1Digest())));
+ }
+ }
+
static public class dsa224
extends DSASigner
{
@@ -228,7 +238,16 @@ public class DSASigner
super(new SHA224Digest(), new org.bouncycastle.crypto.signers.DSASigner());
}
}
-
+
+ static public class detDSA224
+ extends DSASigner
+ {
+ public detDSA224()
+ {
+ super(new SHA224Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA224Digest())));
+ }
+ }
+
static public class dsa256
extends DSASigner
{
@@ -237,7 +256,16 @@ public class DSASigner
super(new SHA256Digest(), new org.bouncycastle.crypto.signers.DSASigner());
}
}
-
+
+ static public class detDSA256
+ extends DSASigner
+ {
+ public detDSA256()
+ {
+ super(new SHA256Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA256Digest())));
+ }
+ }
+
static public class dsa384
extends DSASigner
{
@@ -246,7 +274,16 @@ public class DSASigner
super(new SHA384Digest(), new org.bouncycastle.crypto.signers.DSASigner());
}
}
-
+
+ static public class detDSA384
+ extends DSASigner
+ {
+ public detDSA384()
+ {
+ super(new SHA384Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA384Digest())));
+ }
+ }
+
static public class dsa512
extends DSASigner
{
@@ -256,6 +293,15 @@ public class DSASigner
}
}
+ static public class detDSA512
+ extends DSASigner
+ {
+ public detDSA512()
+ {
+ super(new SHA512Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA512Digest())));
+ }
+ }
+
static public class noneDSA
extends DSASigner
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PrivateKey.java
index 56fe741..9b7e797 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PrivateKey.java
@@ -119,8 +119,8 @@ public class BCDSTU4145PrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -150,8 +150,8 @@ public class BCDSTU4145PrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -162,8 +162,8 @@ public class BCDSTU4145PrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
spec.getN(),
spec.getH().intValue());
}
@@ -206,8 +206,8 @@ public class BCDSTU4145PrivateKey
oid.getId(),
ellipticCurve,
new ECPoint(
- gParam.getG().getX().toBigInteger(),
- gParam.getG().getY().toBigInteger()),
+ gParam.getG().getAffineXCoord().toBigInteger(),
+ gParam.getG().getAffineYCoord().toBigInteger()),
gParam.getN(),
gParam.getH());
}
@@ -219,8 +219,8 @@ public class BCDSTU4145PrivateKey
ECUtil.getCurveName(oid),
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH());
}
@@ -237,8 +237,8 @@ public class BCDSTU4145PrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH().intValue());
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PublicKey.java
index a060ae6..c641ee9 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PublicKey.java
@@ -16,7 +16,6 @@ import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.ua.DSTU4145BinaryField;
import org.bouncycastle.asn1.ua.DSTU4145ECBinary;
@@ -28,13 +27,9 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ECPoint;
-import org.bouncycastle.asn1.x9.X9IntegerConverter;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
-import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.jce.interfaces.ECPointEncoder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -88,7 +83,7 @@ public class BCDSTU4145PublicKey
{
org.bouncycastle.jce.spec.ECParameterSpec s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
- q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger(), false);
+ q = s.getCurve().createPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
}
this.ecSpec = null;
}
@@ -157,8 +152,8 @@ public class BCDSTU4145PublicKey
return new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -191,155 +186,79 @@ public class BCDSTU4145PublicKey
private void populateFromPubKeyInfo(SubjectPublicKeyInfo info)
{
- if (info.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145be) || info.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
- {
- DERBitString bits = info.getPublicKeyData();
- ASN1OctetString key;
- this.algorithm = "DSTU4145";
-
- try
- {
- key = (ASN1OctetString)ASN1Primitive.fromByteArray(bits.getBytes());
- }
- catch (IOException ex)
- {
- throw new IllegalArgumentException("error recovering public key");
- }
-
- byte[] keyEnc = key.getOctets();
-
- if (info.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
- {
- reverseBytes(keyEnc);
- }
-
- dstuParams = DSTU4145Params.getInstance((ASN1Sequence)info.getAlgorithm().getParameters());
+ DERBitString bits = info.getPublicKeyData();
+ ASN1OctetString key;
+ this.algorithm = "DSTU4145";
- //ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()));
- org.bouncycastle.jce.spec.ECParameterSpec spec = null;
- if (dstuParams.isNamedCurve())
- {
- ASN1ObjectIdentifier curveOid = dstuParams.getNamedCurve();
- ECDomainParameters ecP = DSTU4145NamedCurves.getByOID(curveOid);
+ try
+ {
+ key = (ASN1OctetString)ASN1Primitive.fromByteArray(bits.getBytes());
+ }
+ catch (IOException ex)
+ {
+ throw new IllegalArgumentException("error recovering public key");
+ }
- spec = new ECNamedCurveParameterSpec(curveOid.getId(), ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed());
- }
- else
- {
- DSTU4145ECBinary binary = dstuParams.getECBinary();
- byte[] b_bytes = binary.getB();
- if (info.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 (info.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
- {
- reverseBytes(g_bytes);
- }
- spec = new org.bouncycastle.jce.spec.ECParameterSpec(curve, DSTU4145PointEncoder.decodePoint(curve, g_bytes), binary.getN());
- }
+ byte[] keyEnc = key.getOctets();
- ECCurve curve = spec.getCurve();
- EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
+ if (info.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
+ {
+ reverseBytes(keyEnc);
+ }
- //this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y), false);
- this.q = DSTU4145PointEncoder.decodePoint(curve, keyEnc);
+ dstuParams = DSTU4145Params.getInstance((ASN1Sequence)info.getAlgorithm().getParameters());
- if (dstuParams.isNamedCurve())
- {
- ecSpec = new ECNamedCurveSpec(
- dstuParams.getNamedCurve().getId(),
- ellipticCurve,
- new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
- spec.getN(), spec.getH());
- }
- else
- {
- ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
- spec.getN(), spec.getH().intValue());
- }
+ //ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()));
+ org.bouncycastle.jce.spec.ECParameterSpec spec = null;
+ if (dstuParams.isNamedCurve())
+ {
+ ASN1ObjectIdentifier curveOid = dstuParams.getNamedCurve();
+ ECDomainParameters ecP = DSTU4145NamedCurves.getByOID(curveOid);
+ spec = new ECNamedCurveParameterSpec(curveOid.getId(), ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed());
}
else
{
- X962Parameters params = new X962Parameters((ASN1Primitive)info.getAlgorithm().getParameters());
- ECCurve curve;
- EllipticCurve ellipticCurve;
-
- if (params.isNamedCurve())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
- X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
-
- curve = ecP.getCurve();
- ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
-
- ecSpec = new ECNamedCurveSpec(
- ECUtil.getCurveName(oid),
- ellipticCurve,
- new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
- ecP.getN(),
- ecP.getH());
- }
- else if (params.isImplicitlyCA())
+ DSTU4145ECBinary binary = dstuParams.getECBinary();
+ byte[] b_bytes = binary.getB();
+ if (info.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
{
- ecSpec = null;
- curve = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa().getCurve();
+ reverseBytes(b_bytes);
}
- else
+ 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 (info.getAlgorithm().getAlgorithm().equals(UAObjectIdentifiers.dstu4145le))
{
- X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters());
-
- curve = ecP.getCurve();
- ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
-
- this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
- ecP.getN(),
- ecP.getH().intValue());
+ reverseBytes(g_bytes);
}
+ spec = new org.bouncycastle.jce.spec.ECParameterSpec(curve, DSTU4145PointEncoder.decodePoint(curve, g_bytes), binary.getN());
+ }
- DERBitString bits = info.getPublicKeyData();
- byte[] data = bits.getBytes();
- ASN1OctetString key = new DEROctetString(data);
+ ECCurve curve = spec.getCurve();
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
- //
- // extra octet string - one of our old certs...
- //
- if (data[0] == 0x04 && data[1] == data.length - 2
- && (data[2] == 0x02 || data[2] == 0x03))
- {
- int qLength = new X9IntegerConverter().getByteLength(curve);
-
- if (qLength >= data.length - 3)
- {
- try
- {
- key = (ASN1OctetString)ASN1Primitive.fromByteArray(data);
- }
- catch (IOException ex)
- {
- throw new IllegalArgumentException("error recovering public key");
- }
- }
- }
- X9ECPoint derQ = new X9ECPoint(curve, key);
+ //this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y), false);
+ this.q = DSTU4145PointEncoder.decodePoint(curve, keyEnc);
- this.q = derQ.getPoint();
+ if (dstuParams.isNamedCurve())
+ {
+ ecSpec = new ECNamedCurveSpec(
+ dstuParams.getNamedCurve().getId(),
+ ellipticCurve,
+ new ECPoint(
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
+ spec.getN(), spec.getH());
+ }
+ else
+ {
+ ecSpec = new ECParameterSpec(
+ ellipticCurve,
+ new ECPoint(
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
+ spec.getN(), spec.getH().intValue());
}
}
@@ -370,61 +289,18 @@ public class BCDSTU4145PublicKey
ASN1Encodable params;
SubjectPublicKeyInfo info;
- if (algorithm.equals("DSTU4145"))
+ if (dstuParams != null)
{
- if (dstuParams != null)
- {
- params = dstuParams;
- }
- else
- {
- if (ecSpec instanceof ECNamedCurveSpec)
- {
- params = new DSTU4145Params(new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()));
- }
- else
- { // strictly speaking this may not be applicable...
- ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
-
- X9ECParameters ecP = new X9ECParameters(
- curve,
- EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),
- ecSpec.getOrder(),
- BigInteger.valueOf(ecSpec.getCofactor()),
- ecSpec.getCurve().getSeed());
-
- params = new X962Parameters(ecP);
- }
- }
-
- byte[] encKey = DSTU4145PointEncoder.encodePoint(this.q);
-
- try
- {
- info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(UAObjectIdentifiers.dstu4145be, params), new DEROctetString(encKey));
- }
- catch (IOException e)
- {
- return null;
- }
+ params = dstuParams;
}
else
{
if (ecSpec instanceof ECNamedCurveSpec)
{
- ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
- if (curveOid == null)
- {
- curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
- }
- params = new X962Parameters(curveOid);
- }
- else if (ecSpec == null)
- {
- params = new X962Parameters(DERNull.INSTANCE);
+ params = new DSTU4145Params(new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()));
}
else
- {
+ { // strictly speaking this may not be applicable...
ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
X9ECParameters ecP = new X9ECParameters(
@@ -436,12 +312,17 @@ public class BCDSTU4145PublicKey
params = new X962Parameters(ecP);
}
+ }
- ECCurve curve = this.engineGetQ().getCurve();
- ASN1OctetString p = (ASN1OctetString)
- new X9ECPoint(curve.createPoint(this.getQ().getX().toBigInteger(), this.getQ().getY().toBigInteger(), withCompression)).toASN1Primitive();
+ byte[] encKey = DSTU4145PointEncoder.encodePoint(this.q);
- info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
+ try
+ {
+ info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(UAObjectIdentifiers.dstu4145be, params), new DEROctetString(encKey));
+ }
+ catch (IOException e)
+ {
+ return null;
}
return KeyUtil.getEncodedSubjectPublicKeyInfo(info);
@@ -464,7 +345,7 @@ public class BCDSTU4145PublicKey
public ECPoint getW()
{
- return new ECPoint(q.getX().toBigInteger(), q.getY().toBigInteger());
+ return new ECPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
}
public org.bouncycastle.math.ec.ECPoint getQ()
@@ -473,11 +354,11 @@ public class BCDSTU4145PublicKey
{
if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp)
{
- return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord());
}
else
{
- return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord());
}
}
@@ -505,8 +386,8 @@ public class BCDSTU4145PublicKey
String nl = System.getProperty("line.separator");
buf.append("EC Public Key").append(nl);
- buf.append(" X: ").append(this.q.getX().toBigInteger().toString(16)).append(nl);
- buf.append(" Y: ").append(this.q.getY().toBigInteger().toString(16)).append(nl);
+ buf.append(" X: ").append(this.q.getAffineXCoord().toBigInteger().toString(16)).append(nl);
+ buf.append(" Y: ").append(this.q.getAffineYCoord().toBigInteger().toString(16)).append(nl);
return buf.toString();
}
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 ac04d3c..45d5b08 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
@@ -13,14 +13,11 @@ import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
-import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
@@ -138,8 +135,8 @@ public class BCECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -171,22 +168,16 @@ public class BCECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
else
{
EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed());
-
- this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
- spec.getN(),
- spec.getH().intValue());
+
+ this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec);
}
publicKey = getPublicKeyDetails(pubKey);
@@ -223,34 +214,16 @@ public class BCECPrivateKey
{
ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
-
- if (ecP == null) // GOST Curve
- {
- ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid);
- EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed());
-
- ecSpec = new ECNamedCurveSpec(
- ECGOST3410NamedCurves.getName(oid),
- ellipticCurve,
- new ECPoint(
- gParam.getG().getX().toBigInteger(),
- gParam.getG().getY().toBigInteger()),
- gParam.getN(),
- gParam.getH());
- }
- else
- {
- EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
-
- ecSpec = new ECNamedCurveSpec(
- ECUtil.getCurveName(oid),
- ellipticCurve,
- new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
- ecP.getN(),
- ecP.getH());
- }
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
+
+ ecSpec = new ECNamedCurveSpec(
+ ECUtil.getCurveName(oid),
+ ellipticCurve,
+ new ECPoint(
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
+ ecP.getN(),
+ ecP.getH());
}
else if (params.isImplicitlyCA())
{
@@ -264,16 +237,16 @@ public class BCECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH().intValue());
}
ASN1Encodable privKey = info.parsePrivateKey();
- if (privKey instanceof DERInteger)
+ if (privKey instanceof ASN1Integer)
{
- DERInteger derD = DERInteger.getInstance(privKey);
+ ASN1Integer derD = ASN1Integer.getInstance(privKey);
this.d = derD.getValue();
}
@@ -313,11 +286,12 @@ public class BCECPrivateKey
if (ecSpec instanceof ECNamedCurveSpec)
{
- DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
+ ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
if (curveOid == null) // guess it's the OID
{
- curveOid = new DERObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
+ curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
}
+
params = new X962Parameters(curveOid);
}
else if (ecSpec == null)
@@ -352,15 +326,7 @@ public class BCECPrivateKey
try
{
- if (algorithm.equals("ECGOST3410"))
- {
- info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.toASN1Primitive()), keyStructure.toASN1Primitive());
- }
- else
- {
-
- info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.toASN1Primitive()), keyStructure.toASN1Primitive());
- }
+ info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), keyStructure);
return info.getEncoded(ASN1Encoding.DER);
}
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 2b61727..0eaae1d 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
@@ -90,7 +90,7 @@ public class BCECPublicKey
{
org.bouncycastle.jce.spec.ECParameterSpec s = configuration.getEcImplicitlyCa();
- q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger(), false);
+ q = s.getCurve().createPoint(q.getXCoord().toBigInteger(), q.getYCoord().toBigInteger(), false);
}
this.ecSpec = null;
}
@@ -188,8 +188,8 @@ public class BCECPublicKey
return new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -212,8 +212,8 @@ public class BCECPublicKey
ECUtil.getCurveName(oid),
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH());
}
@@ -232,8 +232,8 @@ public class BCECPublicKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH().intValue());
}
@@ -310,8 +310,19 @@ public class BCECPublicKey
}
ECCurve curve = this.engineGetQ().getCurve();
- ASN1OctetString p = (ASN1OctetString)
- new X9ECPoint(curve.createPoint(this.getQ().getX().toBigInteger(), this.getQ().getY().toBigInteger(), withCompression)).toASN1Primitive();
+ ASN1OctetString p;
+
+ // stored curve is null if ImplicitlyCa
+ if (ecSpec == null)
+ {
+ p = (ASN1OctetString)
+ new X9ECPoint(curve.createPoint(this.getQ().getXCoord().toBigInteger(), this.getQ().getYCoord().toBigInteger(), withCompression)).toASN1Primitive();
+ }
+ else
+ {
+ p = (ASN1OctetString)
+ new X9ECPoint(curve.createPoint(this.getQ().getAffineXCoord().toBigInteger(), this.getQ().getAffineYCoord().toBigInteger(), withCompression)).toASN1Primitive();
+ }
info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
@@ -351,7 +362,7 @@ public class BCECPublicKey
public ECPoint getW()
{
- return new ECPoint(q.getX().toBigInteger(), q.getY().toBigInteger());
+ return new ECPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
}
public org.bouncycastle.math.ec.ECPoint getQ()
@@ -360,11 +371,11 @@ public class BCECPublicKey
{
if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp)
{
- return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord());
}
else
{
- return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord());
}
}
@@ -392,8 +403,8 @@ public class BCECPublicKey
String nl = System.getProperty("line.separator");
buf.append("EC Public Key").append(nl);
- buf.append(" X: ").append(this.q.getX().toBigInteger().toString(16)).append(nl);
- buf.append(" Y: ").append(this.q.getY().toBigInteger().toString(16)).append(nl);
+ buf.append(" X: ").append(this.q.getAffineXCoord().toBigInteger().toString(16)).append(nl);
+ buf.append(" Y: ").append(this.q.getAffineYCoord().toBigInteger().toString(16)).append(nl);
return buf.toString();
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 c609d95..0556378 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
@@ -15,7 +15,7 @@ import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;
-import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x9.X9IntegerConverter;
@@ -76,7 +76,7 @@ public class KeyAgreementSpi
private byte[] bigIntToBytes(
BigInteger r)
{
- return converter.integerToBytes(r, converter.getByteLength(parameters.getG().getX()));
+ return converter.integerToBytes(r, converter.getByteLength(parameters.getG().getAffineXCoord()));
}
protected KeyAgreementSpi(
@@ -185,7 +185,7 @@ public class KeyAgreementSpi
int keySize = ((Integer)algorithms.get(algorithm)).intValue();
- DHKDFParameters params = new DHKDFParameters(new DERObjectIdentifier(algorithm), keySize, secret);
+ DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(algorithm), keySize, secret);
byte[] keyBytes = new byte[keySize / 8];
kdf.init(params);
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 5e1a8a3..f47f8a2 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
@@ -10,10 +10,7 @@ import java.security.spec.ECGenParameterSpec;
import java.util.Hashtable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
+import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
@@ -148,47 +145,23 @@ public abstract class KeyPairGeneratorSpi
curveName = ((ECNamedCurveGenParameterSpec)params).getName();
}
- X9ECParameters ecP = X962NamedCurves.getByName(curveName);
+ X9ECParameters ecP = ECNamedCurveTable.getByName(curveName);
if (ecP == null)
{
- ecP = SECNamedCurves.getByName(curveName);
- if (ecP == null)
+ // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug)
+ try
{
- ecP = NISTNamedCurves.getByName(curveName);
- }
- if (ecP == null)
- {
- ecP = TeleTrusTNamedCurves.getByName(curveName);
- }
- if (ecP == null)
- {
- // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug)
- try
+ ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(curveName);
+ ecP = ECNamedCurveTable.getByOID(oid);
+ if (ecP == null)
{
- ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(curveName);
- ecP = X962NamedCurves.getByOID(oid);
- if (ecP == null)
- {
- ecP = SECNamedCurves.getByOID(oid);
- }
- if (ecP == null)
- {
- ecP = NISTNamedCurves.getByOID(oid);
- }
- if (ecP == null)
- {
- ecP = TeleTrusTNamedCurves.getByOID(oid);
- }
- if (ecP == null)
- {
- throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName);
- }
- }
- catch (IllegalArgumentException ex)
- {
- throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
+ throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName);
}
}
+ catch (IllegalArgumentException ex)
+ {
+ throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
+ }
}
this.ecParams = new ECNamedCurveSpec(
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 29c50f4..e94746c 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
@@ -25,6 +25,7 @@ import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.ECNRSigner;
+import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
import org.bouncycastle.jcajce.provider.asymmetric.util.DSABase;
import org.bouncycastle.jcajce.provider.asymmetric.util.DSAEncoder;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
@@ -73,6 +74,15 @@ public class SignatureSpi
}
}
+ static public class ecDetDSA
+ extends SignatureSpi
+ {
+ public ecDetDSA()
+ {
+ super(new SHA1Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA1Digest())), new StdDSAEncoder());
+ }
+ }
+
static public class ecDSAnone
extends SignatureSpi
{
@@ -91,6 +101,15 @@ public class SignatureSpi
}
}
+ static public class ecDetDSA224
+ extends SignatureSpi
+ {
+ public ecDetDSA224()
+ {
+ super(new SHA224Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA224Digest())), new StdDSAEncoder());
+ }
+ }
+
static public class ecDSA256
extends SignatureSpi
{
@@ -100,6 +119,15 @@ public class SignatureSpi
}
}
+ static public class ecDetDSA256
+ extends SignatureSpi
+ {
+ public ecDetDSA256()
+ {
+ super(new SHA256Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())), new StdDSAEncoder());
+ }
+ }
+
static public class ecDSA384
extends SignatureSpi
{
@@ -109,6 +137,15 @@ public class SignatureSpi
}
}
+ static public class ecDetDSA384
+ extends SignatureSpi
+ {
+ public ecDetDSA384()
+ {
+ super(new SHA384Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA384Digest())), new StdDSAEncoder());
+ }
+ }
+
static public class ecDSA512
extends SignatureSpi
{
@@ -118,6 +155,15 @@ public class SignatureSpi
}
}
+ static public class ecDetDSA512
+ extends SignatureSpi
+ {
+ public ecDetDSA512()
+ {
+ super(new SHA512Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA512Digest())), new StdDSAEncoder());
+ }
+ }
+
static public class ecDSARipeMD160
extends SignatureSpi
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java
index 88d81c0..2b1c3fa 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java
@@ -14,27 +14,32 @@ import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
+import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
+import org.bouncycastle.jce.ECGOST3410NamedCurveTable;
import org.bouncycastle.jce.interfaces.ECPointEncoder;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.math.ec.ECCurve;
@@ -43,10 +48,11 @@ public class BCECGOST3410PrivateKey
{
static final long serialVersionUID = 7245981689601667138L;
- private String algorithm = "ECGOST3410";
- private boolean withCompression;
+ private String algorithm = "ECGOST3410";
+ private boolean withCompression;
- private transient BigInteger d;
+ private transient GOST3410PublicKeyAlgParameters gostParams;
+ private transient BigInteger d;
private transient ECParameterSpec ecSpec;
private transient DERBitString publicKey;
private transient PKCS12BagAttributeCarrierImpl attrCarrier = new PKCS12BagAttributeCarrierImpl();
@@ -99,6 +105,7 @@ public class BCECGOST3410PrivateKey
this.withCompression = key.withCompression;
this.attrCarrier = key.attrCarrier;
this.publicKey = key.publicKey;
+ this.gostParams = key.gostParams;
}
public BCECGOST3410PrivateKey(
@@ -107,7 +114,7 @@ public class BCECGOST3410PrivateKey
BCECGOST3410PublicKey pubKey,
ECParameterSpec spec)
{
- ECDomainParameters dp = params.getParameters();
+ ECDomainParameters dp = params.getParameters();
this.algorithm = algorithm;
this.d = params.getD();
@@ -117,18 +124,20 @@ public class BCECGOST3410PrivateKey
EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ new ECPoint(
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
+ dp.getN(),
+ dp.getH().intValue());
}
else
{
this.ecSpec = spec;
}
+ this.gostParams = pubKey.getGostParams();
+
publicKey = getPublicKeyDetails(pubKey);
}
@@ -138,7 +147,7 @@ public class BCECGOST3410PrivateKey
BCECGOST3410PublicKey pubKey,
org.bouncycastle.jce.spec.ECParameterSpec spec)
{
- ECDomainParameters dp = params.getParameters();
+ ECDomainParameters dp = params.getParameters();
this.algorithm = algorithm;
this.d = params.getD();
@@ -148,26 +157,28 @@ public class BCECGOST3410PrivateKey
EllipticCurve ellipticCurve = EC5Util.convertCurve(dp.getCurve(), dp.getSeed());
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ new ECPoint(
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
+ dp.getN(),
+ dp.getH().intValue());
}
else
{
EllipticCurve ellipticCurve = EC5Util.convertCurve(spec.getCurve(), spec.getSeed());
-
+
this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
- spec.getN(),
- spec.getH().intValue());
+ ellipticCurve,
+ new ECPoint(
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
+ spec.getN(),
+ spec.getH().intValue());
}
+ this.gostParams = pubKey.getGostParams();
+
publicKey = getPublicKeyDetails(pubKey);
}
@@ -190,72 +201,107 @@ public class BCECGOST3410PrivateKey
private void populateFromPrivKeyInfo(PrivateKeyInfo info)
throws IOException
{
- X962Parameters params = new X962Parameters((ASN1Primitive)info.getPrivateKeyAlgorithm().getParameters());
+ ASN1Primitive p = info.getPrivateKeyAlgorithm().getParameters().toASN1Primitive();
+
+ if (p instanceof ASN1Sequence && (ASN1Sequence.getInstance(p).size() == 2 || ASN1Sequence.getInstance(p).size() == 3))
+ {
+ gostParams = GOST3410PublicKeyAlgParameters.getInstance(info.getPrivateKeyAlgorithm().getParameters());
+
+ ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()));
- if (params.isNamedCurve())
+ ECCurve curve = spec.getCurve();
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
+
+ ecSpec = new ECNamedCurveSpec(
+ ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
+ ellipticCurve,
+ new ECPoint(
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
+ spec.getN(), spec.getH());
+
+ ASN1Encodable privKey = info.parsePrivateKey();
+
+ 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];
+ }
+
+ this.d = new BigInteger(1, dVal);
+ }
+ else
{
- ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
- X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
+ // for backwards compatibility
+ X962Parameters params = X962Parameters.getInstance(info.getPrivateKeyAlgorithm().getParameters());
- if (ecP == null) // GOST Curve
+ if (params.isNamedCurve())
{
- ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid);
- EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed());
+ ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
+ X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
- ecSpec = new ECNamedCurveSpec(
+ if (ecP == null) // GOST Curve
+ {
+ ECDomainParameters gParam = ECGOST3410NamedCurves.getByOID(oid);
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(gParam.getCurve(), gParam.getSeed());
+
+ ecSpec = new ECNamedCurveSpec(
ECGOST3410NamedCurves.getName(oid),
ellipticCurve,
new ECPoint(
- gParam.getG().getX().toBigInteger(),
- gParam.getG().getY().toBigInteger()),
+ gParam.getG().getAffineXCoord().toBigInteger(),
+ gParam.getG().getAffineYCoord().toBigInteger()),
gParam.getN(),
gParam.getH());
- }
- else
- {
- EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
+ }
+ else
+ {
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
- ecSpec = new ECNamedCurveSpec(
+ ecSpec = new ECNamedCurveSpec(
ECUtil.getCurveName(oid),
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH());
+ }
}
- }
- else if (params.isImplicitlyCA())
- {
- ecSpec = null;
- }
- else
- {
- X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters());
- EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
+ else if (params.isImplicitlyCA())
+ {
+ ecSpec = null;
+ }
+ else
+ {
+ X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters());
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP.getCurve(), ecP.getSeed());
- this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
- ecP.getN(),
- ecP.getH().intValue());
- }
+ this.ecSpec = new ECParameterSpec(
+ ellipticCurve,
+ new ECPoint(
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
+ ecP.getN(),
+ ecP.getH().intValue());
+ }
- ASN1Encodable privKey = info.parsePrivateKey();
- if (privKey instanceof DERInteger)
- {
- DERInteger derD = DERInteger.getInstance(privKey);
+ ASN1Encodable privKey = info.parsePrivateKey();
+ if (privKey instanceof DERInteger)
+ {
+ DERInteger derD = DERInteger.getInstance(privKey);
- this.d = derD.getValue();
- }
- else
- {
- org.bouncycastle.asn1.sec.ECPrivateKey ec = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(privKey);
+ this.d = derD.getValue();
+ }
+ else
+ {
+ org.bouncycastle.asn1.sec.ECPrivateKey ec = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(privKey);
- this.d = ec.getKey();
- this.publicKey = ec.getPublicKey();
+ this.d = ec.getKey();
+ this.publicKey = ec.getPublicKey();
+ }
}
}
@@ -282,64 +328,92 @@ public class BCECGOST3410PrivateKey
*/
public byte[] getEncoded()
{
- X962Parameters params;
-
- if (ecSpec instanceof ECNamedCurveSpec)
+ if (gostParams != null)
{
- DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
- if (curveOid == null) // guess it's the OID
+ byte[] encKey = new byte[32];
+
+ extractBytes(encKey, 0, this.getS());
+
+ try
{
- curveOid = new DERObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
+ PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, gostParams), new DEROctetString(encKey));
+
+ return info.getEncoded(ASN1Encoding.DER);
+ }
+ catch (IOException e)
+ {
+ return null;
}
- params = new X962Parameters(curveOid);
- }
- else if (ecSpec == null)
- {
- params = new X962Parameters(DERNull.INSTANCE);
}
else
{
- ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
+ X962Parameters params;
- X9ECParameters ecP = new X9ECParameters(
- curve,
- EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),
- ecSpec.getOrder(),
- BigInteger.valueOf(ecSpec.getCofactor()),
- ecSpec.getCurve().getSeed());
+ if (ecSpec instanceof ECNamedCurveSpec)
+ {
+ DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
+ if (curveOid == null) // guess it's the OID
+ {
+ curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
+ }
+ params = new X962Parameters(curveOid);
+ }
+ else if (ecSpec == null)
+ {
+ params = new X962Parameters(DERNull.INSTANCE);
+ }
+ else
+ {
+ ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
- params = new X962Parameters(ecP);
- }
-
- PrivateKeyInfo info;
- org.bouncycastle.asn1.sec.ECPrivateKey keyStructure;
+ X9ECParameters ecP = new X9ECParameters(
+ curve,
+ EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),
+ ecSpec.getOrder(),
+ BigInteger.valueOf(ecSpec.getCofactor()),
+ ecSpec.getCurve().getSeed());
- if (publicKey != null)
- {
- keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), publicKey, params);
- }
- else
- {
- keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), params);
- }
+ params = new X962Parameters(ecP);
+ }
- try
- {
- if (algorithm.equals("ECGOST3410"))
+ PrivateKeyInfo info;
+ org.bouncycastle.asn1.sec.ECPrivateKey keyStructure;
+
+ if (publicKey != null)
{
- info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.toASN1Primitive()), keyStructure.toASN1Primitive());
+ keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), publicKey, params);
}
else
{
+ keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), params);
+ }
+
+ try
+ {
+ info = new PrivateKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params.toASN1Primitive()), keyStructure.toASN1Primitive());
- info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.toASN1Primitive()), keyStructure.toASN1Primitive());
+ return info.getEncoded(ASN1Encoding.DER);
}
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+ }
- return info.getEncoded(ASN1Encoding.DER);
+ private void extractBytes(byte[] encKey, int offSet, BigInteger bI)
+ {
+ byte[] val = bI.toByteArray();
+ if (val.length < 32)
+ {
+ byte[] tmp = new byte[32];
+ System.arraycopy(val, 0, tmp, tmp.length - val.length, val.length);
+ val = tmp;
}
- catch (IOException e)
+
+ for (int i = 0; i != 32; i++)
{
- return null;
+ encKey[offSet + i] = val[val.length - 1 - i];
}
}
@@ -354,7 +428,7 @@ public class BCECGOST3410PrivateKey
{
return null;
}
-
+
return EC5Util.convertSpec(ecSpec, withCompression);
}
@@ -377,10 +451,10 @@ public class BCECGOST3410PrivateKey
{
return d;
}
-
+
public void setBagAttribute(
ASN1ObjectIdentifier oid,
- ASN1Encodable attribute)
+ ASN1Encodable attribute)
{
attrCarrier.setBagAttribute(oid, attribute);
}
@@ -398,7 +472,7 @@ public class BCECGOST3410PrivateKey
public void setPointFormat(String style)
{
- withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style));
+ withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style));
}
public boolean equals(Object o)
@@ -420,8 +494,8 @@ public class BCECGOST3410PrivateKey
public String toString()
{
- StringBuffer buf = new StringBuffer();
- String nl = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+ String nl = System.getProperty("line.separator");
buf.append("EC Private Key").append(nl);
buf.append(" S: ").append(this.d.toString(16)).append(nl);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java
index b7a1170..650855e 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java
@@ -11,12 +11,9 @@ import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
@@ -25,13 +22,9 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ECPoint;
-import org.bouncycastle.asn1.x9.X9IntegerConverter;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
-import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.jce.ECGOST3410NamedCurveTable;
import org.bouncycastle.jce.interfaces.ECPointEncoder;
@@ -45,12 +38,12 @@ public class BCECGOST3410PublicKey
{
static final long serialVersionUID = 7026240464295649314L;
- private String algorithm = "ECGOST3410";
- private boolean withCompression;
+ private String algorithm = "ECGOST3410";
+ private boolean withCompression;
private transient org.bouncycastle.math.ec.ECPoint q;
- private transient ECParameterSpec ecSpec;
- private transient GOST3410PublicKeyAlgParameters gostParams;
+ private transient ECParameterSpec ecSpec;
+ private transient GOST3410PublicKeyAlgParameters gostParams;
public BCECGOST3410PublicKey(
BCECGOST3410PublicKey key)
@@ -60,7 +53,7 @@ public class BCECGOST3410PublicKey
this.withCompression = key.withCompression;
this.gostParams = key.gostParams;
}
-
+
public BCECGOST3410PublicKey(
ECPublicKeySpec spec)
{
@@ -86,18 +79,18 @@ public class BCECGOST3410PublicKey
{
org.bouncycastle.jce.spec.ECParameterSpec s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
- q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger(), false);
- }
+ q = s.getCurve().createPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
+ }
this.ecSpec = null;
}
}
-
+
public BCECGOST3410PublicKey(
String algorithm,
ECPublicKeyParameters params,
ECParameterSpec spec)
{
- ECDomainParameters dp = params.getParameters();
+ ECDomainParameters dp = params.getParameters();
this.algorithm = algorithm;
this.q = params.getQ();
@@ -119,7 +112,7 @@ public class BCECGOST3410PublicKey
ECPublicKeyParameters params,
org.bouncycastle.jce.spec.ECParameterSpec spec)
{
- ECDomainParameters dp = params.getParameters();
+ ECDomainParameters dp = params.getParameters();
this.algorithm = algorithm;
this.q = params.getQ();
@@ -153,14 +146,14 @@ public class BCECGOST3410PublicKey
private ECParameterSpec createSpec(EllipticCurve ellipticCurve, ECDomainParameters dp)
{
return new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
- dp.getN(),
- dp.getH().intValue());
+ ellipticCurve,
+ new ECPoint(
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
+ dp.getN(),
+ dp.getH().intValue());
}
-
+
public BCECGOST3410PublicKey(
ECPublicKey key)
{
@@ -177,125 +170,49 @@ public class BCECGOST3410PublicKey
private void populateFromPubKeyInfo(SubjectPublicKeyInfo info)
{
- if (info.getAlgorithm().getAlgorithm().equals(CryptoProObjectIdentifiers.gostR3410_2001))
- {
- DERBitString bits = info.getPublicKeyData();
- ASN1OctetString key;
- this.algorithm = "ECGOST3410";
-
- try
- {
- key = (ASN1OctetString) ASN1Primitive.fromByteArray(bits.getBytes());
- }
- catch (IOException ex)
- {
- throw new IllegalArgumentException("error recovering public key");
- }
-
- byte[] keyEnc = key.getOctets();
- byte[] x = new byte[32];
- byte[] y = new byte[32];
-
- for (int i = 0; i != x.length; i++)
- {
- x[i] = keyEnc[32 - 1 - i];
- }
-
- for (int i = 0; i != y.length; i++)
- {
- y[i] = keyEnc[64 - 1 - i];
- }
-
- gostParams = new GOST3410PublicKeyAlgParameters((ASN1Sequence)info.getAlgorithm().getParameters());
-
- ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()));
-
- ECCurve curve = spec.getCurve();
- EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
+ DERBitString bits = info.getPublicKeyData();
+ ASN1OctetString key;
+ this.algorithm = "ECGOST3410";
- this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y), false);
+ try
+ {
+ key = (ASN1OctetString)ASN1Primitive.fromByteArray(bits.getBytes());
+ }
+ catch (IOException ex)
+ {
+ throw new IllegalArgumentException("error recovering public key");
+ }
- ecSpec = new ECNamedCurveSpec(
- ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
- ellipticCurve,
- new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
- spec.getN(), spec.getH());
+ 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];
}
- else
+
+ for (int i = 0; i != y.length; i++)
{
- X962Parameters params = new X962Parameters((ASN1Primitive)info.getAlgorithm().getParameters());
- ECCurve curve;
- EllipticCurve ellipticCurve;
+ y[i] = keyEnc[64 - 1 - i];
+ }
- if (params.isNamedCurve())
- {
- ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
- X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
-
- curve = ecP.getCurve();
- ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
-
- ecSpec = new ECNamedCurveSpec(
- ECUtil.getCurveName(oid),
- ellipticCurve,
- new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
- ecP.getN(),
- ecP.getH());
- }
- else if (params.isImplicitlyCA())
- {
- ecSpec = null;
- curve = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa().getCurve();
- }
- else
- {
- X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters());
-
- curve = ecP.getCurve();
- ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
-
- this.ecSpec = new ECParameterSpec(
- ellipticCurve,
- new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
- ecP.getN(),
- ecP.getH().intValue());
- }
+ gostParams = GOST3410PublicKeyAlgParameters.getInstance(info.getAlgorithm().getParameters());
- DERBitString bits = info.getPublicKeyData();
- byte[] data = bits.getBytes();
- ASN1OctetString key = new DEROctetString(data);
+ ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()));
- //
- // extra octet string - one of our old certs...
- //
- if (data[0] == 0x04 && data[1] == data.length - 2
- && (data[2] == 0x02 || data[2] == 0x03))
- {
- int qLength = new X9IntegerConverter().getByteLength(curve);
-
- if (qLength >= data.length - 3)
- {
- try
- {
- key = (ASN1OctetString) ASN1Primitive.fromByteArray(data);
- }
- catch (IOException ex)
- {
- throw new IllegalArgumentException("error recovering public key");
- }
- }
- }
- X9ECPoint derQ = new X9ECPoint(curve, key);
+ ECCurve curve = spec.getCurve();
+ EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
- this.q = derQ.getPoint();
- }
+ this.q = curve.createPoint(new BigInteger(1, x), new BigInteger(1, y));
+
+ ecSpec = new ECNamedCurveSpec(
+ ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
+ ellipticCurve,
+ new ECPoint(
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
+ spec.getN(), spec.getH());
}
public String getAlgorithm()
@@ -310,71 +227,23 @@ public class BCECGOST3410PublicKey
public byte[] getEncoded()
{
- ASN1Encodable params;
+ ASN1Encodable params;
SubjectPublicKeyInfo info;
- if (algorithm.equals("ECGOST3410"))
+ if (gostParams != null)
{
- if (gostParams != null)
- {
- params = gostParams;
- }
- else
- {
- if (ecSpec instanceof ECNamedCurveSpec)
- {
- params = new GOST3410PublicKeyAlgParameters(
- ECGOST3410NamedCurves.getOID(((ECNamedCurveSpec)ecSpec).getName()),
- CryptoProObjectIdentifiers.gostR3411_94_CryptoProParamSet);
- }
- else
- { // strictly speaking this may not be applicable...
- ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
-
- X9ECParameters ecP = new X9ECParameters(
- curve,
- EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression),
- ecSpec.getOrder(),
- BigInteger.valueOf(ecSpec.getCofactor()),
- ecSpec.getCurve().getSeed());
-
- params = new X962Parameters(ecP);
- }
- }
-
- BigInteger bX = this.q.getX().toBigInteger();
- BigInteger bY = this.q.getY().toBigInteger();
- byte[] encKey = new byte[64];
-
- extractBytes(encKey, 0, bX);
- extractBytes(encKey, 32, bY);
-
- try
- {
- info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params), new DEROctetString(encKey));
- }
- catch (IOException e)
- {
- return null;
- }
+ params = gostParams;
}
else
{
if (ecSpec instanceof ECNamedCurveSpec)
{
- ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName());
- if (curveOid == null)
- {
- curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName());
- }
- params = new X962Parameters(curveOid);
- }
- else if (ecSpec == null)
- {
- params = new X962Parameters(DERNull.INSTANCE);
+ params = new GOST3410PublicKeyAlgParameters(
+ ECGOST3410NamedCurves.getOID(((ECNamedCurveSpec)ecSpec).getName()),
+ CryptoProObjectIdentifiers.gostR3411_94_CryptoProParamSet);
}
else
- {
+ { // strictly speaking this may not be applicable...
ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
X9ECParameters ecP = new X9ECParameters(
@@ -386,12 +255,22 @@ public class BCECGOST3410PublicKey
params = new X962Parameters(ecP);
}
+ }
+
+ BigInteger bX = this.q.getAffineXCoord().toBigInteger();
+ BigInteger bY = this.q.getAffineYCoord().toBigInteger();
+ byte[] encKey = new byte[64];
- ECCurve curve = this.engineGetQ().getCurve();
- ASN1OctetString p = (ASN1OctetString)
- new X9ECPoint(curve.createPoint(this.getQ().getX().toBigInteger(), this.getQ().getY().toBigInteger(), withCompression)).toASN1Primitive();
+ extractBytes(encKey, 0, bX);
+ extractBytes(encKey, 32, bY);
- info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
+ try
+ {
+ info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3410_2001, params), new DEROctetString(encKey));
+ }
+ catch (IOException e)
+ {
+ return null;
}
return KeyUtil.getEncodedSubjectPublicKeyInfo(info);
@@ -430,7 +309,7 @@ public class BCECGOST3410PublicKey
public ECPoint getW()
{
- return new ECPoint(q.getX().toBigInteger(), q.getY().toBigInteger());
+ return new ECPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
}
public org.bouncycastle.math.ec.ECPoint getQ()
@@ -439,11 +318,11 @@ public class BCECGOST3410PublicKey
{
if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp)
{
- return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord());
}
else
{
- return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord());
}
}
@@ -467,19 +346,19 @@ public class BCECGOST3410PublicKey
public String toString()
{
- StringBuffer buf = new StringBuffer();
- String nl = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+ String nl = System.getProperty("line.separator");
buf.append("EC Public Key").append(nl);
- buf.append(" X: ").append(this.q.getX().toBigInteger().toString(16)).append(nl);
- buf.append(" Y: ").append(this.q.getY().toBigInteger().toString(16)).append(nl);
+ buf.append(" X: ").append(this.q.getAffineXCoord().toBigInteger().toString(16)).append(nl);
+ buf.append(" Y: ").append(this.q.getAffineYCoord().toBigInteger().toString(16)).append(nl);
return buf.toString();
}
-
+
public void setPointFormat(String style)
{
- withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style));
+ withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style));
}
public boolean equals(Object o)
@@ -518,4 +397,9 @@ public class BCECGOST3410PublicKey
out.writeObject(this.getEncoded());
}
+
+ public GOST3410PublicKeyAlgParameters getGostParams()
+ {
+ return gostParams;
+ }
}
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 ce0e603..a2114fa 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,6 +1,9 @@
package org.bouncycastle.jcajce.provider.asymmetric.rsa;
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;
@@ -15,14 +18,18 @@ import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
public class BCRSAPublicKey
implements RSAPublicKey
{
+ private static final AlgorithmIdentifier DEFAULT_ALGORITHM_IDENTIFIER = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);
+
static final long serialVersionUID = 2675817738516720772L;
-
+
private BigInteger modulus;
private BigInteger publicExponent;
+ private transient AlgorithmIdentifier algorithmIdentifier;
BCRSAPublicKey(
RSAKeyParameters key)
{
+ this.algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
this.modulus = key.getModulus();
this.publicExponent = key.getExponent();
}
@@ -30,6 +37,7 @@ public class BCRSAPublicKey
BCRSAPublicKey(
RSAPublicKeySpec spec)
{
+ this.algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
this.modulus = spec.getModulus();
this.publicExponent = spec.getPublicExponent();
}
@@ -37,6 +45,7 @@ public class BCRSAPublicKey
BCRSAPublicKey(
RSAPublicKey key)
{
+ this.algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
this.modulus = key.getModulus();
this.publicExponent = key.getPublicExponent();
}
@@ -44,10 +53,16 @@ public class BCRSAPublicKey
BCRSAPublicKey(
SubjectPublicKeyInfo info)
{
+ populateFromPublicKeyInfo(info);
+ }
+
+ private void populateFromPublicKeyInfo(SubjectPublicKeyInfo info)
+ {
try
{
org.bouncycastle.asn1.pkcs.RSAPublicKey pubKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(info.parsePublicKey());
+ this.algorithmIdentifier = info.getAlgorithm();
this.modulus = pubKey.getModulus();
this.publicExponent = pubKey.getPublicExponent();
}
@@ -89,7 +104,7 @@ public class BCRSAPublicKey
public byte[] getEncoded()
{
- return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new org.bouncycastle.asn1.pkcs.RSAPublicKey(getModulus(), getPublicExponent()));
+ return KeyUtil.getEncodedSubjectPublicKeyInfo(algorithmIdentifier, new org.bouncycastle.asn1.pkcs.RSAPublicKey(getModulus(), getPublicExponent()));
}
public int hashCode()
@@ -126,4 +141,32 @@ public class BCRSAPublicKey
return buf.toString();
}
+
+ private void readObject(
+ ObjectInputStream in)
+ throws IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+
+ try
+ {
+ algorithmIdentifier = AlgorithmIdentifier.getInstance(in.readObject());
+ }
+ catch (OptionalDataException e)
+ {
+ algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER;
+ }
+ }
+
+ private void writeObject(
+ ObjectOutputStream out)
+ throws IOException
+ {
+ out.defaultWriteObject();
+
+ if (!algorithmIdentifier.equals(DEFAULT_ALGORITHM_IDENTIFIER))
+ {
+ out.writeObject(algorithmIdentifier.getEncoded());
+ }
+ }
}
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 d4065ac..5eea1b9 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
@@ -74,8 +74,8 @@ public class EC5Util
((ECNamedCurveParameterSpec)spec).getName(),
ellipticCurve,
new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
spec.getN(),
spec.getH());
}
@@ -84,8 +84,8 @@ public class EC5Util
return new ECParameterSpec(
ellipticCurve,
new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
spec.getN(),
spec.getH().intValue());
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java
index 1888328..32e595c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java
@@ -31,7 +31,7 @@ import org.bouncycastle.asn1.x509.X509Extension;
* ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
* (critical)
*/
-class X509CRLEntryObject extends X509CRLEntry
+public class X509CRLEntryObject extends X509CRLEntry
{
private TBSCertList.CRLEntry c;
@@ -39,7 +39,7 @@ class X509CRLEntryObject extends X509CRLEntry
private int hashValue;
private boolean isHashValueSet;
- public X509CRLEntryObject(TBSCertList.CRLEntry c)
+ protected X509CRLEntryObject(TBSCertList.CRLEntry c)
{
this.c = c;
this.certificateIssuer = null;
@@ -62,7 +62,7 @@ class X509CRLEntryObject extends X509CRLEntry
* @param previousCertificateIssuer
* Certificate issuer of the previous CRLEntry.
*/
- public X509CRLEntryObject(
+ protected X509CRLEntryObject(
TBSCertList.CRLEntry c,
boolean isIndirect,
X500Name previousCertificateIssuer)
@@ -211,6 +211,23 @@ class X509CRLEntryObject extends X509CRLEntry
return hashValue;
}
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (o instanceof X509CRLEntryObject)
+ {
+ X509CRLEntryObject other = (X509CRLEntryObject)o;
+
+ return this.c.equals(other.c);
+ }
+
+ return super.equals(this);
+ }
+
public byte[] getEncoded()
throws CRLException
{
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 2fc0826..c7d0402 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
@@ -54,13 +54,15 @@ import org.bouncycastle.util.encoders.Hex;
* Delta CRL Indicator (critical)
* Issuing Distribution Point (critical)
*/
-class X509CRLObject
+public class X509CRLObject
extends X509CRL
{
private CertificateList c;
private String sigAlgName;
private byte[] sigAlgParams;
private boolean isIndirect;
+ private boolean isHashCodeSet = false;
+ private int hashCodeValue;
static boolean isIndirectCRL(X509CRL crl)
throws CRLException
@@ -78,7 +80,7 @@ class X509CRLObject
}
}
- public X509CRLObject(
+ protected X509CRLObject(
CertificateList c)
throws CRLException
{
@@ -522,19 +524,21 @@ class X509CRLObject
throw new RuntimeException("X.509 CRL used with non X.509 Cert");
}
- TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
+ Enumeration certs = c.getRevokedCertificateEnumeration();
X500Name caName = c.getIssuer();
- if (certs != null)
+ if (certs.hasMoreElements())
{
BigInteger serial = ((X509Certificate)cert).getSerialNumber();
- for (int i = 0; i < certs.length; i++)
+ while (certs.hasMoreElements())
{
- if (isIndirect && certs[i].hasExtensions())
+ TBSCertList.CRLEntry entry = TBSCertList.CRLEntry.getInstance(certs.nextElement());
+
+ if (isIndirect && entry.hasExtensions())
{
- Extension currentCaName = certs[i].getExtensions().getExtension(Extension.certificateIssuer);
+ Extension currentCaName = entry.getExtensions().getExtension(Extension.certificateIssuer);
if (currentCaName != null)
{
@@ -542,7 +546,7 @@ class X509CRLObject
}
}
- if (certs[i].getUserCertificate().getValue().equals(serial))
+ if (entry.getUserCertificate().getValue().equals(serial))
{
X500Name issuer;
@@ -574,5 +578,50 @@ class X509CRLObject
return false;
}
+
+ public boolean equals(Object other)
+ {
+ if (this == other)
+ {
+ return true;
+ }
+
+ if (!(other instanceof X509CRL))
+ {
+ return false;
+ }
+
+ if (other instanceof X509CRLObject)
+ {
+ X509CRLObject crlObject = (X509CRLObject)other;
+
+ if (isHashCodeSet)
+ {
+ boolean otherIsHashCodeSet = crlObject.isHashCodeSet;
+ if (otherIsHashCodeSet)
+ {
+ if (crlObject.hashCodeValue != hashCodeValue)
+ {
+ return false;
+ }
+ }
+ }
+
+ return this.c.equals(crlObject.c);
+ }
+
+ return super.equals(other);
+ }
+
+ public int hashCode()
+ {
+ if (!isHashCodeSet)
+ {
+ isHashCodeSet = true;
+ hashCodeValue = super.hashCode();
+ }
+
+ return hashCodeValue;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java
index 7ff57d3..2112673 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/GOST3411.java
@@ -7,6 +7,7 @@ import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
+import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory;
public class GOST3411
{
@@ -46,6 +47,18 @@ public class GOST3411
}
}
+ /**
+ * PBEWithHmacGOST3411
+ */
+ public static class PBEWithMacKeyFactory
+ extends PBESecretKeyFactory
+ {
+ public PBEWithMacKeyFactory()
+ {
+ super("PBEwithHmacGOST3411", null, false, PKCS12, GOST3411, 256, 0);
+ }
+ }
+
public static class KeyGenerator
extends BaseKeyGenerator
{
@@ -71,6 +84,9 @@ public class GOST3411
provider.addAlgorithm("Alg.Alias.MessageDigest.GOST-3411", "GOST3411");
provider.addAlgorithm("Alg.Alias.MessageDigest." + CryptoProObjectIdentifiers.gostR3411, "GOST3411");
+ provider.addAlgorithm("SecretKeyFactory.PBEWITHHMACGOST3411", PREFIX + "$PBEWithMacKeyFactory");
+ provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + CryptoProObjectIdentifiers.gostR3411, "PBEWITHHMACGOST3411");
+
addHMACAlgorithm(provider, "GOST3411", PREFIX + "$HashMac", PREFIX + "$KeyGenerator");
addHMACAlias(provider, "GOST3411", CryptoProObjectIdentifiers.gostR3411);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java
index df5d41a..c7502c7 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java
@@ -193,7 +193,6 @@ public class SHA1
provider.addAlgorithm("SecretKeyFactory.PBEWITHHMACSHA1", PREFIX + "$PBEWithMacKeyFactory");
provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1", PREFIX + "$PBKDF2WithHmacSHA1UTF8");
- provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2WithHmacSHA1");
provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WithHmacSHA1AndUTF8", "PBKDF2WithHmacSHA1");
provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1And8BIT", PREFIX + "$PBKDF2WithHmacSHA18BIT");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SM3.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SM3.java
new file mode 100644
index 0000000..8050e35
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SM3.java
@@ -0,0 +1,47 @@
+package org.bouncycastle.jcajce.provider.digest;
+
+import org.bouncycastle.crypto.digests.SM3Digest;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+
+public class SM3
+{
+ private SM3()
+ {
+ }
+
+ static public class Digest
+ extends BCMessageDigest
+ implements Cloneable
+ {
+ public Digest()
+ {
+ super(new SM3Digest());
+ }
+
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ Digest d = (Digest)super.clone();
+ d.digest = new SM3Digest((SM3Digest)digest);
+
+ return d;
+ }
+ }
+
+ public static class Mappings
+ extends DigestAlgorithmProvider
+ {
+ private static final String PREFIX = SM3.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+ provider.addAlgorithm("MessageDigest.SM3", PREFIX + "$Digest");
+ provider.addAlgorithm("Alg.Alias.MessageDigest.SM3", "SM3");
+ provider.addAlgorithm("Alg.Alias.MessageDigest.1.2.156.197.1.401", "SM3");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Skein.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Skein.java
new file mode 100644
index 0000000..1191049
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/Skein.java
@@ -0,0 +1,740 @@
+package org.bouncycastle.jcajce.provider.digest;
+
+import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.digests.SkeinDigest;
+import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.crypto.macs.SkeinMac;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
+
+public class Skein
+{
+ private Skein()
+ {
+ }
+
+ public static class DigestSkein256
+ extends BCMessageDigest
+ implements Cloneable
+ {
+ public DigestSkein256(int outputSize)
+ {
+ super(new SkeinDigest(SkeinDigest.SKEIN_256, outputSize));
+ }
+
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ BCMessageDigest d = (BCMessageDigest)super.clone();
+ d.digest = new SkeinDigest((SkeinDigest)digest);
+
+ return d;
+ }
+ }
+
+ public static class Digest_256_128
+ extends DigestSkein256
+ {
+ public Digest_256_128()
+ {
+ super(128);
+ }
+ }
+
+ public static class Digest_256_160
+ extends DigestSkein256
+ {
+ public Digest_256_160()
+ {
+ super(160);
+ }
+ }
+
+ public static class Digest_256_224
+ extends DigestSkein256
+ {
+ public Digest_256_224()
+ {
+ super(224);
+ }
+ }
+
+ public static class Digest_256_256
+ extends DigestSkein256
+ {
+ public Digest_256_256()
+ {
+ super(256);
+ }
+ }
+
+ public static class DigestSkein512
+ extends BCMessageDigest
+ implements Cloneable
+ {
+ public DigestSkein512(int outputSize)
+ {
+ super(new SkeinDigest(SkeinDigest.SKEIN_512, outputSize));
+ }
+
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ BCMessageDigest d = (BCMessageDigest)super.clone();
+ d.digest = new SkeinDigest((SkeinDigest)digest);
+
+ return d;
+ }
+ }
+
+ public static class Digest_512_128
+ extends DigestSkein512
+ {
+ public Digest_512_128()
+ {
+ super(128);
+ }
+ }
+
+ public static class Digest_512_160
+ extends DigestSkein512
+ {
+ public Digest_512_160()
+ {
+ super(160);
+ }
+ }
+
+ public static class Digest_512_224
+ extends DigestSkein512
+ {
+ public Digest_512_224()
+ {
+ super(224);
+ }
+ }
+
+ public static class Digest_512_256
+ extends DigestSkein512
+ {
+ public Digest_512_256()
+ {
+ super(256);
+ }
+ }
+
+ public static class Digest_512_384
+ extends DigestSkein512
+ {
+ public Digest_512_384()
+ {
+ super(384);
+ }
+ }
+
+ public static class Digest_512_512
+ extends DigestSkein512
+ {
+ public Digest_512_512()
+ {
+ super(512);
+ }
+ }
+
+ public static class DigestSkein1024
+ extends BCMessageDigest
+ implements Cloneable
+ {
+ public DigestSkein1024(int outputSize)
+ {
+ super(new SkeinDigest(SkeinDigest.SKEIN_1024, outputSize));
+ }
+
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ BCMessageDigest d = (BCMessageDigest)super.clone();
+ d.digest = new SkeinDigest((SkeinDigest)digest);
+
+ return d;
+ }
+ }
+
+ public static class Digest_1024_384
+ extends DigestSkein1024
+ {
+ public Digest_1024_384()
+ {
+ super(384);
+ }
+ }
+
+ public static class Digest_1024_512
+ extends DigestSkein1024
+ {
+ public Digest_1024_512()
+ {
+ super(512);
+ }
+ }
+
+ public static class Digest_1024_1024
+ extends DigestSkein1024
+ {
+ public Digest_1024_1024()
+ {
+ super(1024);
+ }
+ }
+
+ /**
+ * Skein HMac
+ */
+ public static class HashMac_256_128
+ extends BaseMac
+ {
+ public HashMac_256_128()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_256, 128)));
+ }
+ }
+
+ public static class HashMac_256_160
+ extends BaseMac
+ {
+ public HashMac_256_160()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_256, 160)));
+ }
+ }
+
+ public static class HashMac_256_224
+ extends BaseMac
+ {
+ public HashMac_256_224()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_256, 224)));
+ }
+ }
+
+ public static class HashMac_256_256
+ extends BaseMac
+ {
+ public HashMac_256_256()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_256, 256)));
+ }
+ }
+
+ public static class HashMac_512_128
+ extends BaseMac
+ {
+ public HashMac_512_128()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_512, 128)));
+ }
+ }
+
+ public static class HashMac_512_160
+ extends BaseMac
+ {
+ public HashMac_512_160()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_512, 160)));
+ }
+ }
+
+ public static class HashMac_512_224
+ extends BaseMac
+ {
+ public HashMac_512_224()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_512, 224)));
+ }
+ }
+
+ public static class HashMac_512_256
+ extends BaseMac
+ {
+ public HashMac_512_256()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_512, 256)));
+ }
+ }
+
+ public static class HashMac_512_384
+ extends BaseMac
+ {
+ public HashMac_512_384()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_512, 384)));
+ }
+ }
+
+ public static class HashMac_512_512
+ extends BaseMac
+ {
+ public HashMac_512_512()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_512, 512)));
+ }
+ }
+
+ public static class HashMac_1024_384
+ extends BaseMac
+ {
+ public HashMac_1024_384()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_1024, 384)));
+ }
+ }
+
+ public static class HashMac_1024_512
+ extends BaseMac
+ {
+ public HashMac_1024_512()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_1024, 512)));
+ }
+ }
+
+ public static class HashMac_1024_1024
+ extends BaseMac
+ {
+ public HashMac_1024_1024()
+ {
+ super(new HMac(new SkeinDigest(SkeinDigest.SKEIN_1024, 1024)));
+ }
+ }
+
+ public static class HMacKeyGenerator_256_128
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_256_128()
+ {
+ super("HMACSkein-256-128", 128, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_256_160
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_256_160()
+ {
+ super("HMACSkein-256-160", 160, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_256_224
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_256_224()
+ {
+ super("HMACSkein-256-224", 224, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_256_256
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_256_256()
+ {
+ super("HMACSkein-256-256", 256, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_512_128
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_512_128()
+ {
+ super("HMACSkein-512-128", 128, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_512_160
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_512_160()
+ {
+ super("HMACSkein-512-160", 160, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_512_224
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_512_224()
+ {
+ super("HMACSkein-512-224", 224, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_512_256
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_512_256()
+ {
+ super("HMACSkein-512-256", 256, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_512_384
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_512_384()
+ {
+ super("HMACSkein-512-384", 384, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_512_512
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_512_512()
+ {
+ super("HMACSkein-512-512", 512, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_1024_384
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_1024_384()
+ {
+ super("HMACSkein-1024-384", 384, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_1024_512
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_1024_512()
+ {
+ super("HMACSkein-1024-512", 512, new CipherKeyGenerator());
+ }
+ }
+
+ public static class HMacKeyGenerator_1024_1024
+ extends BaseKeyGenerator
+ {
+ public HMacKeyGenerator_1024_1024()
+ {
+ super("HMACSkein-1024-1024", 1024, new CipherKeyGenerator());
+ }
+ }
+
+ /*
+ * Skein-MAC
+ */
+ public static class SkeinMac_256_128
+ extends BaseMac
+ {
+ public SkeinMac_256_128()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_256, 128));
+ }
+ }
+
+ public static class SkeinMac_256_160
+ extends BaseMac
+ {
+ public SkeinMac_256_160()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_256, 160));
+ }
+ }
+
+ public static class SkeinMac_256_224
+ extends BaseMac
+ {
+ public SkeinMac_256_224()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_256, 224));
+ }
+ }
+
+ public static class SkeinMac_256_256
+ extends BaseMac
+ {
+ public SkeinMac_256_256()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_256, 256));
+ }
+ }
+
+ public static class SkeinMac_512_128
+ extends BaseMac
+ {
+ public SkeinMac_512_128()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_512, 128));
+ }
+ }
+
+ public static class SkeinMac_512_160
+ extends BaseMac
+ {
+ public SkeinMac_512_160()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_512, 160));
+ }
+ }
+
+ public static class SkeinMac_512_224
+ extends BaseMac
+ {
+ public SkeinMac_512_224()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_512, 224));
+ }
+ }
+
+ public static class SkeinMac_512_256
+ extends BaseMac
+ {
+ public SkeinMac_512_256()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_512, 256));
+ }
+ }
+
+ public static class SkeinMac_512_384
+ extends BaseMac
+ {
+ public SkeinMac_512_384()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_512, 384));
+ }
+ }
+
+ public static class SkeinMac_512_512
+ extends BaseMac
+ {
+ public SkeinMac_512_512()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_512, 512));
+ }
+ }
+
+ public static class SkeinMac_1024_384
+ extends BaseMac
+ {
+ public SkeinMac_1024_384()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_1024, 384));
+ }
+ }
+
+ public static class SkeinMac_1024_512
+ extends BaseMac
+ {
+ public SkeinMac_1024_512()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_1024, 512));
+ }
+ }
+
+ public static class SkeinMac_1024_1024
+ extends BaseMac
+ {
+ public SkeinMac_1024_1024()
+ {
+ super(new SkeinMac(SkeinMac.SKEIN_1024, 1024));
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_256_128
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_256_128()
+ {
+ super("Skein-MAC-256-128", 128, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_256_160
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_256_160()
+ {
+ super("Skein-MAC-256-160", 160, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_256_224
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_256_224()
+ {
+ super("Skein-MAC-256-224", 224, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_256_256
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_256_256()
+ {
+ super("Skein-MAC-256-256", 256, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_512_128
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_512_128()
+ {
+ super("Skein-MAC-512-128", 128, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_512_160
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_512_160()
+ {
+ super("Skein-MAC-512-160", 160, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_512_224
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_512_224()
+ {
+ super("Skein-MAC-512-224", 224, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_512_256
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_512_256()
+ {
+ super("Skein-MAC-512-256", 256, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_512_384
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_512_384()
+ {
+ super("Skein-MAC-512-384", 384, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_512_512
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_512_512()
+ {
+ super("Skein-MAC-512-512", 512, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_1024_384
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_1024_384()
+ {
+ super("Skein-MAC-1024-384", 384, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_1024_512
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_1024_512()
+ {
+ super("Skein-MAC-1024-512", 512, new CipherKeyGenerator());
+ }
+ }
+
+ public static class SkeinMacKeyGenerator_1024_1024
+ extends BaseKeyGenerator
+ {
+ public SkeinMacKeyGenerator_1024_1024()
+ {
+ super("Skein-MAC-1024-1024", 1024, new CipherKeyGenerator());
+ }
+ }
+
+ public static class Mappings
+ extends DigestAlgorithmProvider
+ {
+ private static final String PREFIX = Skein.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+ // Skein sizes as used in "The Skein Hash Function Family 1.3"
+
+ provider.addAlgorithm("MessageDigest.Skein-256-128", PREFIX + "$Digest_256_128");
+ provider.addAlgorithm("MessageDigest.Skein-256-160", PREFIX + "$Digest_256_160");
+ provider.addAlgorithm("MessageDigest.Skein-256-224", PREFIX + "$Digest_256_224");
+ provider.addAlgorithm("MessageDigest.Skein-256-256", PREFIX + "$Digest_256_256");
+
+ provider.addAlgorithm("MessageDigest.Skein-512-128", PREFIX + "$Digest_512_128");
+ provider.addAlgorithm("MessageDigest.Skein-512-160", PREFIX + "$Digest_512_160");
+ provider.addAlgorithm("MessageDigest.Skein-512-224", PREFIX + "$Digest_512_224");
+ provider.addAlgorithm("MessageDigest.Skein-512-256", PREFIX + "$Digest_512_256");
+ provider.addAlgorithm("MessageDigest.Skein-512-384", PREFIX + "$Digest_512_384");
+ provider.addAlgorithm("MessageDigest.Skein-512-512", PREFIX + "$Digest_512_512");
+
+ provider.addAlgorithm("MessageDigest.Skein-1024-384", PREFIX + "$Digest_1024_384");
+ provider.addAlgorithm("MessageDigest.Skein-1024-512", PREFIX + "$Digest_1024_512");
+ provider.addAlgorithm("MessageDigest.Skein-1024-1024", PREFIX + "$Digest_1024_1024");
+
+ addHMACAlgorithm(provider, "Skein-256-128", PREFIX + "$HashMac_256_128", PREFIX + "$HMacKeyGenerator_256_128");
+ addHMACAlgorithm(provider, "Skein-256-160", PREFIX + "$HashMac_256_160", PREFIX + "$HMacKeyGenerator_256_160");
+ addHMACAlgorithm(provider, "Skein-256-224", PREFIX + "$HashMac_256_224", PREFIX + "$HMacKeyGenerator_256_224");
+ addHMACAlgorithm(provider, "Skein-256-256", PREFIX + "$HashMac_256_256", PREFIX + "$HMacKeyGenerator_256_256");
+
+ addHMACAlgorithm(provider, "Skein-512-128", PREFIX + "$HashMac_512_128", PREFIX + "$HMacKeyGenerator_512_128");
+ addHMACAlgorithm(provider, "Skein-512-160", PREFIX + "$HashMac_512_160", PREFIX + "$HMacKeyGenerator_512_160");
+ addHMACAlgorithm(provider, "Skein-512-224", PREFIX + "$HashMac_512_224", PREFIX + "$HMacKeyGenerator_512_224");
+ addHMACAlgorithm(provider, "Skein-512-256", PREFIX + "$HashMac_512_256", PREFIX + "$HMacKeyGenerator_512_256");
+ addHMACAlgorithm(provider, "Skein-512-384", PREFIX + "$HashMac_512_384", PREFIX + "$HMacKeyGenerator_512_384");
+ addHMACAlgorithm(provider, "Skein-512-512", PREFIX + "$HashMac_512_512", PREFIX + "$HMacKeyGenerator_512_512");
+
+ addHMACAlgorithm(provider, "Skein-1024-384", PREFIX + "$HashMac_1024_384", PREFIX + "$HMacKeyGenerator_1024_384");
+ addHMACAlgorithm(provider, "Skein-1024-512", PREFIX + "$HashMac_1024_512", PREFIX + "$HMacKeyGenerator_1024_512");
+ addHMACAlgorithm(provider, "Skein-1024-1024", PREFIX + "$HashMac_1024_1024", PREFIX + "$HMacKeyGenerator_1024_1024");
+
+ addSkeinMacAlgorithm(provider, 256, 128);
+ addSkeinMacAlgorithm(provider, 256, 160);
+ addSkeinMacAlgorithm(provider, 256, 224);
+ addSkeinMacAlgorithm(provider, 256, 256);
+
+ addSkeinMacAlgorithm(provider, 512, 128);
+ addSkeinMacAlgorithm(provider, 512, 160);
+ addSkeinMacAlgorithm(provider, 512, 224);
+ addSkeinMacAlgorithm(provider, 512, 256);
+ addSkeinMacAlgorithm(provider, 512, 384);
+ addSkeinMacAlgorithm(provider, 512, 512);
+
+ addSkeinMacAlgorithm(provider, 1024, 384);
+ addSkeinMacAlgorithm(provider, 1024, 512);
+ addSkeinMacAlgorithm(provider, 1024, 1024);
+ }
+
+ private void addSkeinMacAlgorithm(ConfigurableProvider provider, int blockSize, int outputSize)
+ {
+ String mainName = "Skein-MAC-" + blockSize + "-" + outputSize;
+ String algorithmClassName = PREFIX + "$SkeinMac_" + blockSize + "_" + outputSize;
+ String keyGeneratorClassName = PREFIX + "$SkeinMacKeyGenerator_" + blockSize + "_" + outputSize;
+
+ provider.addAlgorithm("Mac." + mainName, algorithmClassName);
+ provider.addAlgorithm("Alg.Alias.Mac.Skein-MAC" + blockSize + "/" + outputSize, mainName);
+ provider.addAlgorithm("KeyGenerator." + mainName, keyGeneratorClassName);
+ provider.addAlgorithm("Alg.Alias.KeyGenerator.Skein-MAC" + blockSize + "/" + outputSize, mainName);
+ }
+
+ }
+}
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 c255002..9a62c98 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,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStore.LoadStoreParameter;
@@ -24,13 +26,18 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Map;
import java.util.Vector;
import javax.crypto.Cipher;
import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
@@ -54,6 +61,10 @@ import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.DERSequence;
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.pkcs.AuthenticatedSafe;
import org.bouncycastle.asn1.pkcs.CertBag;
import org.bouncycastle.asn1.pkcs.ContentInfo;
@@ -75,12 +86,14 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.jcajce.provider.config.PKCS12StoreParameter;
import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
-import org.bouncycastle.jcajce.provider.util.SecretKeyUtil;
+import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
+import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
import org.bouncycastle.jce.interfaces.BCKeyStore;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
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.Strings;
import org.bouncycastle.util.encoders.Hex;
@@ -92,6 +105,7 @@ public class PKCS12KeyStoreSpi
private static final int MIN_ITERATIONS = 1024;
private static final Provider bcProvider = new BouncyCastleProvider();
+ private static final DefaultSecretKeyProvider keySizeProvider = new DefaultSecretKeyProvider();
private IgnoresCaseHashtable keys = new IgnoresCaseHashtable();
private Hashtable localIds = new Hashtable();
@@ -593,16 +607,8 @@ public class PKCS12KeyStoreSpi
}
else if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2))
{
- PBES2Parameters alg = PBES2Parameters.getInstance(algId.getParameters());
- PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
- SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg.getKeyDerivationFunc().getAlgorithm().getId(), bcProvider);
-
- SecretKey k = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), SecretKeyUtil.getKeySize(alg.getEncryptionScheme().getAlgorithm())));
-
- Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId(), bcProvider);
-
- cipher.init(Cipher.UNWRAP_MODE, k, new IvParameterSpec(ASN1OctetString.getInstance(alg.getEncryptionScheme().getParameters()).getOctets()));
+ Cipher cipher = createCipher(Cipher.UNWRAP_MODE, password, algId);
// we pass "" as the key algorithm type as it is unknown at this point
return (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY);
@@ -656,29 +662,88 @@ public class PKCS12KeyStoreSpi
byte[] data)
throws IOException
{
- String algorithm = algId.getAlgorithm().getId();
- PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
- PBEKeySpec pbeSpec = new PBEKeySpec(password);
+ ASN1ObjectIdentifier algorithm = algId.getAlgorithm();
- try
+ if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds))
{
- SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm, bcProvider);
- PBEParameterSpec defParams = new PBEParameterSpec(
- pbeParams.getIV(),
- pbeParams.getIterations().intValue());
- BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec);
+ PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters());
+ PBEKeySpec pbeSpec = new PBEKeySpec(password);
- key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
+ try
+ {
+ SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm.getId(), bcProvider);
+ PBEParameterSpec defParams = new PBEParameterSpec(
+ pbeParams.getIV(),
+ pbeParams.getIterations().intValue());
+ BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec);
- Cipher cipher = Cipher.getInstance(algorithm, bcProvider);
- int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
- cipher.init(mode, key, defParams);
- return cipher.doFinal(data);
+ key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
+
+ Cipher cipher = Cipher.getInstance(algorithm.getId(), bcProvider);
+ int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
+ cipher.init(mode, key, defParams);
+ return cipher.doFinal(data);
+ }
+ catch (Exception e)
+ {
+ throw new IOException("exception decrypting data - " + e.toString());
+ }
}
- catch (Exception e)
+ else if (algorithm.equals(PKCSObjectIdentifiers.id_PBES2))
+ {
+ try
+ {
+ Cipher cipher = createCipher(Cipher.DECRYPT_MODE, password, algId);
+
+ return cipher.doFinal(data);
+ }
+ catch (Exception e)
+ {
+ throw new IOException("exception decrypting data - " + e.toString());
+ }
+ }
+ else
+ {
+ throw new IOException("unknown PBE algorithm: " + algorithm);
+ }
+ }
+
+ private Cipher createCipher(int mode, char[] password, AlgorithmIdentifier algId)
+ throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ PBES2Parameters alg = PBES2Parameters.getInstance(algId.getParameters());
+ PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
+ AlgorithmIdentifier encScheme = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
+
+ SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg.getKeyDerivationFunc().getAlgorithm().getId(), bcProvider);
+ SecretKey key;
+
+ if (func.isDefaultPrf())
+ {
+ key = keyFact.generateSecret(new PBEKeySpec(password, func.getSalt(), func.getIterationCount().intValue(), keySizeProvider.getKeySize(encScheme)));
+ }
+ else
+ {
+ key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), func.getIterationCount().intValue(), 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)
{
- throw new IOException("exception decrypting data - " + e.toString());
+ cipher.init(mode, key, new IvParameterSpec(ASN1OctetString.getInstance(encParams).getOctets()));
}
+ else
+ {
+ // TODO: at the moment it's just GOST, but...
+ GOST28147Parameters gParams = GOST28147Parameters.getInstance(encParams);
+
+ cipher.init(mode, key, new GOST28147ParameterSpec(gParams.getEncryptionParamSet(), gParams.getIV()));
+ }
+ return cipher;
}
public void engineLoad(
@@ -1671,4 +1736,43 @@ public class PKCS12KeyStoreSpi
return orig.elements();
}
}
+
+ private static class DefaultSecretKeyProvider
+ {
+ private final Map KEY_SIZES;
+
+ DefaultSecretKeyProvider()
+ {
+ Map keySizes = new HashMap();
+
+ keySizes.put(new ASN1ObjectIdentifier("1.2.840.113533.7.66.10"), Integers.valueOf(128));
+
+ keySizes.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), Integers.valueOf(192));
+
+ keySizes.put(NISTObjectIdentifiers.id_aes128_CBC, Integers.valueOf(128));
+ keySizes.put(NISTObjectIdentifiers.id_aes192_CBC, Integers.valueOf(192));
+ keySizes.put(NISTObjectIdentifiers.id_aes256_CBC, Integers.valueOf(256));
+
+ 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));
+
+ keySizes.put(CryptoProObjectIdentifiers.gostR28147_gcfb, Integers.valueOf(256));
+
+ KEY_SIZES = Collections.unmodifiableMap(keySizes);
+ }
+
+ public int getKeySize(AlgorithmIdentifier algorithmIdentifier)
+ {
+ // TODO: not all ciphers/oid relationships are this simple.
+ Integer keySize = (Integer)KEY_SIZES.get(algorithmIdentifier.getAlgorithm());
+
+ if (keySize != null)
+ {
+ return keySize.intValue();
+ }
+
+ return -1;
+ }
+ }
}
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 7a6f7b0..a600604 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java
@@ -1,13 +1,18 @@
package org.bouncycastle.jcajce.provider.symmetric;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
import javax.crypto.spec.IvParameterSpec;
import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
+import org.bouncycastle.asn1.cms.GCMParameters;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
@@ -15,6 +20,7 @@ import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.engines.AESWrapEngine;
import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.CMac;
import org.bouncycastle.crypto.macs.GMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
@@ -23,6 +29,7 @@ import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.modes.OFBBlockCipher;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameters;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
@@ -31,9 +38,12 @@ import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider;
import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters;
import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.Integers;
public final class AES
{
+ private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
+
private AES()
{
}
@@ -80,6 +90,15 @@ public final class AES
}
}
+ static public class GCM
+ extends BaseBlockCipher
+ {
+ public GCM()
+ {
+ super(new GCMBlockCipher(new AESFastEngine()));
+ }
+ }
+
public static class AESCMAC
extends BaseMac
{
@@ -98,6 +117,24 @@ public final class AES
}
}
+ public static class Poly1305
+ extends BaseMac
+ {
+ public Poly1305()
+ {
+ super(new org.bouncycastle.crypto.macs.Poly1305(new AESFastEngine()));
+ }
+ }
+
+ public static class Poly1305KeyGen
+ extends BaseKeyGenerator
+ {
+ public Poly1305KeyGen()
+ {
+ super("Poly1305-AES", 256, new Poly1305KeyGenerator());
+ }
+ }
+
static public class Wrap
extends BaseWrapCipher
{
@@ -325,6 +362,95 @@ public final class AES
}
}
+ public static class AlgParamsGCM
+ extends BaseAlgorithmParameters
+ {
+ private GCMParameters gcmParams;
+
+ protected void engineInit(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (gcmSpecClass != null)
+ {
+ try
+ {
+ Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]);
+ Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]);
+
+
+ gcmParams = new GCMParameters((byte[])iv.invoke(paramSpec, new Object[0]), ((Integer)tLen.invoke(paramSpec, new Object[0])).intValue());
+ }
+ catch (Exception e)
+ {
+ throw new InvalidParameterSpecException("Cannot process GCMParameterSpec.");
+ }
+ }
+ }
+
+ protected void engineInit(byte[] params)
+ throws IOException
+ {
+ gcmParams = GCMParameters.getInstance(params);
+ }
+
+ protected void engineInit(byte[] params, String format)
+ throws IOException
+ {
+ if (!isASN1FormatString(format))
+ {
+ throw new IOException("unknown format specified");
+ }
+
+ gcmParams = GCMParameters.getInstance(params);
+ }
+
+ protected byte[] engineGetEncoded()
+ throws IOException
+ {
+ return gcmParams.getEncoded();
+ }
+
+ protected byte[] engineGetEncoded(String format)
+ throws IOException
+ {
+ if (!isASN1FormatString(format))
+ {
+ throw new IOException("unknown format specified");
+ }
+
+ return gcmParams.getEncoded();
+ }
+
+ protected String engineToString()
+ {
+ return "GCM";
+ }
+
+ protected AlgorithmParameterSpec localEngineGetParameterSpec(Class paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (gcmSpecClass != null)
+ {
+ try
+ {
+ Constructor constructor = gcmSpecClass.getConstructor(new Class[] { byte[].class, Integer.class });
+
+ return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { gcmParams.getNonce(), Integers.valueOf(gcmParams.getIcvLen()) });
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new InvalidParameterSpecException("no constructor found!"); // should never happen
+ }
+ catch (Exception e)
+ {
+ throw new InvalidParameterSpecException("construction failed: " + e.getMessage()); // should never happen
+ }
+ }
+
+ throw new InvalidParameterSpecException("unknown parameter spec: " + paramSpec.getName());
+ }
+ }
+
public static class Mappings
extends SymmetricAlgorithmProvider
{
@@ -353,6 +479,11 @@ public final class AES
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_CBC, "AES");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_CBC, "AES");
+ provider.addAlgorithm("AlgorithmParameters.GCM", PREFIX + "$AlgParamsGCM");
+ provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
+ provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
+ provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
+
provider.addAlgorithm("AlgorithmParameterGenerator.AES", PREFIX + "$AlgParamGen");
provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + wrongAES128, "AES");
provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + wrongAES192, "AES");
@@ -383,6 +514,11 @@ public final class AES
provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_wrap, "AESWRAP");
provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap");
+ provider.addAlgorithm("Cipher.GCM", PREFIX + "$GCM");
+ provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
+ provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
+ provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
+
provider.addAlgorithm("KeyGenerator.AES", PREFIX + "$KeyGen");
provider.addAlgorithm("KeyGenerator." + wrongAES128, PREFIX + "$KeyGen128");
provider.addAlgorithm("KeyGenerator." + wrongAES192, PREFIX + "$KeyGen192");
@@ -484,6 +620,21 @@ public final class AES
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.getId(), "PKCS12PBE");
addGMacAlgorithm(provider, "AES", PREFIX + "$AESGMAC", PREFIX + "$KeyGen128");
+ addPoly1305Algorithm(provider, "AES", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
+ }
+ }
+
+ 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/CAST6.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/CAST6.java
index 68605f4..d16e6c7 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/CAST6.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/CAST6.java
@@ -1,13 +1,16 @@
package org.bouncycastle.jcajce.provider.symmetric;
+import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.CAST6Engine;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.GMac;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
+import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider;
public final class CAST6
{
@@ -20,7 +23,13 @@ public final class CAST6
{
public ECB()
{
- super(new CAST6Engine());
+ super(new BlockCipherProvider()
+ {
+ public BlockCipher get()
+ {
+ return new CAST6Engine();
+ }
+ });
}
}
@@ -42,6 +51,24 @@ public final class CAST6
}
}
+ public static class Poly1305
+ extends BaseMac
+ {
+ public Poly1305()
+ {
+ super(new org.bouncycastle.crypto.macs.Poly1305(new CAST6Engine()));
+ }
+ }
+
+ public static class Poly1305KeyGen
+ extends BaseKeyGenerator
+ {
+ public Poly1305KeyGen()
+ {
+ super("Poly1305-CAST6", 256, new Poly1305KeyGenerator());
+ }
+ }
+
public static class Mappings
extends SymmetricAlgorithmProvider
{
@@ -57,6 +84,7 @@ public final class CAST6
provider.addAlgorithm("KeyGenerator.CAST6", PREFIX + "$KeyGen");
addGMacAlgorithm(provider, "CAST6", PREFIX + "$GMAC", PREFIX + "$KeyGen");
+ addPoly1305Algorithm(provider, "CAST6", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Camellia.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Camellia.java
index 38b5ca7..95b5156 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Camellia.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Camellia.java
@@ -13,6 +13,7 @@ import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.CamelliaEngine;
import org.bouncycastle.crypto.engines.CamelliaWrapEngine;
import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.GMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
@@ -83,6 +84,24 @@ public final class Camellia
}
}
+ public static class Poly1305
+ extends BaseMac
+ {
+ public Poly1305()
+ {
+ super(new org.bouncycastle.crypto.macs.Poly1305(new CamelliaEngine()));
+ }
+ }
+
+ public static class Poly1305KeyGen
+ extends BaseKeyGenerator
+ {
+ public Poly1305KeyGen()
+ {
+ super("Poly1305-Camellia", 256, new Poly1305KeyGenerator());
+ }
+ }
+
public static class KeyGen
extends BaseKeyGenerator
{
@@ -213,6 +232,7 @@ public final class Camellia
provider.addAlgorithm("KeyGenerator." + NTTObjectIdentifiers.id_camellia256_cbc, PREFIX + "$KeyGen256");
addGMacAlgorithm(provider, "CAMELLIA", PREFIX + "$GMAC", PREFIX + "$KeyGen");
+ addPoly1305Algorithm(provider, "CAMELLIA", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/ChaCha.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/ChaCha.java
new file mode 100644
index 0000000..ff748ae
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/ChaCha.java
@@ -0,0 +1,51 @@
+package org.bouncycastle.jcajce.provider.symmetric;
+
+import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.engines.ChaChaEngine;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseStreamCipher;
+import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
+
+public final class ChaCha
+{
+ private ChaCha()
+ {
+ }
+
+ public static class Base
+ extends BaseStreamCipher
+ {
+ public Base()
+ {
+ super(new ChaChaEngine(), 8);
+ }
+ }
+
+ public static class KeyGen
+ extends BaseKeyGenerator
+ {
+ public KeyGen()
+ {
+ super("ChaCha", 128, new CipherKeyGenerator());
+ }
+ }
+
+ public static class Mappings
+ extends AlgorithmProvider
+ {
+ private static final String PREFIX = ChaCha.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+
+ provider.addAlgorithm("Cipher.CHACHA", PREFIX + "$Base");
+ provider.addAlgorithm("KeyGenerator.CHACHA", PREFIX + "$KeyGen");
+
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java
index 389b79a..b3ff96b 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/GOST28147.java
@@ -8,10 +8,12 @@ import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.GOST28147Engine;
import org.bouncycastle.crypto.macs.GOST28147Mac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
+import org.bouncycastle.crypto.modes.GCFBBlockCipher;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
@@ -45,6 +47,15 @@ public final class GOST28147
}
}
+ public static class GCFB
+ extends BaseBlockCipher
+ {
+ public GCFB()
+ {
+ super(new BufferedBlockCipher(new GCFBBlockCipher(new GOST28147Engine())), 64);
+ }
+ }
+
/**
* GOST28147
*/
@@ -132,12 +143,12 @@ public final class GOST28147
provider.addAlgorithm("Cipher.GOST28147", PREFIX + "$ECB");
provider.addAlgorithm("Alg.Alias.Cipher.GOST", "GOST28147");
provider.addAlgorithm("Alg.Alias.Cipher.GOST-28147", "GOST28147");
- provider.addAlgorithm("Cipher." + CryptoProObjectIdentifiers.gostR28147_cbc, PREFIX + "$CBC");
+ provider.addAlgorithm("Cipher." + CryptoProObjectIdentifiers.gostR28147_gcfb, PREFIX + "$GCFB");
provider.addAlgorithm("KeyGenerator.GOST28147", PREFIX + "$KeyGen");
provider.addAlgorithm("Alg.Alias.KeyGenerator.GOST", "GOST28147");
provider.addAlgorithm("Alg.Alias.KeyGenerator.GOST-28147", "GOST28147");
- provider.addAlgorithm("Alg.Alias.KeyGenerator." + CryptoProObjectIdentifiers.gostR28147_cbc, "GOST28147");
+ provider.addAlgorithm("Alg.Alias.KeyGenerator." + CryptoProObjectIdentifiers.gostR28147_gcfb, "GOST28147");
provider.addAlgorithm("Mac.GOST28147MAC", PREFIX + "$Mac");
provider.addAlgorithm("Alg.Alias.Mac.GOST28147", "GOST28147MAC");
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Noekeon.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Noekeon.java
index 2d089cc..a92f21d 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Noekeon.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Noekeon.java
@@ -7,8 +7,10 @@ import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.IvParameterSpec;
+import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.NoekeonEngine;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.GMac;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
@@ -16,6 +18,7 @@ import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGen
import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
+import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider;
import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -30,7 +33,13 @@ public final class Noekeon
{
public ECB()
{
- super(new NoekeonEngine());
+ super(new BlockCipherProvider()
+ {
+ public BlockCipher get()
+ {
+ return new NoekeonEngine();
+ }
+ });
}
}
@@ -52,6 +61,24 @@ public final class Noekeon
}
}
+ public static class Poly1305
+ extends BaseMac
+ {
+ public Poly1305()
+ {
+ super(new org.bouncycastle.crypto.macs.Poly1305(new NoekeonEngine()));
+ }
+ }
+
+ public static class Poly1305KeyGen
+ extends BaseKeyGenerator
+ {
+ public Poly1305KeyGen()
+ {
+ super("Poly1305-Noekeon", 256, new Poly1305KeyGenerator());
+ }
+ }
+
public static class AlgParamGen
extends BaseAlgorithmParameterGenerator
{
@@ -120,6 +147,7 @@ public final class Noekeon
provider.addAlgorithm("KeyGenerator.NOEKEON", PREFIX + "$KeyGen");
addGMacAlgorithm(provider, "NOEKEON", PREFIX + "$GMAC", PREFIX + "$KeyGen");
+ addPoly1305Algorithm(provider, "NOEKEON", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
}
}
}
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 ee3cac9..4b0d8b9 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
@@ -2,17 +2,28 @@ package org.bouncycastle.jcajce.provider.symmetric;
import java.io.IOException;
import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.KeySpec;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameters;
+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;
public class PBEPBKDF2
{
@@ -104,6 +115,99 @@ public class PBEPBKDF2
}
}
+ public static class BasePBKDF2
+ extends BaseSecretKeyFactory
+ {
+ private int scheme;
+
+ public BasePBKDF2(String name, int scheme)
+ {
+ super(name, PKCSObjectIdentifiers.id_PBKDF2);
+
+ this.scheme = scheme;
+ }
+
+ protected SecretKey engineGenerateSecret(
+ KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof PBEKeySpec)
+ {
+ PBEKeySpec pbeSpec = (PBEKeySpec)keySpec;
+
+ if (pbeSpec.getSalt() == null)
+ {
+ throw new InvalidKeySpecException("missing required salt");
+ }
+
+ if (pbeSpec.getIterationCount() <= 0)
+ {
+ throw new InvalidKeySpecException("positive iteration count required: "
+ + pbeSpec.getIterationCount());
+ }
+
+ if (pbeSpec.getKeyLength() <= 0)
+ {
+ throw new InvalidKeySpecException("positive key length required: "
+ + pbeSpec.getKeyLength());
+ }
+
+ if (pbeSpec.getPassword().length == 0)
+ {
+ throw new IllegalArgumentException("password empty");
+ }
+
+ if (pbeSpec instanceof PBKDF2KeySpec)
+ {
+ PBKDF2KeySpec spec = (PBKDF2KeySpec)pbeSpec;
+
+ int digest = getDigestCode(spec.getPrf().getAlgorithm());
+ int keySize = pbeSpec.getKeyLength();
+ int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version.
+ CipherParameters param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize);
+
+ return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param);
+ }
+ else
+ {
+ int digest = SHA1;
+ int keySize = pbeSpec.getKeyLength();
+ int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version.
+ CipherParameters param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize);
+
+ return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param);
+ }
+ }
+
+ throw new InvalidKeySpecException("Invalid KeySpec");
+ }
+
+
+ private int getDigestCode(ASN1ObjectIdentifier algorithm)
+ throws InvalidKeySpecException
+ {
+ if (algorithm.equals(CryptoProObjectIdentifiers.gostR3411Hmac))
+ {
+ return GOST3411;
+ }
+ else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA1))
+ {
+ return SHA1;
+ }
+
+ throw new InvalidKeySpecException("Invalid KeySpec: unknown PRF algorithm " + algorithm);
+ }
+ }
+
+ public static class PBKDF2withUTF8
+ extends BasePBKDF2
+ {
+ public PBKDF2withUTF8()
+ {
+ super("PBKDF2", PKCS5S2_UTF8);
+ }
+ }
+
public static class Mappings
extends AlgorithmProvider
{
@@ -117,6 +221,8 @@ public class PBEPBKDF2
{
provider.addAlgorithm("AlgorithmParameters.PBKDF2", PREFIX + "$AlgParams");
provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2");
+ provider.addAlgorithm("SecretKeyFactory.PBKDF2", PREFIX + "$PBKDF2withUTF8");
+ provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2");
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC6.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC6.java
index a29e717..114c40b 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC6.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC6.java
@@ -11,6 +11,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.RC6Engine;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.GMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.modes.CFBBlockCipher;
@@ -82,6 +83,24 @@ public final class RC6
}
}
+ public static class Poly1305
+ extends BaseMac
+ {
+ public Poly1305()
+ {
+ super(new org.bouncycastle.crypto.macs.Poly1305(new RC6Engine()));
+ }
+ }
+
+ public static class Poly1305KeyGen
+ extends BaseKeyGenerator
+ {
+ public Poly1305KeyGen()
+ {
+ super("Poly1305-RC6", 256, new Poly1305KeyGenerator());
+ }
+ }
+
public static class KeyGen
extends BaseKeyGenerator
{
@@ -155,6 +174,7 @@ public final class RC6
provider.addAlgorithm("AlgorithmParameters.RC6", PREFIX + "$AlgParams");
addGMacAlgorithm(provider, "RC6", PREFIX + "$GMAC", PREFIX + "$KeyGen");
+ addPoly1305Algorithm(provider, "RC6", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SEED.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SEED.java
index 2ad41bf..e7e257c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SEED.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SEED.java
@@ -12,6 +12,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.SEEDEngine;
import org.bouncycastle.crypto.engines.SEEDWrapEngine;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.GMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
@@ -82,6 +83,24 @@ public final class SEED
}
}
+ public static class Poly1305
+ extends BaseMac
+ {
+ public Poly1305()
+ {
+ super(new org.bouncycastle.crypto.macs.Poly1305(new SEEDEngine()));
+ }
+ }
+
+ public static class Poly1305KeyGen
+ extends BaseKeyGenerator
+ {
+ public Poly1305KeyGen()
+ {
+ super("Poly1305-SEED", 256, new Poly1305KeyGenerator());
+ }
+ }
+
public static class AlgParamGen
extends BaseAlgorithmParameterGenerator
{
@@ -158,6 +177,7 @@ public final class SEED
provider.addAlgorithm("KeyGenerator." + KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap, PREFIX + "$KeyGen");
addGMacAlgorithm(provider, "SEED", PREFIX + "$GMAC", PREFIX + "$KeyGen");
+ addPoly1305Algorithm(provider, "SEED", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Serpent.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Serpent.java
index 578de32..ec21880 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Serpent.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Serpent.java
@@ -3,6 +3,8 @@ package org.bouncycastle.jcajce.provider.symmetric;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.SerpentEngine;
+import org.bouncycastle.crypto.engines.TwofishEngine;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.GMac;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
@@ -51,6 +53,24 @@ public final class Serpent
}
}
+ public static class Poly1305
+ extends BaseMac
+ {
+ public Poly1305()
+ {
+ super(new org.bouncycastle.crypto.macs.Poly1305(new TwofishEngine()));
+ }
+ }
+
+ public static class Poly1305KeyGen
+ extends BaseKeyGenerator
+ {
+ public Poly1305KeyGen()
+ {
+ super("Poly1305-Serpent", 256, new Poly1305KeyGenerator());
+ }
+ }
+
public static class AlgParams
extends IvAlgorithmParameters
{
@@ -77,6 +97,7 @@ public final class Serpent
provider.addAlgorithm("AlgorithmParameters.Serpent", PREFIX + "$AlgParams");
addGMacAlgorithm(provider, "SERPENT", PREFIX + "$SerpentGMAC", PREFIX + "$KeyGen");
+ addPoly1305Algorithm(provider, "SERPENT", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Shacal2.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Shacal2.java
new file mode 100644
index 0000000..81666af
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Shacal2.java
@@ -0,0 +1,124 @@
+package org.bouncycastle.jcajce.provider.symmetric;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.spec.IvParameterSpec;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.engines.Shacal2Engine;
+import org.bouncycastle.crypto.modes.CBCBlockCipher;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameterGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+public final class Shacal2
+{
+ private Shacal2()
+ {
+ }
+
+ public static class ECB
+ extends BaseBlockCipher
+ {
+ public ECB()
+ {
+ super(new BlockCipherProvider()
+ {
+ public BlockCipher get()
+ {
+ return new Shacal2Engine();
+ }
+ });
+ }
+ }
+
+ public static class CBC
+ extends BaseBlockCipher
+ {
+ public CBC()
+ {
+ super(new CBCBlockCipher(new Shacal2Engine()), 256);//block size
+ }
+ }
+
+ public static class KeyGen
+ extends BaseKeyGenerator
+ {
+ public KeyGen()
+ {
+ super("Shacal2", 512, new CipherKeyGenerator());//key size
+ }
+ }
+
+ public static class AlgParamGen
+ extends BaseAlgorithmParameterGenerator
+ {
+ protected void engineInit(
+ AlgorithmParameterSpec genParamSpec,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for Shacal2 parameter generation.");
+ }
+
+ protected AlgorithmParameters engineGenerateParameters()
+ {
+ byte[] iv = new byte[32];// block size 256
+
+ if (random == null)
+ {
+ random = new SecureRandom();
+ }
+
+ random.nextBytes(iv);
+
+ AlgorithmParameters params;
+
+ try
+ {
+ params = AlgorithmParameters.getInstance("Shacal2", BouncyCastleProvider.PROVIDER_NAME);
+ params.init(new IvParameterSpec(iv));
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.getMessage());
+ }
+ return params;
+ }
+ }
+
+ public static class AlgParams
+ extends IvAlgorithmParameters
+ {
+ protected String engineToString()
+ {
+ return "Shacal2 IV";
+ }
+ }
+
+ public static class Mappings
+ extends SymmetricAlgorithmProvider
+ {
+ private static final String PREFIX = Shacal2.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+ provider.addAlgorithm("Cipher.Shacal2", PREFIX + "$ECB");
+ provider.addAlgorithm("KeyGenerator.Shacal2", PREFIX + "$KeyGen");
+ provider.addAlgorithm("AlgorithmParameterGenerator.Shacal2", PREFIX + "$AlgParamGen");
+ provider.addAlgorithm("AlgorithmParameters.Shacal2", PREFIX + "$AlgParams");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
index 49656c2..c1b3d19 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
@@ -18,4 +18,17 @@ abstract class SymmetricAlgorithmProvider
provider.addAlgorithm("KeyGenerator." + algorithm + "-GMAC", keyGeneratorClassName);
provider.addAlgorithm("Alg.Alias.KeyGenerator." + algorithm + "GMAC", algorithm + "-GMAC");
}
+
+ protected void addPoly1305Algorithm(ConfigurableProvider provider,
+ String algorithm,
+ String algorithmClassName,
+ String keyGeneratorClassName)
+ {
+ provider.addAlgorithm("Mac.POLY1305-" + algorithm, algorithmClassName);
+ provider.addAlgorithm("Alg.Alias.Mac.POLY1305" + algorithm, "POLY1305-" + algorithm);
+
+ provider.addAlgorithm("KeyGenerator.POLY1305-" + algorithm, keyGeneratorClassName);
+ provider.addAlgorithm("Alg.Alias.KeyGenerator.POLY1305" + algorithm, "POLY1305-" + algorithm);
+ }
+
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Threefish.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Threefish.java
new file mode 100644
index 0000000..2970de6
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Threefish.java
@@ -0,0 +1,120 @@
+package org.bouncycastle.jcajce.provider.symmetric;
+
+import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.engines.ThreefishEngine;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters;
+import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
+
+public final class Threefish
+{
+ private Threefish()
+ {
+ }
+
+ public static class ECB_256
+ extends BaseBlockCipher
+ {
+ public ECB_256()
+ {
+ super(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256));
+ }
+ }
+
+ public static class ECB_512
+ extends BaseBlockCipher
+ {
+ public ECB_512()
+ {
+ super(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512));
+ }
+ }
+
+ public static class ECB_1024
+ extends BaseBlockCipher
+ {
+ public ECB_1024()
+ {
+ super(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024));
+ }
+ }
+
+ public static class KeyGen_256
+ extends BaseKeyGenerator
+ {
+ public KeyGen_256()
+ {
+ super("Threefish-256", 256, new CipherKeyGenerator());
+ }
+ }
+
+ public static class KeyGen_512
+ extends BaseKeyGenerator
+ {
+ public KeyGen_512()
+ {
+ super("Threefish-512", 512, new CipherKeyGenerator());
+ }
+ }
+
+ public static class KeyGen_1024
+ extends BaseKeyGenerator
+ {
+ public KeyGen_1024()
+ {
+ super("Threefish-1024", 1024, new CipherKeyGenerator());
+ }
+ }
+
+ public static class AlgParams_256
+ extends IvAlgorithmParameters
+ {
+ protected String engineToString()
+ {
+ return "Threefish-256 IV";
+ }
+ }
+
+ public static class AlgParams_512
+ extends IvAlgorithmParameters
+ {
+ protected String engineToString()
+ {
+ return "Threefish-512 IV";
+ }
+ }
+
+ public static class AlgParams_1024
+ extends IvAlgorithmParameters
+ {
+ protected String engineToString()
+ {
+ return "Threefish-1024 IV";
+ }
+ }
+
+ public static class Mappings
+ extends AlgorithmProvider
+ {
+ private static final String PREFIX = Threefish.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+ provider.addAlgorithm("Cipher.Threefish-256", PREFIX + "$ECB_256");
+ provider.addAlgorithm("Cipher.Threefish-512", PREFIX + "$ECB_512");
+ provider.addAlgorithm("Cipher.Threefish-1024", PREFIX + "$ECB_1024");
+ provider.addAlgorithm("KeyGenerator.Threefish-256", PREFIX + "$KeyGen_256");
+ provider.addAlgorithm("KeyGenerator.Threefish-512", PREFIX + "$KeyGen_512");
+ provider.addAlgorithm("KeyGenerator.Threefish-1024", PREFIX + "$KeyGen_1024");
+ provider.addAlgorithm("AlgorithmParameters.Threefish-256", PREFIX + "$AlgParams_256");
+ provider.addAlgorithm("AlgorithmParameters.Threefish-512", PREFIX + "$AlgParams_512");
+ provider.addAlgorithm("AlgorithmParameters.Threefish-1024", PREFIX + "$AlgParams_1024");
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
index 67b9f66..4c3ab1c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
@@ -3,6 +3,7 @@ package org.bouncycastle.jcajce.provider.symmetric;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherKeyGenerator;
import org.bouncycastle.crypto.engines.TwofishEngine;
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.GMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
@@ -53,6 +54,24 @@ public final class Twofish
}
}
+ public static class Poly1305
+ extends BaseMac
+ {
+ public Poly1305()
+ {
+ super(new org.bouncycastle.crypto.macs.Poly1305(new TwofishEngine()));
+ }
+ }
+
+ public static class Poly1305KeyGen
+ extends BaseKeyGenerator
+ {
+ public Poly1305KeyGen()
+ {
+ super("Poly1305-Twofish", 256, new Poly1305KeyGenerator());
+ }
+ }
+
/**
* PBEWithSHAAndTwofish-CBC
*/
@@ -107,6 +126,7 @@ public final class Twofish
provider.addAlgorithm("SecretKeyFactory.PBEWITHSHAANDTWOFISH-CBC", PREFIX + "$PBEWithSHAKeyFactory");
addGMacAlgorithm(provider, "Twofish", PREFIX + "$GMAC", PREFIX + "$KeyGen");
+ addPoly1305Algorithm(provider, "Twofish", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen");
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/XSalsa20.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/XSalsa20.java
new file mode 100644
index 0000000..5be0640
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/XSalsa20.java
@@ -0,0 +1,51 @@
+package org.bouncycastle.jcajce.provider.symmetric;
+
+import org.bouncycastle.crypto.CipherKeyGenerator;
+import org.bouncycastle.crypto.engines.XSalsa20Engine;
+import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
+import org.bouncycastle.jcajce.provider.symmetric.util.BaseStreamCipher;
+import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
+
+public final class XSalsa20
+{
+ private XSalsa20()
+ {
+ }
+
+ public static class Base
+ extends BaseStreamCipher
+ {
+ public Base()
+ {
+ super(new XSalsa20Engine(), 24);
+ }
+ }
+
+ public static class KeyGen
+ extends BaseKeyGenerator
+ {
+ public KeyGen()
+ {
+ super("XSalsa20", 256, new CipherKeyGenerator());
+ }
+ }
+
+ public static class Mappings
+ extends AlgorithmProvider
+ {
+ private static final String PREFIX = XSalsa20.class.getName();
+
+ public Mappings()
+ {
+ }
+
+ public void configure(ConfigurableProvider provider)
+ {
+
+ provider.addAlgorithm("Cipher.XSALSA20", PREFIX + "$Base");
+ provider.addAlgorithm("KeyGenerator.XSALSA20", PREFIX + "$KeyGen");
+
+ }
+ }
+}
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 17b66a5..943fa18 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
@@ -1,5 +1,7 @@
package org.bouncycastle.jcajce.provider.symmetric.util;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -20,6 +22,7 @@ import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.RC2ParameterSpec;
import javax.crypto.spec.RC5ParameterSpec;
+import org.bouncycastle.asn1.cms.GCMParameters;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
@@ -32,6 +35,7 @@ import org.bouncycastle.crypto.modes.CCMBlockCipher;
import org.bouncycastle.crypto.modes.CFBBlockCipher;
import org.bouncycastle.crypto.modes.CTSBlockCipher;
import org.bouncycastle.crypto.modes.EAXBlockCipher;
+import org.bouncycastle.crypto.modes.GCFBBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.modes.GOFBBlockCipher;
import org.bouncycastle.crypto.modes.OCBBlockCipher;
@@ -46,21 +50,24 @@ import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.paddings.TBCPadding;
import org.bouncycastle.crypto.paddings.X923Padding;
import org.bouncycastle.crypto.paddings.ZeroBytePadding;
+import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.ParametersWithSBox;
import org.bouncycastle.crypto.params.RC2Parameters;
import org.bouncycastle.crypto.params.RC5Parameters;
+import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
+import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.spec.GOST28147ParameterSpec;
-import org.bouncycastle.jce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.util.Strings;
public class BaseBlockCipher
extends BaseWrapCipher
implements PBE
{
+ private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec");
+
//
// specs we can handle.
//
@@ -70,13 +77,15 @@ public class BaseBlockCipher
RC5ParameterSpec.class,
IvParameterSpec.class,
PBEParameterSpec.class,
- GOST28147ParameterSpec.class
+ GOST28147ParameterSpec.class,
+ gcmSpecClass
};
private BlockCipher baseEngine;
private BlockCipherProvider engineProvider;
private GenericBlockCipher cipher;
private ParametersWithIV ivParam;
+ private AEADParameters aeadParams;
private int ivLength = 0;
@@ -87,6 +96,20 @@ 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)
{
@@ -105,6 +128,14 @@ public class BaseBlockCipher
}
protected BaseBlockCipher(
+ AEADBlockCipher engine)
+ {
+ baseEngine = engine.getUnderlyingCipher();
+ ivLength = baseEngine.getBlockSize();
+ cipher = new AEADGenericBlockCipher(engine);
+ }
+
+ protected BaseBlockCipher(
org.bouncycastle.crypto.BlockCipher engine,
int ivLength)
{
@@ -181,6 +212,18 @@ public class BaseBlockCipher
throw new RuntimeException(e.toString());
}
}
+ else if (aeadParams != null)
+ {
+ try
+ {
+ engineParams = AlgorithmParameters.getInstance("GCM", BouncyCastleProvider.PROVIDER_NAME);
+ engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize()).getEncoded());
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.toString());
+ }
+ }
}
return engineParams;
@@ -271,6 +314,12 @@ public class BaseBlockCipher
cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
new GOFBBlockCipher(baseEngine)));
}
+ else if (modeName.startsWith("GCFB"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
+ new GCFBBlockCipher(baseEngine)));
+ }
else if (modeName.startsWith("CTS"))
{
ivLength = baseEngine.getBlockSize();
@@ -278,14 +327,15 @@ public class BaseBlockCipher
}
else if (modeName.startsWith("CCM"))
{
- ivLength = baseEngine.getBlockSize();
+ ivLength = 13; // CCM nonce 7..13 bytes
cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine));
}
else if (modeName.startsWith("OCB"))
{
if (engineProvider != null)
{
- ivLength = baseEngine.getBlockSize();
+ // Nonce restricted to max 120 bits over 128 bit block cipher since draft-irtf-cfrg-ocb-03
+ ivLength = 15;
cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get()));
}
else
@@ -377,6 +427,7 @@ public class BaseBlockCipher
this.pbeSpec = null;
this.pbeAlgorithm = null;
this.engineParams = null;
+ this.aeadParams = null;
//
// basic key check
@@ -419,6 +470,18 @@ public class BaseBlockCipher
param = new ParametersWithIV(param, iv.getIV());
}
+ else if (params instanceof GOST28147ParameterSpec)
+ {
+ // need to pick up IV and SBox.
+ GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params;
+
+ param = new ParametersWithSBox(param, gost28147Param.getSbox());
+
+ if (gost28147Param.getIV() != null && ivLength != 0)
+ {
+ param = new ParametersWithIV(param, gost28147Param.getIV());
+ }
+ }
}
else if (params instanceof PBEParameterSpec)
{
@@ -528,12 +591,38 @@ public class BaseBlockCipher
ivParam = (ParametersWithIV)param;
}
}
+ else if (gcmSpecClass != null && gcmSpecClass.isInstance(params))
+ {
+ if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher))
+ {
+ throw new InvalidAlgorithmParameterException("GCMParameterSpec can only be used with AEAD modes.");
+ }
+
+ try
+ {
+ Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]);
+ Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]);
+
+ if (key instanceof RepeatedSecretKeySpec)
+ {
+ param = aeadParams = new AEADParameters(null, ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0]));
+ }
+ else
+ {
+ param = aeadParams = new AEADParameters(new KeyParameter(key.getEncoded()), ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0]));
+ }
+ }
+ catch (Exception e)
+ {
+ throw new InvalidAlgorithmParameterException("Cannot process GCMParameterSpec.");
+ }
+ }
else
{
throw new InvalidAlgorithmParameterException("unknown parameter type.");
}
- if ((ivLength != 0) && !(param instanceof ParametersWithIV))
+ if ((ivLength != 0) && !(param instanceof ParametersWithIV) && !(param instanceof AEADParameters))
{
SecureRandom ivRandom = random;
@@ -596,6 +685,11 @@ public class BaseBlockCipher
{
for (int i = 0; i != availableSpecs.length; i++)
{
+ if (availableSpecs[i] == null)
+ {
+ continue;
+ }
+
try
{
paramSpec = params.getParameterSpec(availableSpecs[i]);
@@ -634,6 +728,18 @@ public class BaseBlockCipher
}
}
+ protected void engineUpdateAAD(byte[] input, int offset, int length)
+ {
+ cipher.updateAAD(input, offset, length);
+ }
+
+ protected void engineUpdateAAD(ByteBuffer bytebuffer)
+ {
+ int offset = bytebuffer.arrayOffset() + bytebuffer.position();
+ int length = bytebuffer.limit() - bytebuffer.position();
+ engineUpdateAAD(bytebuffer.array(), offset, length);
+ }
+
protected byte[] engineUpdate(
byte[] input,
int inputOffset,
@@ -783,6 +889,8 @@ public class BaseBlockCipher
public int getUpdateOutputSize(int len);
+ public void updateAAD(byte[] input, int offset, int length);
+
public int processByte(byte in, byte[] out, int outOff)
throws DataLengthException;
@@ -844,6 +952,11 @@ public class BaseBlockCipher
return cipher.getUpdateOutputSize(len);
}
+ public void updateAAD(byte[] input, int offset, int length)
+ {
+ throw new UnsupportedOperationException("AAD is not supported in the current mode.");
+ }
+
public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
{
return cipher.processByte(in, out, outOff);
@@ -901,6 +1014,11 @@ public class BaseBlockCipher
return cipher.getUpdateOutputSize(len);
}
+ public void updateAAD(byte[] input, int offset, int length)
+ {
+ cipher.processAADBytes(input, offset, length);
+ }
+
public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
{
return cipher.processByte(in, out, outOff);
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 442dcdd..270d648 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
@@ -4,6 +4,9 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
import javax.crypto.MacSpi;
import javax.crypto.spec.IvParameterSpec;
@@ -13,6 +16,8 @@ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.crypto.params.SkeinParameters;
+import org.bouncycastle.jcajce.spec.SkeinParameterSpec;
public class BaseMac
extends MacSpi implements PBE
@@ -74,6 +79,10 @@ public class BaseMac
{
param = new ParametersWithIV(new KeyParameter(key.getEncoded()), ((IvParameterSpec)params).getIV());
}
+ else if (params instanceof SkeinParameterSpec)
+ {
+ param = new SkeinParameters.Builder(copyMap(((SkeinParameterSpec)params).getParameters())).setKey(key.getEncoded()).build();
+ }
else if (params == null)
{
param = new KeyParameter(key.getEncoded());
@@ -118,4 +127,18 @@ public class BaseMac
return out;
}
+
+ private static Hashtable copyMap(Map paramsMap)
+ {
+ Hashtable newTable = new Hashtable();
+
+ Iterator keys = paramsMap.keySet().iterator();
+ while (keys.hasNext())
+ {
+ Object key = keys.next();
+ newTable.put(key, paramsMap.get(key));
+ }
+
+ return newTable;
+ }
}
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 6feab0e..31ba38f 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
@@ -3,6 +3,7 @@ package org.bouncycastle.jcajce.provider.symmetric.util;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
import java.security.Key;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
@@ -201,7 +202,7 @@ public class BaseStreamCipher
}
else
{
- throw new IllegalArgumentException("unknown parameter type.");
+ throw new InvalidAlgorithmParameterException("unknown parameter type.");
}
if ((ivLength != 0) && !(param instanceof ParametersWithIV))
@@ -227,18 +228,25 @@ public class BaseStreamCipher
}
}
- switch (opmode)
+ try
+ {
+ switch (opmode)
+ {
+ case Cipher.ENCRYPT_MODE:
+ case Cipher.WRAP_MODE:
+ cipher.init(true, param);
+ break;
+ case Cipher.DECRYPT_MODE:
+ case Cipher.UNWRAP_MODE:
+ cipher.init(false, param);
+ break;
+ default:
+ throw new InvalidParameterException("unknown opmode " + opmode + " passed");
+ }
+ }
+ catch (Exception e)
{
- case Cipher.ENCRYPT_MODE:
- case Cipher.WRAP_MODE:
- cipher.init(true, param);
- break;
- case Cipher.DECRYPT_MODE:
- case Cipher.UNWRAP_MODE:
- cipher.init(false, param);
- break;
- default:
- System.out.println("eeek!");
+ throw new InvalidKeyException(e.getMessage());
}
}
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 f16de3c..fac3ead 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
@@ -72,7 +72,32 @@ public interface PBE
}
else if (type == PKCS5S2 || type == PKCS5S2_UTF8)
{
- generator = new PKCS5S2ParametersGenerator();
+ switch (hash)
+ {
+ case MD2:
+ generator = new PKCS5S2ParametersGenerator(new MD2Digest());
+ break;
+ case MD5:
+ generator = new PKCS5S2ParametersGenerator(new MD5Digest());
+ break;
+ case SHA1:
+ generator = new PKCS5S2ParametersGenerator(new SHA1Digest());
+ break;
+ case RIPEMD160:
+ generator = new PKCS5S2ParametersGenerator(new RIPEMD160Digest());
+ break;
+ case TIGER:
+ generator = new PKCS5S2ParametersGenerator(new TigerDigest());
+ break;
+ case SHA256:
+ generator = new PKCS5S2ParametersGenerator(new SHA256Digest());
+ break;
+ case GOST3411:
+ generator = new PKCS5S2ParametersGenerator(new GOST3411Digest());
+ break;
+ default:
+ throw new IllegalStateException("unknown digest scheme for PBE PKCS5S2 encryption.");
+ }
}
else if (type == PKCS12)
{
@@ -261,9 +286,9 @@ public interface PBE
key = convertPassword(type, keySpec);
generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
-
+
param = generator.generateDerivedMacParameters(keySize);
-
+
for (int i = 0; i != key.length; i++)
{
key[i] = 0;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/GOST28147ParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/GOST28147ParameterSpec.java
new file mode 100644
index 0000000..be341c4
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/GOST28147ParameterSpec.java
@@ -0,0 +1,108 @@
+package org.bouncycastle.jcajce.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.crypto.engines.GOST28147Engine;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * A parameter spec for the GOST-28147 cipher.
+ */
+public class GOST28147ParameterSpec
+ implements AlgorithmParameterSpec
+{
+ private byte[] iv = null;
+ private byte[] sBox = null;
+
+ public GOST28147ParameterSpec(
+ byte[] sBox)
+ {
+ this.sBox = new byte[sBox.length];
+
+ System.arraycopy(sBox, 0, this.sBox, 0, sBox.length);
+ }
+
+ public GOST28147ParameterSpec(
+ byte[] sBox,
+ byte[] iv)
+ {
+ this(sBox);
+ this.iv = new byte[iv.length];
+
+ System.arraycopy(iv, 0, this.iv, 0, iv.length);
+ }
+
+ public GOST28147ParameterSpec(
+ String sBoxName)
+ {
+ this.sBox = GOST28147Engine.getSBox(sBoxName);
+ }
+
+ public GOST28147ParameterSpec(
+ String sBoxName,
+ byte[] iv)
+ {
+ this(sBoxName);
+ this.iv = new byte[iv.length];
+
+ System.arraycopy(iv, 0, this.iv, 0, iv.length);
+ }
+
+ public GOST28147ParameterSpec(
+ ASN1ObjectIdentifier sBoxName,
+ byte[] iv)
+ {
+ this(getName(sBoxName));
+ this.iv = Arrays.clone(iv);
+ }
+
+ public byte[] getSbox()
+ {
+ return sBox;
+ }
+
+ /**
+ * Returns the IV or null if this parameter set does not contain an IV.
+ *
+ * @return the IV or null if this parameter set does not contain an IV.
+ */
+ public byte[] getIV()
+ {
+ if (iv == null)
+ {
+ return null;
+ }
+
+ byte[] tmp = new byte[iv.length];
+
+ System.arraycopy(iv, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ private static Map oidMappings = new HashMap();
+
+ static
+ {
+ oidMappings.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_A_ParamSet, "E-A");
+ oidMappings.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_B_ParamSet, "E-B");
+ oidMappings.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_C_ParamSet, "E-C");
+ oidMappings.put(CryptoProObjectIdentifiers.id_Gost28147_89_CryptoPro_D_ParamSet, "E-D");
+ }
+
+ private static String getName(ASN1ObjectIdentifier sBoxOid)
+ {
+ String sBoxName = (String)oidMappings.get(sBoxOid);
+
+ if (sBoxName == null)
+ {
+ throw new IllegalArgumentException("unknown OID: " + sBoxOid);
+ }
+
+ return sBoxName;
+ }
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java
new file mode 100644
index 0000000..214a5eb
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java
@@ -0,0 +1,23 @@
+package org.bouncycastle.jcajce.spec;
+
+import javax.crypto.spec.PBEKeySpec;
+
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class PBKDF2KeySpec
+ extends PBEKeySpec
+{
+ private AlgorithmIdentifier prf;
+
+ public PBKDF2KeySpec(char[] password, byte[] salt, int iterationCount, int keySize, AlgorithmIdentifier prf)
+ {
+ super(password, salt, iterationCount, keySize);
+
+ this.prf = prf;
+ }
+
+ public AlgorithmIdentifier getPrf()
+ {
+ return prf;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/RepeatedSecretKeySpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/RepeatedSecretKeySpec.java
new file mode 100644
index 0000000..6af15db
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/RepeatedSecretKeySpec.java
@@ -0,0 +1,34 @@
+package org.bouncycastle.jcajce.spec;
+
+
+import javax.crypto.SecretKey;
+
+/**
+ * A simple object to indicate that a symmetric cipher should reuse the
+ * last key provided.
+ */
+public class RepeatedSecretKeySpec
+ implements SecretKey
+{
+ private String algorithm;
+
+ public RepeatedSecretKeySpec(String algorithm)
+ {
+ this.algorithm = algorithm;
+ }
+
+ public String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public String getFormat()
+ {
+ return null;
+ }
+
+ public byte[] getEncoded()
+ {
+ return null;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/SkeinParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/SkeinParameterSpec.java
new file mode 100644
index 0000000..b43aa95
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/SkeinParameterSpec.java
@@ -0,0 +1,283 @@
+package org.bouncycastle.jcajce.spec;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.security.spec.AlgorithmParameterSpec;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Integers;
+
+/**
+ * Parameters for the Skein hash function - a series of byte[] strings identified by integer tags.
+ * <p/>
+ * Parameterised Skein can be used for:
+ * <ul>
+ * <li>MAC generation, by providing a {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setKey(byte[]) key}.</li>
+ * <li>Randomised hashing, by providing a {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setNonce(byte[]) nonce}.</li>
+ * <li>A hash function for digital signatures, associating a
+ * {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setPublicKey(byte[]) public key} with the message digest.</li>
+ * <li>A key derivation function, by providing a
+ * {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setKeyIdentifier(byte[]) key identifier}.</li>
+ * <li>Personalised hashing, by providing a
+ * {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setPersonalisation(java.util.Date, String, String) recommended format} or
+ * {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setPersonalisation(byte[]) arbitrary} personalisation string.</li>
+ * </ul>
+ *
+ * @see org.bouncycastle.crypto.digests.SkeinEngine
+ * @see org.bouncycastle.crypto.digests.SkeinDigest
+ * @see org.bouncycastle.crypto.macs.SkeinMac
+ */
+public class SkeinParameterSpec
+ implements AlgorithmParameterSpec
+{
+ /**
+ * The parameter type for a secret key, supporting MAC or KDF functions: {@value
+ * #PARAM_TYPE_KEY}.
+ */
+ public static final int PARAM_TYPE_KEY = 0;
+
+ /**
+ * The parameter type for the Skein configuration block: {@value #PARAM_TYPE_CONFIG}.
+ */
+ public static final int PARAM_TYPE_CONFIG = 4;
+
+ /**
+ * The parameter type for a personalisation string: {@value #PARAM_TYPE_PERSONALISATION}.
+ */
+ public static final int PARAM_TYPE_PERSONALISATION = 8;
+
+ /**
+ * The parameter type for a public key: {@value #PARAM_TYPE_PUBLIC_KEY}.
+ */
+ public static final int PARAM_TYPE_PUBLIC_KEY = 12;
+
+ /**
+ * The parameter type for a key identifier string: {@value #PARAM_TYPE_KEY_IDENTIFIER}.
+ */
+ public static final int PARAM_TYPE_KEY_IDENTIFIER = 16;
+
+ /**
+ * The parameter type for a nonce: {@value #PARAM_TYPE_NONCE}.
+ */
+ public static final int PARAM_TYPE_NONCE = 20;
+
+ /**
+ * The parameter type for the message: {@value #PARAM_TYPE_MESSAGE}.
+ */
+ public static final int PARAM_TYPE_MESSAGE = 48;
+
+ /**
+ * The parameter type for the output transformation: {@value #PARAM_TYPE_OUTPUT}.
+ */
+ public static final int PARAM_TYPE_OUTPUT = 63;
+
+ private Map parameters;
+
+ public SkeinParameterSpec()
+ {
+ this(new HashMap());
+ }
+
+ private SkeinParameterSpec(Map parameters)
+ {
+ this.parameters = Collections.unmodifiableMap(parameters);
+ }
+
+ /**
+ * Obtains a map of type (Integer) to value (byte[]) for the parameters tracked in this object.
+ */
+ public Map getParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_KEY key parameter}, or <code>null</code> if not
+ * set.
+ */
+ public byte[] getKey()
+ {
+ return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_KEY)));
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_PERSONALISATION personalisation parameter}, or
+ * <code>null</code> if not set.
+ */
+ public byte[] getPersonalisation()
+ {
+ return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_PERSONALISATION)));
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_PUBLIC_KEY public key parameter}, or
+ * <code>null</code> if not set.
+ */
+ public byte[] getPublicKey()
+ {
+ return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_PUBLIC_KEY)));
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_KEY_IDENTIFIER key identifier parameter}, or
+ * <code>null</code> if not set.
+ */
+ public byte[] getKeyIdentifier()
+ {
+ return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_KEY_IDENTIFIER)));
+ }
+
+ /**
+ * Obtains the value of the {@link #PARAM_TYPE_NONCE nonce parameter}, or <code>null</code> if
+ * not set.
+ */
+ public byte[] getNonce()
+ {
+ return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_NONCE)));
+ }
+
+ /**
+ * A builder for {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec}.
+ */
+ public static class Builder
+ {
+ private Map parameters = new HashMap();
+
+ public Builder()
+ {
+ }
+
+ public Builder(SkeinParameterSpec params)
+ {
+ Iterator keys = params.parameters.keySet().iterator();
+ while (keys.hasNext())
+ {
+ Integer key = (Integer)keys.next();
+ parameters.put(key, params.parameters.get(key));
+ }
+ }
+
+ /**
+ * Sets a parameters to apply to the Skein hash function.<br>
+ * Parameter types must be in the range 0,5..62, and cannot use the value {@value
+ * org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_MESSAGE} (reserved for message body).
+ * <p/>
+ * Parameters with type < {@value org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_MESSAGE} are processed before
+ * the message content, parameters with type > {@value org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_MESSAGE}
+ * are processed after the message and prior to output.
+ *
+ * @param type the type of the parameter, in the range 5..62.
+ * @param value the byte sequence of the parameter.
+ * @return
+ */
+ public Builder set(int type, byte[] value)
+ {
+ if (value == null)
+ {
+ throw new IllegalArgumentException("Parameter value must not be null.");
+ }
+ if ((type != PARAM_TYPE_KEY)
+ && (type <= PARAM_TYPE_CONFIG || type >= PARAM_TYPE_OUTPUT || type == PARAM_TYPE_MESSAGE))
+ {
+ throw new IllegalArgumentException("Parameter types must be in the range 0,5..47,49..62.");
+ }
+ if (type == PARAM_TYPE_CONFIG)
+ {
+ throw new IllegalArgumentException("Parameter type " + PARAM_TYPE_CONFIG
+ + " is reserved for internal use.");
+ }
+ this.parameters.put(Integers.valueOf(type), value);
+ return this;
+ }
+
+ /**
+ * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_KEY} parameter.
+ */
+ public Builder setKey(byte[] key)
+ {
+ return set(PARAM_TYPE_KEY, key);
+ }
+
+ /**
+ * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_PERSONALISATION} parameter.
+ */
+ public Builder setPersonalisation(byte[] personalisation)
+ {
+ return set(PARAM_TYPE_PERSONALISATION, personalisation);
+ }
+
+ /**
+ * Implements the recommended personalisation format for Skein defined in Section 4.11 of
+ * the Skein 1.3 specification.
+ * <p/>
+ * The format is <code>YYYYMMDD email@address distinguisher</code>, encoded to a byte
+ * sequence using UTF-8 encoding.
+ *
+ * @param date the date the personalised application of the Skein was defined.
+ * @param emailAddress the email address of the creation of the personalised application.
+ * @param distinguisher an arbitrary personalisation string distinguishing the application.
+ * @return
+ */
+ public Builder setPersonalisation(Date date, String emailAddress, String distinguisher)
+ {
+ try
+ {
+ final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ final OutputStreamWriter out = new OutputStreamWriter(bout, "UTF-8");
+ final DateFormat format = new SimpleDateFormat("YYYYMMDD");
+ out.write(format.format(date));
+ out.write(" ");
+ out.write(emailAddress);
+ out.write(" ");
+ out.write(distinguisher);
+ out.close();
+ return set(PARAM_TYPE_PERSONALISATION, bout.toByteArray());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("Byte I/O failed: " + e);
+ }
+ }
+
+ /**
+ * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_KEY_IDENTIFIER} parameter.
+ */
+ public Builder setPublicKey(byte[] publicKey)
+ {
+ return set(PARAM_TYPE_PUBLIC_KEY, publicKey);
+ }
+
+ /**
+ * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_KEY_IDENTIFIER} parameter.
+ */
+ public Builder setKeyIdentifier(byte[] keyIdentifier)
+ {
+ return set(PARAM_TYPE_KEY_IDENTIFIER, keyIdentifier);
+ }
+
+ /**
+ * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_NONCE} parameter.
+ */
+ public Builder setNonce(byte[] nonce)
+ {
+ return set(PARAM_TYPE_NONCE, nonce);
+ }
+
+ /**
+ * Constructs a new {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec} instance with the parameters provided to this
+ * builder.
+ */
+ public SkeinParameterSpec build()
+ {
+ return new SkeinParameterSpec(parameters);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java b/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java
index cab5a45..941f476 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/ECNamedCurveTable.java
@@ -1,13 +1,8 @@
package org.bouncycastle.jce;
import java.util.Enumeration;
-import java.util.Vector;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.nist.NISTNamedCurves;
-import org.bouncycastle.asn1.sec.SECNamedCurves;
-import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
@@ -26,12 +21,12 @@ public class ECNamedCurveTable
public static ECNamedCurveParameterSpec getParameterSpec(
String name)
{
- X9ECParameters ecP = X962NamedCurves.getByName(name);
+ X9ECParameters ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByName(name);
if (ecP == null)
{
try
{
- ecP = X962NamedCurves.getByOID(new ASN1ObjectIdentifier(name));
+ ecP = org.bouncycastle.asn1.x9.ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(name));
}
catch (IllegalArgumentException e)
{
@@ -41,43 +36,6 @@ public class ECNamedCurveTable
if (ecP == null)
{
- ecP = SECNamedCurves.getByName(name);
- if (ecP == null)
- {
- try
- {
- ecP = SECNamedCurves.getByOID(new ASN1ObjectIdentifier(name));
- }
- catch (IllegalArgumentException e)
- {
- // ignore - not an oid
- }
- }
- }
-
- if (ecP == null)
- {
- ecP = TeleTrusTNamedCurves.getByName(name);
- if (ecP == null)
- {
- try
- {
- ecP = TeleTrusTNamedCurves.getByOID(new ASN1ObjectIdentifier(name));
- }
- catch (IllegalArgumentException e)
- {
- // ignore - not an oid
- }
- }
- }
-
- if (ecP == null)
- {
- ecP = NISTNamedCurves.getByName(name);
- }
-
- if (ecP == null)
- {
return null;
}
@@ -97,23 +55,6 @@ public class ECNamedCurveTable
*/
public static Enumeration getNames()
{
- Vector v = new Vector();
-
- addEnumeration(v, X962NamedCurves.getNames());
- addEnumeration(v, SECNamedCurves.getNames());
- addEnumeration(v, NISTNamedCurves.getNames());
- addEnumeration(v, TeleTrusTNamedCurves.getNames());
-
- return v.elements();
- }
-
- private static void addEnumeration(
- Vector v,
- Enumeration e)
- {
- while (e.hasMoreElements())
- {
- v.addElement(e.nextElement());
- }
+ return org.bouncycastle.asn1.x9.ECNamedCurveTable.getNames();
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/ECPointUtil.java b/bcprov/src/main/java/org/bouncycastle/jce/ECPointUtil.java
index 3518583..5ff966a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/ECPointUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/ECPointUtil.java
@@ -50,7 +50,7 @@ public class ECPointUtil
}
org.bouncycastle.math.ec.ECPoint p = c.decodePoint(encoded);
-
- return new ECPoint(p.getX().toBigInteger(), p.getY().toBigInteger());
+
+ return new ECPoint(p.getAffineXCoord().toBigInteger(), p.getAffineYCoord().toBigInteger());
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java b/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java
index efa0f66..ddd38e8 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/X509Principal.java
@@ -19,6 +19,7 @@ import org.bouncycastle.asn1.x509.X509Name;
* PrincipalUtil class.
* </p>
* @see org.bouncycastle.jce.PrincipalUtil
+ * @deprecated use the X500Name class.
*/
public class X509Principal
extends X509Name
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/examples/package.html b/bcprov/src/main/java/org/bouncycastle/jce/examples/package.html
deleted file mode 100644
index 96b3193..0000000
--- a/bcprov/src/main/java/org/bouncycastle/jce/examples/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Example classes for use with the JCE.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/interfaces/package.html b/bcprov/src/main/java/org/bouncycastle/jce/interfaces/package.html
deleted file mode 100644
index bacde6c..0000000
--- a/bcprov/src/main/java/org/bouncycastle/jce/interfaces/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Interfaces for supporting Elliptic Curve Keys, El Gamal, and PKCS12 attributes.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/package.html b/bcprov/src/main/java/org/bouncycastle/jce/package.html
deleted file mode 100644
index 52ef3bf..0000000
--- a/bcprov/src/main/java/org/bouncycastle/jce/package.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Utility classes for use with the JCE.
-<p>
-The classes in this package support the generation of certificates and PKCS10 signing requests.
-<p>
-Note: the PKCS7 class is deprecated, for a fuller version of CMS see the cms package distributed
-with the BC mail API.
-</body>
-</html>
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 0433965..dc7db18 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
@@ -44,7 +44,7 @@ import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
public final class BouncyCastleProvider extends Provider
implements ConfigurableProvider
{
- private static String info = "BouncyCastle Security Provider v1.49";
+ private static String info = "BouncyCastle Security Provider v1.50";
public static final String PROVIDER_NAME = "BC";
@@ -69,8 +69,10 @@ public final class BouncyCastleProvider extends Provider
private static final String[] SYMMETRIC_CIPHERS =
{
- "AES", "ARC4", "Blowfish", "Camellia", "CAST5", "CAST6", "DES", "DESede", "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA",
- "Noekeon", "RC2", "RC5", "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Skipjack", "TEA", "Twofish", "VMPC", "VMPCKSA3", "XTEA"
+ "AES", "ARC4", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede",
+ "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA", "Noekeon", "RC2", "RC5",
+ "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "TEA", "Twofish", "Threefish",
+ "VMPC", "VMPCKSA3", "XTEA", "XSalsa20"
};
/*
@@ -96,11 +98,11 @@ public final class BouncyCastleProvider extends Provider
private static final String DIGEST_PACKAGE = "org.bouncycastle.jcajce.provider.digest.";
private static final String[] DIGESTS =
{
- "GOST3411", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "Tiger", "Whirlpool"
+ "GOST3411", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "Skein", "SM3", "Tiger", "Whirlpool"
};
/*
- * Configurable digests
+ * Configurable keystores
*/
private static final String KEYSTORE_PACKAGE = "org.bouncycastle.jcajce.provider.keystore.";
private static final String[] KEYSTORES =
@@ -115,7 +117,7 @@ public final class BouncyCastleProvider extends Provider
*/
public BouncyCastleProvider()
{
- super(PROVIDER_NAME, 1.49, info);
+ super(PROVIDER_NAME, 1.50, info);
AccessController.doPrivileged(new PrivilegedAction()
{
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 3175237..63bb6d8 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPrivateKey.java
@@ -125,8 +125,8 @@ public class JCEECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -156,8 +156,8 @@ public class JCEECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -168,8 +168,8 @@ public class JCEECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
spec.getN(),
spec.getH().intValue());
}
@@ -212,8 +212,8 @@ public class JCEECPrivateKey
ECGOST3410NamedCurves.getName(oid),
ellipticCurve,
new ECPoint(
- gParam.getG().getX().toBigInteger(),
- gParam.getG().getY().toBigInteger()),
+ gParam.getG().getAffineXCoord().toBigInteger(),
+ gParam.getG().getAffineYCoord().toBigInteger()),
gParam.getN(),
gParam.getH());
}
@@ -225,8 +225,8 @@ public class JCEECPrivateKey
ECUtil.getCurveName(oid),
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH());
}
@@ -243,8 +243,8 @@ public class JCEECPrivateKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
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 00df81f..4bf2e68 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEECPublicKey.java
@@ -88,7 +88,7 @@ public class JCEECPublicKey
{
org.bouncycastle.jce.spec.ECParameterSpec s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
- q = s.getCurve().createPoint(q.getX().toBigInteger(), q.getY().toBigInteger(), false);
+ q = s.getCurve().createPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger(), false);
}
this.ecSpec = null;
}
@@ -157,8 +157,8 @@ public class JCEECPublicKey
return new ECParameterSpec(
ellipticCurve,
new ECPoint(
- dp.getG().getX().toBigInteger(),
- dp.getG().getY().toBigInteger()),
+ dp.getG().getAffineXCoord().toBigInteger(),
+ dp.getG().getAffineYCoord().toBigInteger()),
dp.getN(),
dp.getH().intValue());
}
@@ -221,8 +221,8 @@ public class JCEECPublicKey
ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
ellipticCurve,
new ECPoint(
- spec.getG().getX().toBigInteger(),
- spec.getG().getY().toBigInteger()),
+ spec.getG().getAffineXCoord().toBigInteger(),
+ spec.getG().getAffineYCoord().toBigInteger()),
spec.getN(), spec.getH());
}
@@ -244,8 +244,8 @@ public class JCEECPublicKey
ECUtil.getCurveName(oid),
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH());
}
@@ -264,8 +264,8 @@ public class JCEECPublicKey
this.ecSpec = new ECParameterSpec(
ellipticCurve,
new ECPoint(
- ecP.getG().getX().toBigInteger(),
- ecP.getG().getY().toBigInteger()),
+ ecP.getG().getAffineXCoord().toBigInteger(),
+ ecP.getG().getAffineYCoord().toBigInteger()),
ecP.getN(),
ecP.getH().intValue());
}
@@ -344,8 +344,8 @@ public class JCEECPublicKey
}
}
- BigInteger bX = this.q.getX().toBigInteger();
- BigInteger bY = this.q.getY().toBigInteger();
+ BigInteger bX = this.q.getAffineXCoord().toBigInteger();
+ BigInteger bY = this.q.getAffineYCoord().toBigInteger();
byte[] encKey = new byte[64];
extractBytes(encKey, 0, bX);
@@ -391,7 +391,7 @@ public class JCEECPublicKey
ECCurve curve = this.engineGetQ().getCurve();
ASN1OctetString p = (ASN1OctetString)
- new X9ECPoint(curve.createPoint(this.getQ().getX().toBigInteger(), this.getQ().getY().toBigInteger(), withCompression)).toASN1Primitive();
+ new X9ECPoint(curve.createPoint(this.getQ().getAffineXCoord().toBigInteger(), this.getQ().getAffineYCoord().toBigInteger(), withCompression)).toASN1Primitive();
info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets());
}
@@ -432,7 +432,7 @@ public class JCEECPublicKey
public ECPoint getW()
{
- return new ECPoint(q.getX().toBigInteger(), q.getY().toBigInteger());
+ return new ECPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger());
}
public org.bouncycastle.math.ec.ECPoint getQ()
@@ -441,11 +441,11 @@ public class JCEECPublicKey
{
if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp)
{
- return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord());
}
else
{
- return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getX(), q.getY());
+ return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord());
}
}
@@ -473,8 +473,8 @@ public class JCEECPublicKey
String nl = System.getProperty("line.separator");
buf.append("EC Public Key").append(nl);
- buf.append(" X: ").append(this.q.getX().toBigInteger().toString(16)).append(nl);
- buf.append(" Y: ").append(this.q.getY().toBigInteger().toString(16)).append(nl);
+ buf.append(" X: ").append(this.q.getAffineXCoord().toBigInteger().toString(16)).append(nl);
+ buf.append(" Y: ").append(this.q.getAffineYCoord().toBigInteger().toString(16)).append(nl);
return buf.toString();
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java
index d5c3700..7e76a89 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLEntryObject.java
@@ -211,6 +211,23 @@ public class X509CRLEntryObject extends X509CRLEntry
return hashValue;
}
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (o instanceof X509CRLEntryObject)
+ {
+ X509CRLEntryObject other = (X509CRLEntryObject)o;
+
+ return this.c.equals(other.c);
+ }
+
+ return super.equals(this);
+ }
+
public byte[] getEncoded()
throws CRLException
{
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java
index cd83211..b5b4f13 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java
@@ -59,6 +59,8 @@ public class X509CRLObject
private String sigAlgName;
private byte[] sigAlgParams;
private boolean isIndirect;
+ private boolean isHashCodeSet = false;
+ private int hashCodeValue;
static boolean isIndirectCRL(X509CRL crl)
throws CRLException
@@ -520,7 +522,7 @@ public class X509CRLObject
throw new RuntimeException("X.509 CRL used with non X.509 Cert");
}
- TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
+ Enumeration certs = c.getRevokedCertificateEnumeration();
X500Name caName = c.getIssuer();
@@ -528,11 +530,13 @@ public class X509CRLObject
{
BigInteger serial = ((X509Certificate)cert).getSerialNumber();
- for (int i = 0; i < certs.length; i++)
+ while (certs.hasMoreElements())
{
- if (isIndirect && certs[i].hasExtensions())
+ TBSCertList.CRLEntry entry = TBSCertList.CRLEntry.getInstance(certs.nextElement());
+
+ if (isIndirect && entry.hasExtensions())
{
- Extension currentCaName = certs[i].getExtensions().getExtension(Extension.certificateIssuer);
+ Extension currentCaName = entry.getExtensions().getExtension(Extension.certificateIssuer);
if (currentCaName != null)
{
@@ -540,7 +544,7 @@ public class X509CRLObject
}
}
- if (certs[i].getUserCertificate().getValue().equals(serial))
+ if (entry.getUserCertificate().getValue().equals(serial))
{
X500Name issuer;
@@ -572,5 +576,50 @@ public class X509CRLObject
return false;
}
+
+ public boolean equals(Object other)
+ {
+ if (this == other)
+ {
+ return true;
+ }
+
+ if (!(other instanceof X509CRL))
+ {
+ return false;
+ }
+
+ if (other instanceof X509CRLObject)
+ {
+ X509CRLObject crlObject = (X509CRLObject)other;
+
+ if (isHashCodeSet)
+ {
+ boolean otherIsHashCodeSet = crlObject.isHashCodeSet;
+ if (otherIsHashCodeSet)
+ {
+ if (crlObject.hashCodeValue != hashCodeValue)
+ {
+ return false;
+ }
+ }
+ }
+
+ return this.c.equals(crlObject.c);
+ }
+
+ return super.equals(other);
+ }
+
+ public int hashCode()
+ {
+ if (!isHashCodeSet)
+ {
+ isHashCodeSet = true;
+ hashCodeValue = super.hashCode();
+ }
+
+ return hashCodeValue;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/AEADTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/AEADTest.java
new file mode 100644
index 0000000..d2f1405
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/AEADTest.java
@@ -0,0 +1,241 @@
+package org.bouncycastle.jce.provider.test;
+
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.asn1.cms.GCMParameters;
+import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
+
+public class AEADTest extends SimpleTest
+{
+
+ // EAX test vector from EAXTest
+ private byte[] K2 = Hex.decode("91945D3F4DCBEE0BF45EF52255F095A4");
+ private byte[] N2 = Hex.decode("BECAF043B0A23D843194BA972C66DEBD");
+ private byte[] A2 = Hex.decode("FA3BFD4806EB53FA");
+ private byte[] P2 = Hex.decode("F7FB");
+ private byte[] C2 = Hex.decode("19DD5C4C9331049D0BDAB0277408F67967E5");
+ // C2 with only 64bit MAC (default for EAX)
+ private byte[] C2_short = Hex.decode("19DD5C4C9331049D0BDA");
+
+ private byte[] KGCM = Hex.decode("00000000000000000000000000000000");
+ private byte[] NGCM = Hex.decode("000000000000000000000000");
+ private byte[] CGCM = Hex.decode("58e2fccefa7e3061367f1d57a4e7455a");
+
+ public String getName()
+ {
+ return "AEAD";
+ }
+
+ public void performTest() throws Exception
+ {
+ try
+ {
+ this.getClass().getClassLoader().loadClass("javax.crypto.spec.GCMParameterSpec");
+
+ checkCipherWithAD(K2, N2, A2, P2, C2_short);
+ testGCMParameterSpec(K2, N2, A2, P2, C2);
+ testGCMParameterSpecWithRepeatKey(K2, N2, A2, P2, C2);
+ testGCMGeneric(KGCM, NGCM, new byte[0], new byte[0], CGCM);
+ }
+ catch (ClassNotFoundException e)
+ {
+ System.err.println("AEADTest disabled due to JDK");
+ }
+ }
+
+ private void checkCipherWithAD(byte[] K,
+ byte[] N,
+ byte[] A,
+ byte[] P,
+ byte[] C) throws InvalidKeyException,
+ NoSuchAlgorithmException, NoSuchPaddingException,
+ IllegalBlockSizeException, BadPaddingException,
+ InvalidAlgorithmParameterException, NoSuchProviderException
+ {
+ Cipher eax = Cipher.getInstance("AES/EAX/NoPadding", "BC");
+ SecretKeySpec key = new SecretKeySpec(K, "AES");
+ IvParameterSpec iv = new IvParameterSpec(N);
+ eax.init(Cipher.ENCRYPT_MODE, key, iv);
+
+ eax.updateAAD(A);
+ byte[] c = eax.doFinal(P);
+
+ if (!areEqual(C, c))
+ {
+ fail("JCE encrypt with additional data failed.");
+ }
+
+ eax.init(Cipher.DECRYPT_MODE, key, iv);
+ eax.updateAAD(A);
+ byte[] p = eax.doFinal(C);
+
+ if (!areEqual(P, p))
+ {
+ fail("JCE decrypt with additional data failed.");
+ }
+ }
+
+ private void testGCMParameterSpec(byte[] K,
+ byte[] N,
+ byte[] A,
+ byte[] P,
+ byte[] C)
+ throws InvalidKeyException,
+ NoSuchAlgorithmException, NoSuchPaddingException,
+ IllegalBlockSizeException, BadPaddingException,
+ InvalidAlgorithmParameterException, NoSuchProviderException, IOException
+ {
+ Cipher eax = Cipher.getInstance("AES/EAX/NoPadding", "BC");
+ SecretKeySpec key = new SecretKeySpec(K, "AES");
+
+ // GCMParameterSpec mapped to AEADParameters and overrides default MAC
+ // size
+ GCMParameterSpec spec = new GCMParameterSpec(128, N);
+ eax.init(Cipher.ENCRYPT_MODE, key, spec);
+
+ eax.updateAAD(A);
+ byte[] c = eax.doFinal(P);
+
+ if (!areEqual(C, c))
+ {
+ fail("JCE encrypt with additional data and GCMParameterSpec failed.");
+ }
+
+ eax.init(Cipher.DECRYPT_MODE, key, spec);
+ eax.updateAAD(A);
+ byte[] p = eax.doFinal(C);
+
+ if (!areEqual(P, p))
+ {
+ fail("JCE decrypt with additional data and GCMParameterSpec failed.");
+ }
+
+ AlgorithmParameters algParams = eax.getParameters();
+
+ byte[] encParams = algParams.getEncoded();
+
+ GCMParameters gcmParameters = GCMParameters.getInstance(encParams);
+
+ if (!Arrays.areEqual(spec.getIV(), gcmParameters.getNonce()) || spec.getTLen() != gcmParameters.getIcvLen())
+ {
+ fail("parameters mismatch");
+ }
+ }
+
+ private void testGCMParameterSpecWithRepeatKey(byte[] K,
+ byte[] N,
+ byte[] A,
+ byte[] P,
+ byte[] C)
+ throws InvalidKeyException, NoSuchAlgorithmException,
+ NoSuchPaddingException, IllegalBlockSizeException,
+ BadPaddingException, InvalidAlgorithmParameterException, NoSuchProviderException, IOException
+ {
+ Cipher eax = Cipher.getInstance("AES/EAX/NoPadding", "BC");
+ SecretKeySpec key = new SecretKeySpec(K, "AES");
+ GCMParameterSpec spec = new GCMParameterSpec(128, N);
+ eax.init(Cipher.ENCRYPT_MODE, key, spec);
+
+ eax.updateAAD(A);
+ byte[] c = eax.doFinal(P);
+
+ if (!areEqual(C, c))
+ {
+ fail("JCE encrypt with additional data and RepeatedSecretKeySpec failed.");
+ }
+
+ // Check GCMParameterSpec handling knows about RepeatedSecretKeySpec
+ eax.init(Cipher.DECRYPT_MODE, new RepeatedSecretKeySpec("AES"), spec);
+ eax.updateAAD(A);
+ byte[] p = eax.doFinal(C);
+
+ if (!areEqual(P, p))
+ {
+ fail("JCE decrypt with additional data and RepeatedSecretKeySpec failed.");
+ }
+
+ AlgorithmParameters algParams = eax.getParameters();
+
+ byte[] encParams = algParams.getEncoded();
+
+ GCMParameters gcmParameters = GCMParameters.getInstance(encParams);
+
+ if (!Arrays.areEqual(spec.getIV(), gcmParameters.getNonce()) || spec.getTLen() != gcmParameters.getIcvLen())
+ {
+ fail("parameters mismatch");
+ }
+ }
+
+ private void testGCMGeneric(byte[] K,
+ byte[] N,
+ byte[] A,
+ byte[] P,
+ byte[] C)
+ throws InvalidKeyException,
+ NoSuchAlgorithmException, NoSuchPaddingException,
+ IllegalBlockSizeException, BadPaddingException,
+ InvalidAlgorithmParameterException, NoSuchProviderException, IOException
+ {
+ Cipher eax = Cipher.getInstance("AES/GCM/NoPadding", "BC");
+ SecretKeySpec key = new SecretKeySpec(K, "AES");
+
+ // GCMParameterSpec mapped to AEADParameters and overrides default MAC
+ // size
+ GCMParameterSpec spec = new GCMParameterSpec(128, N);
+ eax.init(Cipher.ENCRYPT_MODE, key, spec);
+
+ eax.updateAAD(A);
+ byte[] c = eax.doFinal(P);
+
+ if (!areEqual(C, c))
+ {
+ fail("JCE encrypt with additional data and GCMParameterSpec failed.");
+ }
+
+ eax = Cipher.getInstance("GCM", "BC");
+ eax.init(Cipher.DECRYPT_MODE, key, spec);
+ eax.updateAAD(A);
+ byte[] p = eax.doFinal(C);
+
+ if (!areEqual(P, p))
+ {
+ fail("JCE decrypt with additional data and GCMParameterSpec failed.");
+ }
+
+ AlgorithmParameters algParams = eax.getParameters();
+
+ byte[] encParams = algParams.getEncoded();
+
+ GCMParameters gcmParameters = GCMParameters.getInstance(encParams);
+
+ if (!Arrays.areEqual(spec.getIV(), gcmParameters.getNonce()) || spec.getTLen() != gcmParameters.getIcvLen())
+ {
+ fail("parameters mismatch");
+ }
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ Security.addProvider(new BouncyCastleProvider());
+
+ runTest(new AEADTest());
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/AESSICTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/AESSICTest.java
index 61f7995..ae6d7bc 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/AESSICTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/AESSICTest.java
@@ -7,8 +7,8 @@ import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
+import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.spec.RepeatedSecretKeySpec;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.SimpleTest;
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/BlockCipherTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/BlockCipherTest.java
index 30489bf..0c9cf01 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/BlockCipherTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/BlockCipherTest.java
@@ -1,22 +1,5 @@
package org.bouncycastle.jce.provider.test;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
-
-import javax.crypto.Cipher;
-import javax.crypto.CipherInputStream;
-import javax.crypto.CipherOutputStream;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.ShortBufferException;
-import javax.crypto.spec.DESedeKeySpec;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.RC2ParameterSpec;
-import javax.crypto.spec.RC5ParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -33,6 +16,24 @@ import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.DESedeKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.RC2ParameterSpec;
+import javax.crypto.spec.RC5ParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
+
/**
* basic test class for a block cipher, basically this just exercises the provider, and makes sure we
* are behaving sensibly, correctness of the implementation is shown in the lightweight test classes.
@@ -204,6 +205,12 @@ public class BlockCipherTest
"6cd6f7c5d2c655556d7a9e98a1696d1875e9f1b2fc991e28a2d55b56861e80bd",
"Twofish/OFB/NoPadding",
"821c54b1b54ae113cf74595eefe10c83b61c9682fc81f92c52f39a3a693f88b8",
+ "Threefish-256/OFB/NoPadding",
+ "546ea995dd302f1efcb1f27d14bad468280a3a7994c2af75dfdf1e9fc5ef2373",
+ "Threefish-512/OFB/NoPadding",
+ "152df966484ecc2e9ddfc386559732f7f632e4008920804a1bde4efcf2e6e2f2",
+ "Threefish-1024/OFB/NoPadding",
+ "03953ac751a7377812c6e3e4d14b36c6953f9b390acaa892811c10001c9be454",
"RC2/OFB/NoPadding",
"0a07cb78537cb04c0c74e28a7b86b80f80acadf87d6ef32792f1a8cf74b39f74",
"RC5/OFB/NoPadding",
@@ -220,6 +227,12 @@ public class BlockCipherTest
"6ca6078755b263f09787d830b6fda7b7748494634bdc73ab68540cf9f6b7eccf",
"Twofish/OFB8/NoPadding",
"825dcec234ad52253d6e064b0d769bc04b1142435933f4a510ffc20d70095a88",
+ "Threefish-256/OFB8/NoPadding",
+ "545fbd92313512127218262dd4394569aca96ba122e1432b661ecfc01af3a25c",
+ "Threefish-512/OFB8/NoPadding",
+ "15f6e7d215662c525ea982cab56409cf833157e1af06edd57a13c71487904fea",
+ "Threefish-1024/OFB8/NoPadding",
+ "03d80b67ff7139d9dd8b07280642f94074496e5fc37b1ba1f8593cdf64a1e4ca",
"RC2/OFB8/NoPadding",
"0aa26c6f6a820fe7d38da97085995ad62e2e293323a76300fcd4eb572810f7c6",
"RC5/OFB8/NoPadding",
@@ -236,6 +249,12 @@ public class BlockCipherTest
"6cd6f7c5d2c6555561167fe9b10665102206869339122f1ed89efa4a985397f6",
"Twofish/CFB/NoPadding",
"821c54b1b54ae113cf74595eefe10c8308b7a438277de4f40948ac2d172d53d2",
+ "Threefish-256/CFB/NoPadding",
+ "546ea995dd302f1efcb1f27d14bad468280a3a7994c2af75dfdf1e9fc5ef2373",
+ "Threefish-512/CFB/NoPadding",
+ "152df966484ecc2e9ddfc386559732f7f632e4008920804a1bde4efcf2e6e2f2",
+ "Threefish-1024/CFB/NoPadding",
+ "03953ac751a7377812c6e3e4d14b36c6953f9b390acaa892811c10001c9be454",
"RC2/CFB/NoPadding",
"0a07cb78537cb04ca1401450d5cd411c7da7fa5b6baaa17bb2137bd95c9f26a5",
"RC5/CFB/NoPadding",
@@ -252,6 +271,12 @@ public class BlockCipherTest
"6ca63aaada9188d2410c07513cc0736b9888770768c25a5befc776beea5bdc4c",
"Twofish/CFB8/NoPadding",
"825d12af040721cf5ed4a4798647837ac5eb14d752aace28728aeb37b2010abd",
+ "Threefish-256/CFB8/NoPadding",
+ "545fbf0a4b925f399cf7540f1cc1cc6012e329ab2d4db0aa0dfa29ee2a2019d1",
+ "Threefish-512/CFB8/NoPadding",
+ "15f695964f20b95ed72afad75f905788839c53bed2ae5fdfdfb13e3241fd7f94",
+ "Threefish-1024/CFB8/NoPadding",
+ "03d897c89e740d2254f717b73315151d9a34c829e4162232b3cd5f5158ff367b",
"RC2/CFB8/NoPadding",
"0aa227f94be3a32ff927c5d25647ea41d7c2a1e94012fc7f2ad6767b9664bce5",
"RC5/CFB8/NoPadding",
@@ -265,7 +290,29 @@ public class BlockCipherTest
"Twofish/ECB/TBCPadding",
"70336d9c9718a8a2ced1b19deed973a3c58af7ea71a69e7efc4df082dca581c019d7daa58d02b89aab6e8c0d17202439",
"RC2/ECB/TBCPadding",
- "eb5b889bbcced12eb6b1a3da6a3d965bba66a5edfdd4c8a6b6b1a3da6a3d965b6b5359ba5e69b179"
+ "eb5b889bbcced12eb6b1a3da6a3d965bba66a5edfdd4c8a6b6b1a3da6a3d965b6b5359ba5e69b179",
+ "DES/CTR/NoPadding",
+ "537572e480c1714fb47081d35eb18eaca9e0a5aee982f105438a0db6cece1f6d",
+ "DESede/CTR/NoPadding",
+ "481e9872acea7fcfa93b7d4e34ec7bab340c10faba2e43b879d40d38e07c422d",
+ "SKIPJACK/CTR/NoPadding",
+ "71143a124e3a0cdeee98a7b843baa05bd1d59faee8ec9b89880e070314a04cc2",
+ "Blowfish/CTR/NoPadding",
+ "6cd6f7c5d2c65555d2b31f8614f54ec654f5e7888d515008d59302c3edfcc6cb",
+ "Twofish/CTR/NoPadding",
+ "821c54b1b54ae113cf74595eefe10c83d09e95d4599190b9bbd5bc71dd703730",
+ "Threefish-256/CTR/NoPadding",
+ "546ea995dd302f1efcb1f27d14bad468280a3a7994c2af75dfdf1e9fc5ef2373",
+ "Threefish-512/CTR/NoPadding",
+ "152df966484ecc2e9ddfc386559732f7f632e4008920804a1bde4efcf2e6e2f2",
+ "Threefish-1024/CTR/NoPadding",
+ "03953ac751a7377812c6e3e4d14b36c6953f9b390acaa892811c10001c9be454",
+ "RC2/CTR/NoPadding",
+ "0a07cb78537cb04c8c5a0a39a15977a7eb19f3c48a42759c234868c391a99c63",
+ "RC5/CTR/NoPadding",
+ "c62b233df296283b97f17364d5f69a1ff91f46659cf9856caefd322a936203a7",
+ "IDEA/CTR/NoPadding",
+ "dd447da3cbdcf81f4694ab7715d79e3f90af5682e8c318b8f7dadbed6b5c9714",
};
static String[] cipherTests2 =
@@ -280,8 +327,127 @@ public class BlockCipherTest
"60fa2f8fae5aa2a38e9ac77d0246726b32df660db51a710ceb7511e451"
};
+ static String[] cipherTestsLargeBlock =
+ {
+ "Threefish-256",
+ "9f82b577cf4cca7a504e9f7a2cd7dbb4ef4ac167c716fca19ab1211f195f610f" +
+ "9f82b577cf4cca7a504e9f7a2cd7dbb4ef4ac167c716fca19ab1211f195f610f" +
+ "9f82b577cf4cca7a504e9f7a2cd7dbb4ef4ac167c716fca19ab1211f195f610f" +
+ "9f82b577cf4cca7a504e9f7a2cd7dbb4ef4ac167c716fca19ab1211f195f610f" +
+ "31533aa864e6a40edc3e24b36260d94374893dc2e479793292e29c18a6ee01a9",
+ "Threefish-512",
+ "35d0c46770ebb3bf62fadd48765db209df215d7cd18a8b18d11625e70067e1fa" +
+ "bb98982312ce1fdfccae1a59408e1d5418b400a7bf0d1c4e9ea4afa4395886d7" +
+ "35d0c46770ebb3bf62fadd48765db209df215d7cd18a8b18d11625e70067e1fa" +
+ "bb98982312ce1fdfccae1a59408e1d5418b400a7bf0d1c4e9ea4afa4395886d7" +
+ "ad7ec86b2137af1ddb64794d714c4e1d7b687b19fc9781ef887a0ad7f88e18fc" +
+ "1baa6123ec8bc497e7eb7b5090cfd756fd5333425ed5a240cb96735dea9713d9",
+ "Threefish-1024",
+ "df6d789e301c6a5e22e0cff0b44666630d44ce774a41b628ebaff6adc86d9e66" +
+ "af50a282a4313552bc9b861cb286ab569e2e23b1c97cdb5cb1fde1bacfba9bfb" +
+ "de3b443218e16b6038537b3d803ff5dbd26b13c177a5bfb597ffccca142a5905" +
+ "8c0f74623daa96bff95b716674701034e7947ce0541426fa5177bc1a519b23ba" +
+ "462f1724989612e49ca5e92a0129ec7be576846fe2616664674e16a29ce8679c" +
+ "0adda9034fbd652910c2ae5afacde10281ab18dbeeb83464dc21ff66b0d358ff" +
+ "2328c73aca59e9095a7bca94acc79d10038eab6ef865545bcf73f4caeeba1844" +
+ "6add98350c8276e5abfb8709bb6c01ef3297b862818a4996b744f375b9126e5c",
+ "Threefish-256/CBC/NoPadding",
+ "1c46830ef0a43a0869bf070a87f0d4e63f2458edfa5654bafd8520358dae8bf9" +
+ "2a8c039d41e87bb65a907331dde317450d38aba6cb3885bfbe0aee148503e37b" +
+ "973c5e8a16c4309f7a4229d9943ab403082b5836431b9d1646b619f368e057b3" +
+ "0931ce1b791b641dd3e79f2b536897f3c537e3b4588dc03c3888f9bab3bc7a0e",
+ "Threefish-512/CBC/NoPadding",
+ "caee9b663eba4663de1cd6f17ffc51dc8b808c95f91e12a818ab31436985830b" +
+ "3aa886a93e53849d34e713f36db52bac3557b137328434f41f825f3948a611c6" +
+ "03efe066d8d6d57b15b04729632de0ce5636b8ccd28219ac17ef836734556e15" +
+ "e90356111279412a814b660150323a416138b2b62942f2d0cd08ee0bb45b0dd7",
+ "Threefish-1024/CBC/NoPadding",
+ "7540a8fe54a1a1d117ba1f970a12002cf9e24477daef9439dfc43b79a88a9e87" +
+ "b59be63aa448b4e02e8b9a6464419c35b0b3f97219e6c88ed5429d0f9ffb40bb" +
+ "491f280f4281af177e254828f82e90d196c6bf9afa31926cf5bf0cc3dc81f28a" +
+ "419544ef5907f3b8bf6179da37ff07134d9c6d147521e5c840d5086ec74c1003",
+ "Threefish-256/CBC/PKCS7Padding",
+ "1c46830ef0a43a0869bf070a87f0d4e63f2458edfa5654bafd8520358dae8bf9" +
+ "2a8c039d41e87bb65a907331dde317450d38aba6cb3885bfbe0aee148503e37b" +
+ "973c5e8a16c4309f7a4229d9943ab403082b5836431b9d1646b619f368e057b3" +
+ "0931ce1b791b641dd3e79f2b536897f3c537e3b4588dc03c3888f9bab3bc7a0e" +
+ "f96cb468a5cd39a003f976464a7d072c94cb72a3fe739f101aa7b5452bc3fbba",
+ "Threefish-512/CBC/PKCS7Padding",
+ "caee9b663eba4663de1cd6f17ffc51dc8b808c95f91e12a818ab31436985830b" +
+ "3aa886a93e53849d34e713f36db52bac3557b137328434f41f825f3948a611c6" +
+ "03efe066d8d6d57b15b04729632de0ce5636b8ccd28219ac17ef836734556e15" +
+ "e90356111279412a814b660150323a416138b2b62942f2d0cd08ee0bb45b0dd7" +
+ "03902162280012e59efa15c6beecfbf440a6a0c4474bbbb2f74a0ad31bcd398f" +
+ "b24728c3605a4ced3c92c30a5e231113abafaf6f83a3867978e3cdd74091d09f",
+ "Threefish-1024/CBC/PKCS7Padding",
+ "7540a8fe54a1a1d117ba1f970a12002cf9e24477daef9439dfc43b79a88a9e87" +
+ "b59be63aa448b4e02e8b9a6464419c35b0b3f97219e6c88ed5429d0f9ffb40bb" +
+ "491f280f4281af177e254828f82e90d196c6bf9afa31926cf5bf0cc3dc81f28a" +
+ "419544ef5907f3b8bf6179da37ff07134d9c6d147521e5c840d5086ec74c1003" +
+ "4ddd16ad731ad9a32d0f196a72284f7a8df98918e3e22f1708662edeb1810d2b" +
+ "bafd4200e849f3288b55634b37f99f0f7b2dd192a5944fc211ef9e37b67a829b" +
+ "005a5ec609f736875fdf8946bd79c1daa6c44c9d6733a2223cf8b7e5203b1cfd" +
+ "76995f67e570d9c403b2a2e3f3a89c63c7850ee8d47d4398ac377345a139dda4",
+ "Threefish-256/CTS/NoPadding",
+ "1c46830ef0a43a0869bf070a87f0d4e63f2458edfa5654bafd8520358dae8bf9" +
+ "2a8c039d41e87bb65a907331dde317450d38aba6cb3885bfbe0aee148503e37b" +
+ "0931ce1b791b641dd3e79f2b536897f3c537e3b4588dc03c3888f9bab3bc7a0e" +
+ "973c5e8a16c4309f7a4229d9943ab403082b5836431b9d1646b619f368e057b3",
+ "Threefish-512/CTS/NoPadding",
+ "03efe066d8d6d57b15b04729632de0ce5636b8ccd28219ac17ef836734556e15" +
+ "e90356111279412a814b660150323a416138b2b62942f2d0cd08ee0bb45b0dd7" +
+ "caee9b663eba4663de1cd6f17ffc51dc8b808c95f91e12a818ab31436985830b" +
+ "3aa886a93e53849d34e713f36db52bac3557b137328434f41f825f3948a611c6",
+ "Threefish-1024/CTS/NoPadding",
+ "7540a8fe54a1a1d117ba1f970a12002cf9e24477daef9439dfc43b79a88a9e87b59b" +
+ "e63aa448b4e02e8b9a6464419c35b0b3f97219e6c88ed5429d0f9ffb40bb491f280f" +
+ "4281af177e254828f82e90d196c6bf9afa31926cf5bf0cc3dc81f28a419544ef5907" +
+ "f3b8bf6179da37ff07134d9c6d147521e5c840d5086ec74c1003",
+ "Threefish-256/CBC/WithCTS",
+ "1c46830ef0a43a0869bf070a87f0d4e63f2458edfa5654bafd8520358dae8bf9" +
+ "2a8c039d41e87bb65a907331dde317450d38aba6cb3885bfbe0aee148503e37b" +
+ "0931ce1b791b641dd3e79f2b536897f3c537e3b4588dc03c3888f9bab3bc7a0e" +
+ "973c5e8a16c4309f7a4229d9943ab403082b5836431b9d1646b619f368e057b3",
+ "Threefish-512/CBC/WithCTS",
+ "03efe066d8d6d57b15b04729632de0ce5636b8ccd28219ac17ef836734556e15" +
+ "e90356111279412a814b660150323a416138b2b62942f2d0cd08ee0bb45b0dd7" +
+ "caee9b663eba4663de1cd6f17ffc51dc8b808c95f91e12a818ab31436985830b" +
+ "3aa886a93e53849d34e713f36db52bac3557b137328434f41f825f3948a611c6",
+ "Threefish-1024/CBC/WithCTS",
+ "7540a8fe54a1a1d117ba1f970a12002cf9e24477daef9439dfc43b79a88a9e87b59b" +
+ "e63aa448b4e02e8b9a6464419c35b0b3f97219e6c88ed5429d0f9ffb40bb491f280f" +
+ "4281af177e254828f82e90d196c6bf9afa31926cf5bf0cc3dc81f28a419544ef5907" +
+ "f3b8bf6179da37ff07134d9c6d147521e5c840d5086ec74c1003",
+ "Threefish-256/ECB/TBCPadding",
+ "9f82b577cf4cca7a504e9f7a2cd7dbb4ef4ac167c716fca19ab1211f195f610f" +
+ "9f82b577cf4cca7a504e9f7a2cd7dbb4ef4ac167c716fca19ab1211f195f610f" +
+ "9f82b577cf4cca7a504e9f7a2cd7dbb4ef4ac167c716fca19ab1211f195f610f" +
+ "9f82b577cf4cca7a504e9f7a2cd7dbb4ef4ac167c716fca19ab1211f195f610f" +
+ "89c4e79b90153a821bdd4efd5eb1e2cda89b6a91540a003eef03868472d8cfce",
+ "Threefish-512/ECB/TBCPadding",
+ "35d0c46770ebb3bf62fadd48765db209df215d7cd18a8b18d11625e70067e1fa" +
+ "bb98982312ce1fdfccae1a59408e1d5418b400a7bf0d1c4e9ea4afa4395886d7" +
+ "35d0c46770ebb3bf62fadd48765db209df215d7cd18a8b18d11625e70067e1fa" +
+ "bb98982312ce1fdfccae1a59408e1d5418b400a7bf0d1c4e9ea4afa4395886d7" +
+ "dd6bfa1006e4df51298e382ca397a2c398cdb4d65009dce77c5f0a31f9807218" +
+ "a72372a8a0df3b1bacd5dbfb116ebbe314e0b0cd64fd2c8ae8a81491c2534a2a",
+ "Threefish-1024/ECB/TBCPadding",
+ "df6d789e301c6a5e22e0cff0b44666630d44ce774a41b628ebaff6adc86d9e66" +
+ "af50a282a4313552bc9b861cb286ab569e2e23b1c97cdb5cb1fde1bacfba9bfb" +
+ "de3b443218e16b6038537b3d803ff5dbd26b13c177a5bfb597ffccca142a5905" +
+ "8c0f74623daa96bff95b716674701034e7947ce0541426fa5177bc1a519b23ba" +
+ "7312262dc3a25984847d1b05cb624f5751946f136ee7bd0a9a4bbac5dd3bd213" +
+ "702390d3a53d1a4132f59383cce4fe61e08cd3c73c570190d1c8b60940031ef7" +
+ "42f6775b00fb0b4273a14b46a3fc0e760e02f75dc6100ca9c038c3f151e03145" +
+ "92686fd8cccbee74d246a8c59ad80205c9f9aaeb100ea5812837ee8699753301",
+ };
+
static byte[] input1 = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
static byte[] input2 = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c");
+ static byte[] inputLargeBlock = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f" +
+ "000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f" +
+ "000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f" +
+ "000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
static RC2ParameterSpec rc2Spec = new RC2ParameterSpec(128, Hex.decode("0123456789abcdef"));
static RC5ParameterSpec rc5Spec = new RC5ParameterSpec(16, 16, 32, Hex.decode("0123456789abcdef"));
@@ -930,6 +1096,11 @@ public class BlockCipherTest
test(cipherTests2[i], input2, Hex.decode(cipherTests2[i + 1]));
}
+ for (int i = 0; i != cipherTestsLargeBlock.length; i += 2)
+ {
+ test(cipherTestsLargeBlock[i], inputLargeBlock, Hex.decode(cipherTestsLargeBlock[i + 1]));
+ }
+
//
// check for less than a block
//
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/CipherStreamTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/CipherStreamTest.java
index 83063ef..0110d22 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/CipherStreamTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/CipherStreamTest.java
@@ -1,8 +1,12 @@
package org.bouncycastle.jce.provider.test;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.test.SimpleTest;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
@@ -12,13 +16,10 @@ import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Security;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
/**
* check that cipher input/output streams are working correctly
@@ -44,6 +45,23 @@ public class CipherStreamTest
+ "2B4F97E0FF16924A52DF269515110A07"
+ "F9E460BC65EF95DA58F740B7D1DBB0AA");
+ private static final byte[] XSK = Hex.decode("d5c7f6797b7e7e9c1d7fd2610b2abf2bc5a7885fb3ff78092fb3abe8986d35e2");
+ private static final byte[] XSIV = Hex.decode("744e17312b27969d826444640e9c4a378ae334f185369c95");
+ private static final byte[] XSIN = Hex.decode("7758298c628eb3a4b6963c5445ef66971222be5d1a4ad839715d1188071739b77cc6e05d5410f963a64167629757");
+ private static final byte[] XSOUT= Hex.decode("27b8cfe81416a76301fd1eec6a4d99675069b2da2776c360db1bdfea7c0aa613913e10f7a60fec04d11e65f2d64e");
+
+ private static final byte[] CHAK = Hex.decode("80000000000000000000000000000000");
+ private static final byte[] CHAIV = Hex.decode("0000000000000000");
+ private static final byte[] CHAIN = Hex.decode(
+ "00000000000000000000000000000000"
+ + "00000000000000000000000000000000"
+ + "00000000000000000000000000000000"
+ + "00000000000000000000000000000000");
+ private static final byte[] CHAOUT = Hex.decode("FBB87FBB8395E05DAA3B1D683C422046"
+ + "F913985C2AD9B23CFC06C1D8D04FF213"
+ + "D44A7A7CDB84929F915420A8A3DC58BF"
+ + "0F7ECB4B1F167BB1A5E6153FDAF4493D");
+
private static final byte[] HCIN = new byte[64];
private static final byte[] HCIV = new byte[32];
@@ -151,7 +169,7 @@ public class CipherStreamTest
byte[] enc = in.doFinal(plainText);
if (!areEqual(enc, cipherText))
{
- fail(name + ": cipher text doesn't match");
+ fail(name + ": cipher text doesn't match got " + new String(Hex.encode(enc)));
}
byte[] dec = out.doFinal(enc);
@@ -184,7 +202,7 @@ public class CipherStreamTest
(byte)137, (byte)138, (byte)140, (byte)143 };
byte[] keyBytes;
- if (name.equals("HC256"))
+ if (name.equals("HC256") || name.equals("XSalsa20"))
{
keyBytes = key256;
}
@@ -207,18 +225,18 @@ public class CipherStreamTest
// too
// small to hold the result
ecipher.update(new byte[20], 0, 20, cipherText);
-
+
fail("failed exception test - no ShortBufferException thrown");
}
catch (ShortBufferException e)
{
// ignore
}
-
+
try
{
Cipher c = Cipher.getInstance(name, "BC");
-
+
Key k = new PublicKey()
{
@@ -236,22 +254,22 @@ public class CipherStreamTest
{
return null;
}
-
+
};
-
+
c.init(Cipher.ENCRYPT_MODE, k);
-
+
fail("failed exception test - no InvalidKeyException thrown for public key");
}
catch (InvalidKeyException e)
{
// okay
}
-
+
try
{
Cipher c = Cipher.getInstance(name, "BC");
-
+
Key k = new PrivateKey()
{
@@ -269,11 +287,11 @@ public class CipherStreamTest
{
return null;
}
-
+
};
-
+
c.init(Cipher.DECRYPT_MODE, k);
-
+
fail("failed exception test - no InvalidKeyException thrown for private key");
}
catch (InvalidKeyException e)
@@ -286,7 +304,7 @@ public class CipherStreamTest
fail("unexpected exception.", e);
}
}
-
+
public void performTest()
throws Exception
{
@@ -296,6 +314,12 @@ public class CipherStreamTest
runTest("Salsa20");
testException("Salsa20");
testAlgorithm("Salsa20", SK, SIV, SIN, SOUT);
+ runTest("XSalsa20");
+ testException("XSalsa20");
+ testAlgorithm("XSalsa20", XSK, XSIV, XSIN, XSOUT);
+ runTest("ChaCha");
+ testException("ChaCha");
+ testAlgorithm("ChaCha", CHAK, CHAIV, CHAIN, CHAOUT);
runTest("HC128");
testException("HC128");
testAlgorithm("HC128", HCK128A, HCIV, HCIN, HC128A);
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/CipherStreamTest2.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/CipherStreamTest2.java
new file mode 100644
index 0000000..de9533c
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/CipherStreamTest2.java
@@ -0,0 +1,495 @@
+package org.bouncycastle.jce.provider.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.Key;
+import java.security.Security;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.spec.IvParameterSpec;
+
+import org.bouncycastle.crypto.io.InvalidCipherTextIOException;
+import org.bouncycastle.jcajce.io.CipherInputStream;
+import org.bouncycastle.jcajce.io.CipherOutputStream;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.test.SimpleTest;
+
+public class CipherStreamTest2
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "CipherStreamTest";
+ }
+
+ private void testModes(String algo, String[] transforms, boolean authenticated)
+ throws Exception
+ {
+ Key key = generateKey(algo);
+ for (int i = 0; i != transforms.length; i++)
+ {
+ String transform = transforms[i];
+
+ testWriteRead(algo + transform, key, authenticated, true, false);
+ testWriteRead(algo + transform, key, authenticated, true, true);
+ testWriteRead(algo + transform, key, authenticated, false, false);
+ testWriteRead(algo + transform, key, authenticated, false, true);
+ testReadWrite(algo + transform, key, authenticated, true, false);
+ testReadWrite(algo + transform, key, authenticated, true, true);
+ testReadWrite(algo + transform, key, authenticated, false, false);
+ testReadWrite(algo + transform, key, authenticated, false, true);
+
+ if (!(transform.indexOf("CTS") > -1))
+ {
+ testWriteReadEmpty(algo + transform, key, authenticated, true, false);
+ testWriteReadEmpty(algo + transform, key, authenticated, true, true);
+ testWriteReadEmpty(algo + transform, key, authenticated, false, false);
+ testWriteReadEmpty(algo + transform, key, authenticated, false, true);
+ }
+
+ if (authenticated)
+ {
+ testTamperedRead(algo + transform, key, true, true);
+ testTamperedRead(algo + transform, key, true, false);
+ testTruncatedRead(algo + transform, key, true, true);
+ testTruncatedRead(algo + transform, key, true, false);
+ testTamperedWrite(algo + transform, key, true, true);
+ testTamperedWrite(algo + transform, key, true, false);
+ }
+ }
+ }
+
+ private InputStream createInputStream(byte[] data, Cipher cipher, boolean useBc)
+ {
+ ByteArrayInputStream bytes = new ByteArrayInputStream(data);
+ // cast required for earlier JDK
+ return useBc ? (InputStream)new CipherInputStream(bytes, cipher) : (InputStream)new javax.crypto.CipherInputStream(bytes, cipher);
+ }
+
+ private OutputStream createOutputStream(ByteArrayOutputStream bytes, Cipher cipher, boolean useBc)
+ {
+ // cast required for earlier JDK
+ return useBc ? (OutputStream)new CipherOutputStream(bytes, cipher) : (OutputStream)new javax.crypto.CipherOutputStream(bytes, cipher);
+ }
+
+ /**
+ * Test tampering of ciphertext followed by read from decrypting CipherInputStream
+ */
+ private void testTamperedRead(String name, Key key, boolean authenticated, boolean useBc)
+ throws Exception
+ {
+ Cipher encrypt = Cipher.getInstance(name, "BC");
+ Cipher decrypt = Cipher.getInstance(name, "BC");
+ encrypt.init(Cipher.ENCRYPT_MODE, key);
+ if (encrypt.getIV() != null)
+ {
+ decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encrypt.getIV()));
+ }
+ else
+ {
+ decrypt.init(Cipher.DECRYPT_MODE, key);
+ }
+
+ byte[] ciphertext = encrypt.doFinal(new byte[1000]);
+
+ // Tamper
+ ciphertext[0] += 1;
+
+ InputStream input = createInputStream(ciphertext, decrypt, useBc);
+ try
+ {
+ while (input.read() >= 0)
+ {
+ }
+ fail("Expected invalid ciphertext after tamper and read : " + name, authenticated, useBc);
+ }
+ catch (InvalidCipherTextIOException e)
+ {
+ // Expected
+ }
+ try
+ {
+ input.close();
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected exception : " + name, e, authenticated, useBc);
+ }
+ }
+
+ /**
+ * Test truncation of ciphertext to make tag calculation impossible, followed by read from
+ * decrypting CipherInputStream
+ */
+ private void testTruncatedRead(String name, Key key, boolean authenticated, boolean useBc)
+ throws Exception
+ {
+ Cipher encrypt = Cipher.getInstance(name, "BC");
+ Cipher decrypt = Cipher.getInstance(name, "BC");
+ encrypt.init(Cipher.ENCRYPT_MODE, key);
+ if (encrypt.getIV() != null)
+ {
+ decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encrypt.getIV()));
+ }
+ else
+ {
+ decrypt.init(Cipher.DECRYPT_MODE, key);
+ }
+
+ byte[] ciphertext = encrypt.doFinal(new byte[1000]);
+
+ // Truncate to just smaller than complete tag
+ byte[] truncated = new byte[ciphertext.length - 1000 - 1];
+ System.arraycopy(ciphertext, 0, truncated, 0, truncated.length);
+
+ // Tamper
+ ciphertext[0] += 1;
+
+ InputStream input = createInputStream(truncated, decrypt, useBc);
+ while (true)
+ {
+ int read = 0;
+ try
+ {
+ read = input.read();
+ }
+ catch (InvalidCipherTextIOException e)
+ {
+ // Expected
+ break;
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected exception : " + name, e, authenticated, useBc);
+ break;
+ }
+ if (read < 0)
+ {
+ fail("Expected invalid ciphertext after truncate and read : " + name, authenticated, useBc);
+ break;
+ }
+ }
+ try
+ {
+ input.close();
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected exception : " + name, e, authenticated, useBc);
+ }
+ }
+
+ /**
+ * Test tampering of ciphertext followed by write to decrypting CipherOutputStream
+ */
+ private void testTamperedWrite(String name, Key key, boolean authenticated, boolean useBc)
+ throws Exception
+ {
+ Cipher encrypt = Cipher.getInstance(name, "BC");
+ Cipher decrypt = Cipher.getInstance(name, "BC");
+ encrypt.init(Cipher.ENCRYPT_MODE, key);
+ if (encrypt.getIV() != null)
+ {
+ decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encrypt.getIV()));
+ }
+ else
+ {
+ decrypt.init(Cipher.DECRYPT_MODE, key);
+ }
+
+ byte[] ciphertext = encrypt.doFinal(new byte[1000]);
+
+ // Tamper
+ ciphertext[0] += 1;
+
+ ByteArrayOutputStream plaintext = new ByteArrayOutputStream();
+ OutputStream output = createOutputStream(plaintext, decrypt, useBc);
+
+ for (int i = 0; i < ciphertext.length; i++)
+ {
+ output.write(ciphertext[i]);
+ }
+ try
+ {
+ output.close();
+ fail("Expected invalid ciphertext after tamper and write : " + name, authenticated, useBc);
+ }
+ catch (InvalidCipherTextIOException e)
+ {
+ // Expected
+ }
+ }
+
+ /**
+ * Test CipherOutputStream in ENCRYPT_MODE, CipherInputStream in DECRYPT_MODE
+ */
+ private void testWriteRead(String name, Key key, boolean authenticated, boolean useBc, boolean blocks)
+ throws Exception
+ {
+ byte[] data = new byte[1000];
+ for (int i = 0; i < data.length; i++)
+ {
+ data[i] = (byte)(i % 255);
+ }
+
+ testWriteRead(name, key, authenticated, useBc, blocks, data);
+ }
+
+ /**
+ * Test CipherOutputStream in ENCRYPT_MODE, CipherInputStream in DECRYPT_MODE
+ */
+ private void testWriteReadEmpty(String name, Key key, boolean authenticated, boolean useBc, boolean blocks)
+ throws Exception
+ {
+ byte[] data = new byte[0];
+
+ testWriteRead(name, key, authenticated, useBc, blocks, data);
+ }
+
+ private void testWriteRead(String name, Key key, boolean authenticated, boolean useBc, boolean blocks, byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ Cipher encrypt = Cipher.getInstance(name, "BC");
+ Cipher decrypt = Cipher.getInstance(name, "BC");
+ encrypt.init(Cipher.ENCRYPT_MODE, key);
+ if (encrypt.getIV() != null)
+ {
+ decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encrypt.getIV()));
+ }
+ else
+ {
+ decrypt.init(Cipher.DECRYPT_MODE, key);
+ }
+
+ OutputStream cOut = createOutputStream(bOut, encrypt, useBc);
+ if (blocks)
+ {
+ int chunkSize = data.length / 8;
+ for (int i = 0; i < data.length; i += chunkSize)
+ {
+ cOut.write(data, i, chunkSize);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < data.length; i++)
+ {
+ cOut.write(data[i]);
+ }
+ }
+ cOut.close();
+
+ byte[] cipherText = bOut.toByteArray();
+ bOut.reset();
+ InputStream cIn = createInputStream(cipherText, decrypt, useBc);
+
+ if (blocks)
+ {
+ byte[] block = new byte[encrypt.getBlockSize() + 1];
+ int c;
+ while ((c = cIn.read(block)) >= 0)
+ {
+ bOut.write(block, 0, c);
+ }
+ }
+ else
+ {
+ int c;
+ while ((c = cIn.read()) >= 0)
+ {
+ bOut.write(c);
+ }
+
+ }
+ cIn.close();
+
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected exception " + name, e, authenticated, useBc);
+ }
+
+ byte[] decrypted = bOut.toByteArray();
+ if (!Arrays.areEqual(data, decrypted))
+ {
+ fail("Failed - decrypted data doesn't match: " + name, authenticated, useBc);
+ }
+ }
+
+ protected void fail(String message, boolean authenticated, boolean bc)
+ {
+ if (bc || !authenticated)
+ {
+ super.fail(message);
+ }
+ else
+ {
+ // javax.crypto.CipherInputStream/CipherOutputStream
+ // are broken wrt handling AEAD failures
+ // System.err.println("Broken JCE Streams: " + message);
+ }
+ }
+
+ protected void fail(String message, Throwable throwable, boolean authenticated, boolean bc)
+ {
+ if (bc || !authenticated)
+ {
+ super.fail(message, throwable);
+ }
+ else
+ {
+ // javax.crypto.CipherInputStream/CipherOutputStream
+ // are broken wrt handling AEAD failures
+ //System.err.println("Broken JCE Streams: " + message + " : " + throwable);
+ throwable.printStackTrace();
+ }
+ }
+
+ /**
+ * Test CipherInputStream in ENCRYPT_MODE, CipherOutputStream in DECRYPT_MODE
+ */
+ private void testReadWrite(String name, Key key, boolean authenticated, boolean useBc, boolean blocks)
+ throws Exception
+ {
+ String lCode = "ABCDEFGHIJKLMNOPQRSTU";
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ Cipher in = Cipher.getInstance(name, "BC");
+ Cipher out = Cipher.getInstance(name, "BC");
+ in.init(Cipher.ENCRYPT_MODE, key);
+ if (in.getIV() != null)
+ {
+ out.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(in.getIV()));
+ }
+ else
+ {
+ out.init(Cipher.DECRYPT_MODE, key);
+ }
+
+ InputStream cIn = createInputStream(lCode.getBytes(), in, useBc);
+ OutputStream cOut = createOutputStream(bOut, out, useBc);
+
+ if (blocks)
+ {
+ byte[] block = new byte[in.getBlockSize() + 1];
+ int c;
+ while ((c = cIn.read(block)) >= 0)
+ {
+ cOut.write(block, 0, c);
+ }
+ }
+ else
+ {
+ int c;
+ while ((c = cIn.read()) >= 0)
+ {
+ cOut.write(c);
+ }
+ }
+
+ cIn.close();
+
+ cOut.flush();
+ cOut.close();
+
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected exception " + name, e, authenticated, useBc);
+ }
+
+ String res = new String(bOut.toByteArray());
+ if (!res.equals(lCode))
+ {
+ fail("Failed - decrypted data doesn't match: " + name, authenticated, useBc);
+ }
+ }
+
+ private static Key generateKey(String name)
+ throws Exception
+ {
+ KeyGenerator kGen;
+
+ if (name.indexOf('/') < 0)
+ {
+ kGen = KeyGenerator.getInstance(name, "BC");
+ }
+ else
+ {
+ kGen = KeyGenerator.getInstance(name.substring(0, name.indexOf('/')), "BC");
+ }
+ return kGen.generateKey();
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ final String[] blockCiphers64 = new String[]{"BLOWFISH", "DES", "DESEDE", "TEA", "CAST5", "RC2", "XTEA"};
+
+ for (int i = 0; i != blockCiphers64.length; i++)
+ {
+ testModes(blockCiphers64[i], new String[]{
+ "/ECB/PKCS5Padding",
+ "/CBC/PKCS5Padding",
+ "/OFB/NoPadding",
+ "/CFB/NoPadding",
+ "/CTS/NoPadding",}, false);
+ testModes(blockCiphers64[i], new String[]{"/EAX/NoPadding"}, true);
+ }
+
+ final String[] blockCiphers128 = new String[]{
+ "AES",
+ "NOEKEON",
+ "Twofish",
+ "CAST6",
+ "SEED",
+ "Serpent",
+ "RC6",
+ "CAMELLIA"};
+
+ for (int i = 0; i != blockCiphers128.length; i++)
+ {
+ testModes(blockCiphers128[i], new String[]{
+ "/ECB/PKCS5Padding",
+ "/CBC/PKCS5Padding",
+ "/OFB/NoPadding",
+ "/CFB/NoPadding",
+ "/CTS/NoPadding",
+ "/CTR/NoPadding",
+ "/SIC/NoPadding"}, false);
+ testModes(blockCiphers128[i], new String[]{"/CCM/NoPadding", "/EAX/NoPadding", "/GCM/NoPadding", "/OCB/NoPadding"}, true);
+ }
+
+ final String[] streamCiphers = new String[]{
+ "ARC4",
+ "SALSA20",
+ "XSalsa20",
+ "ChaCha",
+ "Grainv1",
+ "Grain128",
+ "HC128",
+ "HC256"};
+
+ for (int i = 0; i != streamCiphers.length; i++)
+ {
+ testModes(streamCiphers[i], new String[]{""}, false);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+ runTest(new CipherStreamTest2());
+ }
+
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DHTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DHTest.java
index c0720be..4ab21ed 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DHTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DHTest.java
@@ -28,6 +28,8 @@ import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHPrivateKeySpec;
+import javax.crypto.spec.DHPublicKeySpec;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
@@ -264,13 +266,17 @@ public class DHTest
}
private void testTwoParty(String algName, int size, int privateValueSize, KeyPairGenerator keyGen)
+ throws Exception
+ {
+ testTwoParty(algName, size, privateValueSize, keyGen.generateKeyPair(), keyGen.generateKeyPair());
+ }
+
+ private byte[] testTwoParty(String algName, int size, int privateValueSize, KeyPair aKeyPair, KeyPair bKeyPair)
throws Exception
{
//
// a side
//
- KeyPair aKeyPair = keyGen.generateKeyPair();
-
KeyAgreement aKeyAgree = KeyAgreement.getInstance(algName, "BC");
checkKeySize(privateValueSize, aKeyPair);
@@ -280,8 +286,6 @@ public class DHTest
//
// b side
//
- KeyPair bKeyPair = keyGen.generateKeyPair();
-
KeyAgreement bKeyAgree = KeyAgreement.getInstance(algName, "BC");
checkKeySize(privateValueSize, bKeyPair);
@@ -294,13 +298,15 @@ public class DHTest
aKeyAgree.doPhase(bKeyPair.getPublic(), true);
bKeyAgree.doPhase(aKeyPair.getPublic(), true);
- BigInteger k1 = new BigInteger(aKeyAgree.generateSecret());
- BigInteger k2 = new BigInteger(bKeyAgree.generateSecret());
+ byte[] aSecret = aKeyAgree.generateSecret();
+ byte[] bSecret = bKeyAgree.generateSecret();
- if (!k1.equals(k2))
+ if (!Arrays.areEqual(aSecret, bSecret))
{
fail(size + " bit 2-way test failed");
}
+
+ return aSecret;
}
private void testExplicitWrapping(
@@ -415,7 +421,7 @@ public class DHTest
new BouncyCastleProvider().setParameter(ConfigurableProvider.DH_DEFAULT_PARAMS, dhParams);
- KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algName, "BC");
+ KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algName, "BC");
keyGen.initialize(dhParams.getP().bitLength());
@@ -727,6 +733,38 @@ public class DHTest
testTwoParty("DH", 512, 0, keyGen);
}
+ private void testSmallSecret()
+ throws Exception
+ {
+ BigInteger p = new BigInteger("ff3b512a4cc0961fa625d6cbd9642c377ece46b8dbc3146a98e0567f944034b5e3a1406edb179a77cd2539bdb74dc819f0a74d486606e26e578ff52c5242a5ff", 16);
+ BigInteger g = new BigInteger("58a66667431136e99d86de8199eb650a21afc9de3dd4ef9da6dfe89c866e928698952d95e68b418becef26f23211572eebfcbf328809bdaf02bba3d24c74f8c0", 16);
+
+ DHPrivateKeySpec aPrivSpec = new DHPrivateKeySpec(
+ new BigInteger("30a6ea4e2240a42867ad98bd3adbfd5b81aba48bd930f20a595983d807566f7cba4e766951efef2c6c0c1be3823f63d66e12c2a091d5ff3bbeb1ea6e335d072d", 16), p, g);
+ DHPublicKeySpec aPubSpec = new DHPublicKeySpec(
+ new BigInteger("694dfea1bfc8897e2fcbfd88033ab34f4581892d7d5cc362dc056e3d43955accda12222bd651ca31c85f008a05dea914de68828dfd83a54a340fa84f3bbe6caf", 16), p, g);
+
+ DHPrivateKeySpec bPrivSpec = new DHPrivateKeySpec(
+ new BigInteger("775b1e7e162190700e2212dd8e4aaacf8a2af92c9c108b81d5bf9a14548f494eaa86a6c4844b9512eb3e3f2f22ffec44c795c813edfea13f075b99bbdebb34bd", 16), p, g);
+
+ DHPublicKeySpec bPubSpec = new DHPublicKeySpec(
+ new BigInteger("d8ddd4ff9246635eadbfa0bc2ef06d98a329b6e8cd2d1435d7b4921467570e697c9a9d3c172c684626a9d2b6b2fa0fc725d5b91f9a9625b717a4169bc714b064", 16), p, g);
+
+ KeyFactory kFact = KeyFactory.getInstance("DH", "BC");
+
+ byte[] secret = testTwoParty("DH", 512, 0, new KeyPair(kFact.generatePublic(aPubSpec), kFact.generatePrivate(aPrivSpec)), new KeyPair(kFact.generatePublic(bPubSpec), kFact.generatePrivate(bPrivSpec)));
+
+ if (secret.length != ((p.bitLength() + 7) / 8))
+ {
+ fail("short secret wrong length");
+ }
+
+ if (!Arrays.areEqual(Hex.decode("00340d3309ddc86e99e2f0be4fc212837bfb5c59336b09b9e1aeb1884b72c8b485b56723d0bf1c1d37fc89a292fc1cface9125106f1df15f55f22e4f77c5879b"), secret))
+ {
+ fail("short secret mismatch");
+ }
+ }
+
private void testEnc()
throws Exception
{
@@ -882,6 +920,7 @@ public class DHTest
testExceptions();
testDESAndDESede(g768, p768);
testInitialise();
+ testSmallSecret();
testConfig();
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DetDSATest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DetDSATest.java
new file mode 100644
index 0000000..16c1969
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DetDSATest.java
@@ -0,0 +1,152 @@
+package org.bouncycastle.jce.provider.test;
+
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.Security;
+import java.security.Signature;
+import java.security.spec.DSAPrivateKeySpec;
+import java.security.spec.ECFieldFp;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPrivateKeySpec;
+import java.security.spec.EllipticCurve;
+
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.nist.NISTNamedCurves;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
+
+/**
+ * Tests are taken from RFC 6979 - "Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)"
+ */
+public class DetDSATest
+ extends SimpleTest
+{
+
+ public static final byte[] SAMPLE = Hex.decode("73616d706c65"); // "sample"
+ public static final byte[] TEST = Hex.decode("74657374"); // "test"
+
+ // test vectors from appendix in RFC 6979
+ private void testHMacDeterministic()
+ throws Exception
+ {
+ DSAPrivateKeySpec privKeySpec = new DSAPrivateKeySpec(new BigInteger("411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", 16),
+ new BigInteger("86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447" +
+ "E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88" +
+ "73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C" +
+ "881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779", 16),
+ new BigInteger("996F967F6C8E388D9E28D01E205FBA957A5698B1", 16),
+ new BigInteger("07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D" +
+ "89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD" +
+ "87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4" +
+ "17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD", 16));
+
+ KeyFactory keyFact = KeyFactory.getInstance("DSA", "BC");
+
+ PrivateKey privKey = keyFact.generatePrivate(privKeySpec);
+
+ doTestHMACDetDSASample("SHA1withDETDSA", privKey, new BigInteger("2E1A0C2562B2912CAAF89186FB0F42001585DA55", 16), new BigInteger("29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5", 16));
+ doTestHMACDetDSASample("SHA224withDETDSA", privKey, new BigInteger("4BC3B686AEA70145856814A6F1BB53346F02101E", 16), new BigInteger("410697B92295D994D21EDD2F4ADA85566F6F94C1", 16));
+ doTestHMACDetDSASample("SHA256withDETDSA", privKey, new BigInteger("81F2F5850BE5BC123C43F71A3033E9384611C545", 16), new BigInteger("4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89", 16));
+ doTestHMACDetDSASample("SHA384withDETDSA", privKey, new BigInteger("07F2108557EE0E3921BC1774F1CA9B410B4CE65A", 16), new BigInteger("54DF70456C86FAC10FAB47C1949AB83F2C6F7595", 16));
+ doTestHMACDetDSASample("SHA512withDETDSA", privKey, new BigInteger("16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", 16), new BigInteger("02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C", 16));
+ }
+
+ private void doTestHMACDetDSASample(String algName, PrivateKey privKey, BigInteger r, BigInteger s)
+ throws Exception
+ {
+ doTestHMACDetECDSA(Signature.getInstance(algName, "BC"), SAMPLE, privKey, r, s);
+ }
+
+ // test vectors from appendix in RFC 6979
+ private void testECHMacDeterministic()
+ throws Exception
+ {
+ X9ECParameters x9ECParameters = NISTNamedCurves.getByName("P-192");
+ ECCurve curve = x9ECParameters.getCurve();
+
+ ECPrivateKeySpec privKeySpec = new ECPrivateKeySpec(new BigInteger("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
+ new ECParameterSpec(
+ new EllipticCurve(new ECFieldFp(((ECCurve.Fp)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null),
+ new ECPoint(x9ECParameters.getG().getXCoord().toBigInteger(), x9ECParameters.getG().getYCoord().toBigInteger()),
+ x9ECParameters.getN(), x9ECParameters.getH().intValue())
+ );
+
+ KeyFactory keyFact = KeyFactory.getInstance("ECDSA", "BC");
+
+ PrivateKey privKey = keyFact.generatePrivate(privKeySpec);
+
+ doTestHMACDetECDSASample("SHA1withDETECDSA", privKey, new BigInteger("98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", 16), new BigInteger("57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64", 16));
+ doTestHMACDetECDSASample("SHA224withDETECDSA", privKey, new BigInteger("A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", 16), new BigInteger("E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A", 16));
+ doTestHMACDetECDSASample("SHA256withDETECDSA", privKey, new BigInteger("4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", 16), new BigInteger("CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85", 16));
+ doTestHMACDetECDSASample("SHA384withDETECDSA", privKey, new BigInteger("DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", 16), new BigInteger("C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E", 16));
+ doTestHMACDetECDSASample("SHA512withDETECDSA", privKey, new BigInteger("4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", 16), new BigInteger("3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67", 16));
+
+ doTestHMACDetECDSATest("SHA1withDETECDSA", privKey, new BigInteger("0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", 16), new BigInteger("EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7", 16));
+ doTestHMACDetECDSATest("SHA224withDETECDSA", privKey, new BigInteger("6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", 16), new BigInteger("B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293", 16));
+ doTestHMACDetECDSATest("SHA256withDETECDSA", privKey, new BigInteger("3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", 16), new BigInteger("5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F", 16));
+ doTestHMACDetECDSATest("SHA384withDETECDSA", privKey, new BigInteger("B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", 16), new BigInteger("7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A", 16));
+ doTestHMACDetECDSATest("SHA512withDETECDSA", privKey, new BigInteger("FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", 16), new BigInteger("74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290", 16));
+ }
+
+ private void doTestHMACDetECDSASample(String sigAlg, PrivateKey privKey, BigInteger r, BigInteger s)
+ throws Exception
+ {
+ doTestHMACDetECDSA(Signature.getInstance(sigAlg, "BC"), SAMPLE, privKey, r, s);
+ }
+
+ private void doTestHMACDetECDSATest(String sigAlg, PrivateKey privKey, BigInteger r, BigInteger s)
+ throws Exception
+ {
+ doTestHMACDetECDSA(Signature.getInstance(sigAlg, "BC"), TEST, privKey, r, s);
+ }
+
+ private void doTestHMACDetECDSA(Signature detSigner, byte[] data, PrivateKey privKey, BigInteger r, BigInteger s)
+ throws Exception
+ {
+ detSigner.initSign(privKey);
+
+ detSigner.update(data, 0, data.length);
+
+ byte[] m = detSigner.sign();
+
+ ASN1Sequence seq = ASN1Sequence.getInstance(m);
+
+
+ if (!r.equals(ASN1Integer.getInstance(seq.getObjectAt(0)).getValue()))
+ {
+ fail("r value wrong");
+ }
+ if (!s.equals(ASN1Integer.getInstance(seq.getObjectAt(1)).getValue()))
+ {
+ fail("s value wrong");
+ }
+ }
+
+ public String getName()
+ {
+ return "DetDSA";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ testHMacDeterministic();
+ testECHMacDeterministic();
+ }
+
+
+ public static void main(
+ String[] args)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+
+ runTest(new DetDSATest());
+ }
+}
+
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DigestTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DigestTest.java
index 5e37991..679f3ea 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DigestTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/DigestTest.java
@@ -30,7 +30,8 @@ public class DigestTest
{ "RIPEMD320", "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d" },
{ "Tiger", "2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93" },
{ "GOST3411", "b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c" },
- { "WHIRLPOOL", "4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5" }
+ { "WHIRLPOOL", "4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5" },
+ { "SM3", "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0" },
};
public String getName()
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECDSA5Test.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECDSA5Test.java
index 0f93bdc..802134c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECDSA5Test.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECDSA5Test.java
@@ -18,6 +18,7 @@ import java.security.Security;
import java.security.Signature;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECFieldF2m;
import java.security.spec.ECFieldFp;
import java.security.spec.ECGenParameterSpec;
@@ -28,6 +29,7 @@ import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERInteger;
@@ -38,6 +40,7 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jce.ECKeyUtil;
+import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.ECPointUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.BigIntegers;
@@ -687,6 +690,50 @@ public class ECDSA5Test
}
}
+ private static class ECRandom
+ extends SecureRandom
+ {
+ public void nextBytes(byte[] bytes)
+ {
+ byte[] src = BigInteger.valueOf(1000).toByteArray();
+ System.arraycopy(src, 0, bytes, bytes.length - src.length, src.length);
+ }
+ }
+
+ private void testNamedCurveParameterPreservation()
+ throws Exception
+ {
+ AlgorithmParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1");
+ KeyPairGenerator keygen = KeyPairGenerator.getInstance("EC", "BC");
+ keygen.initialize(ecSpec, new ECRandom());
+
+ KeyPair keys = keygen.generateKeyPair();
+
+ PrivateKeyInfo priv1 = PrivateKeyInfo.getInstance(keys.getPrivate().getEncoded());
+ SubjectPublicKeyInfo pub1 = SubjectPublicKeyInfo.getInstance(keys.getPublic().getEncoded());
+
+ keygen = KeyPairGenerator.getInstance("EC", "BC");
+ keygen.initialize(new ECGenParameterSpec("secp256r1"), new ECRandom());
+
+ PrivateKeyInfo priv2 = PrivateKeyInfo.getInstance(keys.getPrivate().getEncoded());
+ SubjectPublicKeyInfo pub2 = SubjectPublicKeyInfo.getInstance(keys.getPublic().getEncoded());
+
+ if (!priv1.equals(priv2) || !pub1.equals(pub2))
+ {
+ fail("mismatch between alg param spec and ECGenParameterSpec");
+ }
+
+ if (!(priv2.getPrivateKeyAlgorithm().getParameters() instanceof ASN1ObjectIdentifier))
+ {
+ fail("OID not preserved in private key");
+ }
+
+ if (!(pub1.getAlgorithm().getParameters() instanceof ASN1ObjectIdentifier))
+ {
+ fail("OID not preserved in public key");
+ }
+ }
+
protected BigInteger[] derDecode(
byte[] encoding)
throws IOException
@@ -718,6 +765,7 @@ public class ECDSA5Test
testECDSA239bitBinary();
testGeneration();
testKeyPairGenerationWithOIDs();
+ testNamedCurveParameterPreservation();
}
public static void main(
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECEncodingTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECEncodingTest.java
index 9a5135a..1bd3178 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECEncodingTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ECEncodingTest.java
@@ -120,8 +120,8 @@ public class ECEncodingTest
{
((ECPointEncoder)pubKey).setPointFormat("UNCOMPRESSED");
}
- byte[] x = pubKey.getQ().getX().toBigInteger().toByteArray();
- byte[] y = pubKey.getQ().getY().toBigInteger().toByteArray();
+ byte[] x = pubKey.getQ().getAffineXCoord().toBigInteger().toByteArray();
+ byte[] y = pubKey.getQ().getAffineYCoord().toBigInteger().toByteArray();
if (x.length == y.length)
{
success = true;
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/GOST28147Test.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/GOST28147Test.java
index b7fecd0..93e3ad7 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/GOST28147Test.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/GOST28147Test.java
@@ -11,8 +11,8 @@ import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -182,11 +182,11 @@ public class GOST28147Test
private void oidTest()
{
String[] oids = {
- CryptoProObjectIdentifiers.gostR28147_cbc.getId(),
+ CryptoProObjectIdentifiers.gostR28147_gcfb.getId(),
};
String[] names = {
- "GOST28147/CBC/PKCS7Padding"
+ "GOST28147/GCFB/NoPadding"
};
try
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ImplicitlyCaTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ImplicitlyCaTest.java
index 103a3e3..fa90108 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ImplicitlyCaTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/ImplicitlyCaTest.java
@@ -122,12 +122,12 @@ public class ImplicitlyCaTest
testEncoding(sKey, vKey);
- ECPublicKey vKey2 = (ECPublicKey)fact.generatePublic(new ECPublicKeySpec(vKey.getQ(), ecSpec));
- ECPrivateKey sKey2 = (ECPrivateKey)fact.generatePrivate(new ECPrivateKeySpec(sKey.getD(), ecSpec));
+ ECPublicKey vKey2 = (ECPublicKey)fact.generatePublic(new ECPublicKeySpec(vKey.getQ(), null));
+ ECPrivateKey sKey2 = (ECPrivateKey)fact.generatePrivate(new ECPrivateKeySpec(sKey.getD(), null));
if (!vKey.equals(vKey2) || vKey.hashCode() != vKey2.hashCode())
{
- fail("private equals/hashCode failed");
+ fail("public equals/hashCode failed");
}
if (!sKey.equals(sKey2) || sKey.hashCode() != sKey2.hashCode())
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/OCBTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/OCBTest.java
new file mode 100644
index 0000000..c693ce8
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/OCBTest.java
@@ -0,0 +1,104 @@
+package org.bouncycastle.jce.provider.test;
+
+import java.security.Key;
+import java.security.Security;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
+
+public class OCBTest
+ extends SimpleTest
+{
+ public String getName()
+ {
+ return "OCB";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ checkRegistrations();
+ }
+
+ private void checkRegistrations()
+ throws Exception
+ {
+ String[] ciphers = new String[] { "AES", "NOEKEON", "Twofish", "CAST6", "SEED", "Serpent", "RC6", "CAMELLIA" };
+ String[] cipherText = new String[]
+ {
+ "BEA5E8798DBE7110031C144DA0B2612213CC8B747807121A4CBB3E4BD6B456AF",
+ "a2545b927e0f2e6db2998e20b17d5fc0564dcab63b748327e2ef4eaed88cb059",
+ "1cfafe72f7181cae331610c116345e51fc356b379aca04da2a53337c5428d8e4",
+ "5b9b738b2ac7000b33b89dd4eec18dd853f4f7c1d9e17b565405f17a0a8c8b63",
+ "fcdbcee69d02c69858ed4569f78b81920b3027cdb7f1f154634aa5ace9e6ba29",
+ "4f7154cb34558940e85db7d3e96ac6c9cb0d9c1b00b18e82e15d1be83deef9df",
+ "23f3e450c4c7199563a0ed601a5c60d75eb88db2a0d090ae5e84d98438a146aa",
+ "ac13ce9db4af148e910a813fc728e5785e23b1bf1d04a961a3f95f356b9417ab"
+ };
+
+ for (int i = 0; i < ciphers.length; i++)
+ {
+ ocbTest(ciphers[i], cipherText[i]);
+ }
+ }
+
+ private void ocbTest(String cipher, String cText)
+ throws Exception
+ {
+ byte[] K = Hex.decode(
+ "000102030405060708090A0B0C0D0E0F");
+ byte[] P = Hex.decode(
+ "000102030405060708090A0B0C0D0E0F");
+ byte[] N = Hex.decode("000102030405060708090A0B");
+ String T = "4CBB3E4BD6B456AF";
+ byte[] C = Hex.decode(cText);
+
+ Key key;
+ Cipher in, out;
+
+ key = new SecretKeySpec(K, cipher);
+
+ in = Cipher.getInstance(cipher + "/OCB/NoPadding", "BC");
+ out = Cipher.getInstance(cipher + "/OCB/NoPadding", "BC");
+
+ in.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(N));
+
+ byte[] enc = in.doFinal(P);
+ if (!areEqual(enc, C))
+ {
+ fail("ciphertext doesn't match in OCB got " + new String(Hex.encode(enc)));
+ }
+
+ out.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(N));
+
+ byte[] dec = out.doFinal(C);
+ if (!areEqual(dec, P))
+ {
+ fail("plaintext doesn't match in OCB");
+ }
+
+ try
+ {
+ in = Cipher.getInstance(cipher + "/OCB/PKCS5Padding", "BC");
+
+ fail("bad padding missed in OCB");
+ }
+ catch (NoSuchPaddingException e)
+ {
+ // expected
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+
+ runTest(new OCBTest());
+ }
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java
index c35c5b8..0828440 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java
@@ -11,6 +11,7 @@ import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
+import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
@@ -426,6 +427,49 @@ public class PKCS12StoreTest
+ "AHoAeQB0AGsAbwB3AG4AaQBrAGEwMTAhMAkGBSsOAwIaBQAEFKJpUOIj0OtI"
+ "j2CPp38YIFBEqvjsBAi8G+yhJe3A/wICCAA=");
+ private byte[] gostPfx = Base64.decode(
+ "MIIHEgIBAzCCBssGCSqGSIb3DQEHAaCCBrwEgga4MIIGtDCCBYEGCSqGSIb3"
+ + "DQEHBqCCBXIwggVuAgEAMIIFZwYJKoZIhvcNAQcBMFUGCSqGSIb3DQEFDTBI"
+ + "MCcGCSqGSIb3DQEFDDAaBAi114+lRrpkXAICCAAwCgYGKoUDAgIKBQAwHQYG"
+ + "KoUDAgIVMBMECLEIQPMsz/ZZBgcqhQMCAh8BgIIFAbu13yJiW/BnSKYKbtv9"
+ + "tDJoTv6l9BVpCCI4tvpzJnMeLBJyVZU4JevcJNii+R1LilVuuB+xc8e7/P4G"
+ + "6TILWmnnispr9KPRAbYRfoCJOa59+TYJMur58wwDuYgMapQAFzsvpzyUWi62"
+ + "o3uQbbLKO9hQCeJW2L+K9cbg8k33MjXMLpnblKpqmZbHTmBJDFR3xGw7IEjD"
+ + "UNqruu7DlHY6jctiVJSii9UNEVetSo9AAzfROxRjROg38VsWxLyO9wEMBv/8"
+ + "H8ur+zOtmQPGqirNXmN+pa08OvZin9kh7CgswW03xIbfsdGGGLRAWtvCnEwJ"
+ + "mS2tEfH1SZcuVLpMomhq3FU/jsc12k+vq/jw4I2cmfDL41ieK72bwNj8xUXu"
+ + "JHeoFSPGX4z+nsJUrFbFG4VBuDs2Y0SCWLyYZvdjvJwYjfqtyi/RoFSZjGHF"
+ + "crstf9YNQ0vW0efCJ7pUBH44OrbnCx5ng2U5jFm1b3HBIKA2RX+Tlhv14MgT"
+ + "KSftPZ67eSmgdsyPuQAdMu6fEdBMpVKMNZNRV565690sqi+1jOmH94TUX8XU"
+ + "2pRQj6eGGLq6lgGnnDabcePUEPXW8zW2KYrDKYJ/1QZmVGldvlqnjZMNhIO+"
+ + "Afsqax/P8RBjMduGqdilGdRzbN8PdhVaN0Ys+WzFxiS9gtaA2yPzcQuedWDN"
+ + "T7sIrfIapgFYmmHRQ7ht4AKj+lmOyNadONYw+ww+8RzHB1d2Kk+iXeZCtvH0"
+ + "XFWJZtuoGKSt/gkI0E2vpDfMbLaczaRC7ityO0iJs25ozP4JhZRBVvOmpxc9"
+ + "YuIetbTnTf1TLJKXDgt1IwPZeugbofSeiNv117lx8VgtvMYFD4W+WQlB8HnO"
+ + "C8NOYjkMPElc6PCMB9gGm0cIu1fKLvY8ycLav93JJjdDuC0kgKLb2+8mC5+2"
+ + "DdMkcfgW6hy4c98xnJs8enCww3A4xkRbMU13zMq70liqmKHV2SSurg5hwUHM"
+ + "ZthT8p988ZBrnqW24lXfMBqTK4YtIBMeMnvKocYBXr96ig3GfahI1Aj2Bw2e"
+ + "bpZTVeayYUd+2xX8JJMdqna6Q61AL8/eUhJUETz5+fgQJtPjcKmdJfVHO6nB"
+ + "vOk1t/rjK17eiXLxHCyvfP+Tw8lSFOhcvr4eIeG8WfsWNRu2eKKosOU7uash"
+ + "QpnvQieqDeijuRxf+tbbJ5D86inwbJqdxra7wNuZXmiaB9gFDzNbNjhtL+6i"
+ + "gUyX/iQHKi9bNK+PH6pdH/gkwnG/juhdgqoNY6GRty/LUOPgXD+r5e/ST16R"
+ + "vnlwrlKp5FzRWBEkem+dhelj3rb+cxKEyvPe3TvIUFcmIlV1VCRQ1fBHtX18"
+ + "eC3a3GprH8c40z3S/kdyk7GlFQ27DRLka+iDN05b+MP5jlgvfqYBKxwLfeNu"
+ + "MpxWoCUvYWiQdMih86/l0H+0o5UB8SqRbpuvr6fY910JCk0hDaO1pgB3HlRz"
+ + "k1vb46pg25heXQm3JmO+ghxjOGliYBWjl8p7AfRS9cjS8ca+X02Mv9Viv7Ce"
+ + "3+Gz0MVwfK98viJ3CFxkaEBlM2LM0IeUQbkHG+YwYaTSfl4GYyrug4F0ZdrA"
+ + "KeY9/kIxa/OJxjcIMs2H+2mSpxmrb7ylmHZ2RB8ITiduRVtO091hn/J7N+eT"
+ + "h6BvLBKIFU+UFUdgjxoDNDk7ao++Mu9T3dQfceFBOYzW9vMQgX30yaPLSdan"
+ + "ZMAP0VtiNjCCASsGCSqGSIb3DQEHAaCCARwEggEYMIIBFDCCARAGCyqGSIb3"
+ + "DQEMCgECoIGyMIGvMFUGCSqGSIb3DQEFDTBIMCcGCSqGSIb3DQEFDDAaBAiQ"
+ + "Owewo16xzQICCAAwCgYGKoUDAgIKBQAwHQYGKoUDAgIVMBMECHSCNJJcQ2VI"
+ + "BgcqhQMCAh8BBFYCyRRpFtZgnsxeK7ZHT+aOyoVmzhtnLrqoBHgV4nJJW2/e"
+ + "UcJjc2Rlbzfd+3L/GWcRGF8Bgn+MjiaAqE64Rzaao9t2hc3myw1WrCfPnoEx"
+ + "VI7OPBM5FzFMMCMGCSqGSIb3DQEJFTEWBBTV7LvI27QWRmHD45X2WKXYs3ct"
+ + "AzAlBgkqhkiG9w0BCRQxGB4WAGMAcABfAGUAeABwAG8AcgB0AGUAZDA+MC4w"
+ + "CgYGKoUDAgIJBQAEIJbGZorQsNM63+xozwEI561cTFVCbyHAEEpkvF3eijT8"
+ + "BAgY5sDtkrVeBQICCAA=");
+
/**
* we generate a self signed certificate for the sake of testing - RSA
*/
@@ -482,6 +526,38 @@ public class PKCS12StoreTest
return certGen.generate(privKey);
}
+ private void testGOSTStore()
+ throws Exception
+ {
+ byte[] data = Hex.decode("deadbeef");
+
+ KeyStore pkcs12 = KeyStore.getInstance("PKCS12", "BC");
+
+ pkcs12.load(new ByteArrayInputStream(gostPfx), "1".toCharArray());
+
+ PrivateKey pk = (PrivateKey)pkcs12.getKey("cp_exported", null);
+ Certificate[] pubCerts = pkcs12.getCertificateChain("cp_exported");
+
+ Signature sig = Signature.getInstance("ECGOST3410", "BC");
+
+ sig.initSign(pk);
+
+ sig.update(data);
+
+ byte[] signature = sig.sign();
+
+ sig = Signature.getInstance("ECGOST3410", "BC");
+
+ sig.initVerify(pubCerts[0].getPublicKey());
+
+ sig.update(data);
+
+ if (!sig.verify(signature))
+ {
+ fail("key test failed in GOST store");
+ }
+ }
+
public void testPKCS12Store()
throws Exception
{
@@ -1080,7 +1156,7 @@ public class PKCS12StoreTest
throws Exception
{
testPKCS12Store();
-
+ testGOSTStore();
// converter tests
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/Poly1305Test.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/Poly1305Test.java
new file mode 100644
index 0000000..c147c17
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/Poly1305Test.java
@@ -0,0 +1,150 @@
+package org.bouncycastle.jce.provider.test;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
+import org.bouncycastle.util.test.TestFailedException;
+
+public class Poly1305Test
+ extends SimpleTest
+{
+ private static final byte[] MASTER_KEY = Hex
+ .decode("95cc0e44d0b79a8856afcae1bec4fe3c01bcb20bfc8b6e03609ddd09f44b060f");
+
+ public String getName()
+ {
+ return "Poly1305";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ checkRegistrations();
+ }
+
+ private void checkRegistrations()
+ throws Exception
+ {
+ List missingMacs = new ArrayList();
+ List missingKeyGens = new ArrayList();
+
+ String[] ciphers = new String[]{"AES", "NOEKEON", "Twofish", "CAST6", "SEED", "Serpent", "RC6", "CAMELLIA"};
+ String[] macs = new String[]{
+ "4bb5e21dd13001ed5faccfcfdaf8a854",
+ "6d601be3d5ebbb9972a64ed3223d913d",
+ "211195296d9afc7b35a1223a79487c87",
+ "f328857a1b653684e73760c804c55b1d",
+ "21cd8adb23ca84eb4dbb12780595bf28",
+ "211195296d9afc7b35a1223a79487c87",
+ "db86de7b1fcae429753d68b1263d7ca0",
+ "11918174f33a2f278fb86554da094112"};
+
+ for (int i = 0; i < ciphers.length; i++)
+ {
+ String cipherName = ciphers[i];
+ Cipher cipher;
+ try
+ {
+ cipher = Cipher.getInstance(cipherName, "BC");
+ } catch (Exception e)
+ {
+ System.err.println(cipherName + ": " + e.getMessage());
+ continue;
+ }
+ int blocksize;
+ try
+ {
+ blocksize = cipher.getBlockSize();
+ } catch (Exception e)
+ {
+ System.err.println(cipherName + ": " + e.getMessage());
+ continue;
+ }
+ // Poly1305 is defined over 128 bit block ciphers
+ if (blocksize == 16)
+ {
+ String macName = "Poly1305-" + cipherName;
+ String macNameAlt = "Poly1305" + cipherName;
+
+ // Check we have a Poly1305 registered for each name
+ checkMac(macName, missingMacs, missingKeyGens, macs[i]);
+ checkMac(macNameAlt, missingMacs, missingKeyGens, macs[i]);
+ }
+ }
+ if (missingMacs.size() != 0)
+ {
+ fail("Did not find Poly1305 registrations for the following ciphers: " + missingMacs);
+ }
+ if (missingKeyGens.size() != 0)
+ {
+ fail("Did not find Poly1305 KeyGenerator registrations for the following macs: " + missingKeyGens);
+ }
+ }
+
+ private void checkMac(String name, List missingMacs, List missingKeyGens, String macOutput)
+ {
+ try
+ {
+ try
+ {
+ KeyGenerator kg = KeyGenerator.getInstance(name);
+ SecretKey key = kg.generateKey();
+
+ try
+ {
+ Poly1305KeyGenerator.checkKey(key.getEncoded());
+ } catch (IllegalArgumentException e)
+ {
+ fail("Generated key for algo " + name + " does not match required Poly1305 format.");
+ }
+
+ try
+ {
+ Mac mac = Mac.getInstance(name);
+ mac.init(new SecretKeySpec(MASTER_KEY, name), new IvParameterSpec(new byte[16]));
+ mac.update(new byte[128]);
+ byte[] bytes = mac.doFinal();
+
+ if (!Arrays.areEqual(bytes, Hex.decode(macOutput)))
+ {
+ fail("wrong mac value computed for " + name, macOutput, new String(Hex.encode(bytes)));
+ }
+ } catch (NoSuchAlgorithmException e)
+ {
+ missingMacs.add(name);
+ }
+
+ } catch (NoSuchAlgorithmException e)
+ {
+ missingKeyGens.add(name);
+ }
+ } catch (TestFailedException e)
+ {
+ throw e;
+ } catch (Exception e)
+ {
+ fail("Unexpected error", e);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+
+ runTest(new Poly1305Test());
+ }
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/RSATest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/RSATest.java
index a0a0572..c1f4582 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/RSATest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/RSATest.java
@@ -43,6 +43,7 @@ import org.bouncycastle.asn1.pkcs.RSAESOAEPparams;
import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DigestInfo;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;
@@ -646,6 +647,29 @@ public class RSATest
fail("public key hashCode check failed");
}
+ //
+ // test an OAEP key
+ //
+ SubjectPublicKeyInfo oaepKey = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, new RSAESOAEPparams()),
+ SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()).parsePublicKey());
+
+ copyKey = (RSAPublicKey)serializeDeserialize(keyFact.generatePublic(new X509EncodedKeySpec(oaepKey.getEncoded())));
+
+ if (!pubKey.equals(copyKey))
+ {
+ fail("public key equality check failed");
+ }
+
+ if (pubKey.hashCode() != copyKey.hashCode())
+ {
+ fail("public key hashCode check failed");
+ }
+
+ if (!Arrays.areEqual(copyKey.getEncoded(), oaepKey.getEncoded()))
+ {
+ fail("encoding does not match");
+ }
+
oaepCompatibilityTest("SHA-1", priv2048Key, pub2048Key);
oaepCompatibilityTest("SHA-224", priv2048Key, pub2048Key);
oaepCompatibilityTest("SHA-256", priv2048Key, pub2048Key);
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/RegressionTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/RegressionTest.java
index 85972a0..e98330e 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/RegressionTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/RegressionTest.java
@@ -12,6 +12,7 @@ public class RegressionTest
new FIPSDESTest(),
new DESedeTest(),
new AESTest(),
+ new AEADTest(),
new CamelliaTest(),
new SEEDTest(),
new AESSICTest(),
@@ -44,6 +45,7 @@ public class RegressionTest
new WrapTest(),
new DoFinalTest(),
new CipherStreamTest(),
+ new CipherStreamTest2(),
new NamedCurveTest(),
new PKIXTest(),
new NetscapeCertRequestTest(),
@@ -68,10 +70,15 @@ public class RegressionTest
new MQVTest(),
new CMacTest(),
new GMacTest(),
+ new OCBTest(),
new DSTU4145Test(),
new CRL5Test(),
+ new Poly1305Test(),
new SipHashTest(),
- new SHA3Test()
+ new SHA3Test(),
+ new SkeinTest(),
+ new Shacal2Test(),
+ new DetDSATest()
};
public static void main(
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/SerialisationTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/SerialisationTest.java
index 3db5e98..6d04f97 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/SerialisationTest.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/SerialisationTest.java
@@ -1,12 +1,5 @@
package org.bouncycastle.jce.provider.test;
-import org.bouncycastle.jce.interfaces.ElGamalPrivateKey;
-import org.bouncycastle.jce.interfaces.ElGamalPublicKey;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.test.SimpleTest;
-
-import javax.crypto.interfaces.DHPrivateKey;
-import javax.crypto.interfaces.DHPublicKey;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -16,6 +9,14 @@ import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+
+import org.bouncycastle.jce.interfaces.ElGamalPrivateKey;
+import org.bouncycastle.jce.interfaces.ElGamalPublicKey;
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.test.SimpleTest;
+
public class SerialisationTest
extends SimpleTest
{
@@ -56,6 +57,11 @@ public class SerialisationTest
+ "eHNxAH4ABv///////////////v////4AAAABdXEAfgAKAAAAEMDh3xza3MJ4XNak/35BYPt4c3EAfgAG///////////////"
+ "+/////gAAAAF1cQB+AAoAAAADAQABeA==");
+ private static byte[] rsaPub2 = Base64.decode(
+ "rO0ABXNyAD5vcmcuYm91bmN5Y2FzdGxlLmpjYWpjZS5wcm92aWRlci5hc3ltbWV0cmljLnJzYS5CQ1JTQVB1YmxpY0tleS"
+ + "Uiag5b+myEAgACTAAHbW9kdWx1c3QAFkxqYXZhL21hdGgvQmlnSW50ZWdlcjtMAA5wdWJsaWNFeHBvbmVudHEAfgABeHBz"
+ + "cgAUamF2YS5tYXRoLkJpZ0ludGVnZXKM/J8fqTv7HQMABkkACGJpdENvdW50SQAJYml0TGVuZ3RoSQATZmlyc3ROb256ZXJvQnl0ZU51bUkADGxvd2VzdFNldEJpdEkABnNpZ251bVsACW1hZ25pdHVkZXQAAltCeHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhw///////////////+/////gAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAAIJqU1y+8k0wz3jgpbPO4fYxeQpuJbXQ4TMZBv0H0wz9PeHNxAH4AA////////////////v////4AAAABdXEAfgAHAAAAAwEAAXg=");
+
private static BigInteger elGamalY = new BigInteger("89822212135401014750127909969755994242838935150891306006689219384134393835581");
private static BigInteger elGamalX = new BigInteger("23522982289275336984843296896007818700866293719703239515258104457243931686357");
private static BigInteger elGamalG = new BigInteger("29672625807664138507782226105202719390719480236799714903174779490259822385963");
@@ -167,6 +173,17 @@ public class SerialisationTest
fail("public key exponent mismatch");
}
+ RSAPublicKey pub2 = (RSAPublicKey)readObject(rsaPub2);
+
+ if (!mod.equals(pub2.getModulus()))
+ {
+ fail("public key 2 modulus mismatch");
+ }
+ if (!pubExp.equals(pub2.getPublicExponent()))
+ {
+ fail("public key 2 exponent mismatch");
+ }
+
RSAPrivateCrtKey priv = (RSAPrivateCrtKey)readObject(rsaPriv);
if (!mod.equals(priv.getModulus()))
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/Shacal2Test.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/Shacal2Test.java
new file mode 100644
index 0000000..4b4954a
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/Shacal2Test.java
@@ -0,0 +1,154 @@
+package org.bouncycastle.jce.provider.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.security.Key;
+import java.security.Security;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
+
+/**
+ * basic test class for the Shacal2 cipher, vector from NESSIE (Test vectors set 8, vector# 0)
+ */
+public class Shacal2Test
+ extends SimpleTest
+{
+ static String[] cipherTests =
+ {
+ "512",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F",
+ "98BCC10405AB0BFC686BECECAAD01AC19B452511BCEB9CB094F905C51CA45430",
+ "00112233445566778899AABBCCDDEEFF102132435465768798A9BACBDCEDFE0F",
+
+ };
+
+ public String getName()
+ {
+ return "Shacal2";
+ }
+
+ public void testECB(
+ int strength,
+ byte[] keyBytes,
+ byte[] input,
+ byte[] output)
+ throws Exception
+ {
+ Key key;
+ Cipher in, out;
+ CipherInputStream cIn;
+ CipherOutputStream cOut;
+ ByteArrayInputStream bIn;
+ ByteArrayOutputStream bOut;
+
+ key = new SecretKeySpec(keyBytes, "Shacal2");
+
+ in = Cipher.getInstance("Shacal2/ECB/NoPadding", "BC");
+ out = Cipher.getInstance("Shacal2/ECB/NoPadding", "BC");
+ try
+ {
+ out.init(Cipher.ENCRYPT_MODE, key);
+ }
+ catch (Exception e)
+ {
+ fail("Shacal2 failed initialisation - " + e.toString(), e);
+ }
+
+ try
+ {
+ in.init(Cipher.DECRYPT_MODE, key);
+ }
+ catch (Exception e)
+ {
+ fail("Shacal2 failed initialisation - " + e.toString(), e);
+ }
+
+ //
+ // encryption pass
+ //
+ bOut = new ByteArrayOutputStream();
+
+ cOut = new CipherOutputStream(bOut, out);
+
+ try
+ {
+ for (int i = 0; i != input.length / 2; i++)
+ {
+ cOut.write(input[i]);
+ }
+ cOut.write(input, input.length / 2, input.length - input.length / 2);
+ cOut.close();
+ }
+ catch (IOException e)
+ {
+ fail("Shacal2 failed encryption - " + e.toString(), e);
+ }
+
+ byte[] bytes;
+
+ bytes = bOut.toByteArray();
+
+ if (!areEqual(bytes, output))
+ {
+ fail("Shacal2 failed encryption - expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(bytes)));
+ }
+
+ //
+ // decryption pass
+ //
+ bIn = new ByteArrayInputStream(bytes);
+
+ cIn = new CipherInputStream(bIn, in);
+
+ try
+ {
+ DataInputStream dIn = new DataInputStream(cIn);
+
+ bytes = new byte[input.length];
+
+ for (int i = 0; i != input.length / 2; i++)
+ {
+ bytes[i] = (byte)dIn.read();
+ }
+ dIn.readFully(bytes, input.length / 2, bytes.length - input.length / 2);
+ }
+ catch (Exception e)
+ {
+ fail("Shacal2 failed encryption - " + e.toString(), e);
+ }
+
+ if (!areEqual(bytes, input))
+ {
+ fail("Shacal2 failed decryption - expected " + new String(Hex.encode(input)) + " got " + new String(Hex.encode(bytes)));
+ }
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ for (int i = 0; i != cipherTests.length; i += 4)
+ {
+ testECB(Integer.parseInt(cipherTests[i]),
+ Hex.decode(cipherTests[i + 1]),
+ Hex.decode(cipherTests[i + 2]),
+ Hex.decode(cipherTests[i + 3]));
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+
+ runTest(new Shacal2Test());
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/test/SkeinTest.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/SkeinTest.java
new file mode 100644
index 0000000..5bc5387
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/test/SkeinTest.java
@@ -0,0 +1,316 @@
+package org.bouncycastle.jce.provider.test;
+
+import java.security.MessageDigest;
+import java.security.Security;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.jcajce.spec.SkeinParameterSpec;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
+
+public class SkeinTest
+ extends SimpleTest
+{
+ final static String provider = "BC";
+
+ static private byte[] nullMsg = new byte[0];
+
+ static private String[][] nullVectors =
+ {
+ { "Skein-256-128", "07e8ff2191c5052e1a25914c7c213078" },
+ { "Skein-256-160", "ff800bed6d2044ee9d604a674e3fda50d9b24a72" },
+ { "Skein-256-224", "0fadf1fa39e3837a95b3660b4184d9c2f3cfc94b55d8e7a083278bf8" },
+ { "Skein-256-256", "c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba" },
+ { "Skein-512-128", "7c9aff5c3738e3faadc7a5265768def1" },
+ { "Skein-512-160", "49daf1ccebb3544bc93cb5019ba91b0eea8876ee" },
+ { "Skein-512-224", "1541ae9fc3ebe24eb758ccb1fd60c2c31a9ebfe65b220086e7819e25" },
+ { "Skein-512-256", "39ccc4554a8b31853b9de7a1fe638a24cce6b35a55f2431009e18780335d2621" },
+ { "Skein-512-384", "dd5aaf4589dc227bd1eb7bc68771f5baeaa3586ef6c7680167a023ec8ce26980f06c4082c488b4ac9ef313f8cbe70808" },
+ { "Skein-512-512", "bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af41fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a" },
+ { "Skein-1024-384", "1fdb081963b960e89eaa11b87dda55e8a55a3e1066b30e38d8ae2a45242f7dadfaf06d80ca8a73cd8242ce5eab84c164" },
+ { "Skein-1024-512", "e2943eb0bc0efabd49503a76edf7cfcf072db25bad94ed44fe537284163f3119c47ac6f78699b4272255966e0aba65c75a0a64bd23df6996d1bc3174afd9fa8b" },
+ { "Skein-1024-1024", "0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6" },
+ };
+
+ static private byte[] shortMsg = Hex.decode("fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+ + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+ + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+ + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410");
+
+ static private String[][] shortVectors =
+ {
+ { "Skein-256-128", "9703382ea27dc2913e9d02cd976c582f" },
+ { "Skein-256-160", "0cd491b7715704c3a15a45a1ca8d93f8f646d3a1" },
+ { "Skein-256-224", "afd1e2d0f5b6cd4e1f8b3935fa2497d27ee97e72060adac099543487" },
+ { "Skein-256-256", "4de6fe2bfdaa3717a4261030ef0e044ced9225d066354610842a24a3eafd1dcf" },
+ { "Skein-512-128", "c901b1c04af3da4dce05d7975c419224" },
+ { "Skein-512-160", "ef03079d61b57c6047e15fa2b35b46fa24279539" },
+ { "Skein-512-224", "d9e3219b214e15246a2038f76a573e018ef69b385b3bd0576b558231" },
+ { "Skein-512-256", "809dd3f763a11af90912bbb92bc0d94361cbadab10142992000c88b4ceb88648" },
+ { "Skein-512-384", "825f5cbd5da8807a7b4d3e7bd9cd089ca3a256bcc064cd73a9355bf3ae67f2bf93ac7074b3b19907a0665ba3a878b262" },
+ { "Skein-512-512", "1a0d5abf4432e7c612d658f8dcfa35b0d1ab68b8d6bd4dd115c23cc57b5c5bcdde9bff0ece4208596e499f211bc07594d0cb6f3c12b0e110174b2a9b4b2cb6a9" },
+ { "Skein-1024-384", "9c3d0648c11f31c18395d5e6c8ebd73f43d189843fc45235e2c35e345e12d62bc21a41f65896ddc6a04969654c2e2ce9" },
+ { "Skein-1024-512", "5d0416f49c2d08dfd40a1446169dc6a1d516e23b8b853be4933513051de8d5c26baccffb08d3b16516ba3c6ccf3e9a6c78fff6ef955f2dbc56e1459a7cdba9a5" },
+ { "Skein-1024-1024", "96ca81f586c825d0360aef5acaec49ad55289e1797072eee198b64f349ce65b6e6ed804fe38f05135fe769cc56240ddda5098f620865ce4a4278c77fa2ec6bc31c0f354ca78c7ca81665bfcc5dc54258c3b8310ed421d9157f36c093814d9b25103d83e0ddd89c52d0050e13a64c6140e6388431961685734b1f138fe2243086" },
+ };
+
+ static private String[][] shortMacVectors =
+ {
+ { "Skein-Mac-256-128", "738f8b23541d50f691ab60af664c1583" },
+ { "Skein-Mac-256-160", "fe07fe50f99b7683bc16980041d8c045857f1189" },
+ { "Skein-Mac-256-224", "0bc19b185f5bfe50f0dba7ab49cd8ca9440260edd5a392d4bdcd2216" },
+ { "Skein-Mac-256-256", "9837ba53d23afcdabd9fcd614ce9e51c0ebecec7a210df4d3724ed591f026ef1" },
+ { "Skein-Mac-512-128", "6d34f46f2033947da7a9dfb068f4102d" },
+ { "Skein-Mac-512-160", "83cb2effecaa60674c2f9fb2fb6771a9899708ba" },
+ { "Skein-Mac-512-224", "e5f83c032875451f31977cd649c866708cb283a509e99cdfd4d995c5" },
+ { "Skein-Mac-512-256", "ed5507ec551ec944c6ed531990c32907eca885dd3af3d50dd09f1dbef422bb11" },
+ { "Skein-Mac-512-384", "b8f84a212723b92a591d6dc145c1655c70df710e9f3365064abdf79e9288dced2f0f895d81f465c811f1207b43b8cfce" },
+ { "Skein-Mac-512-512", "d13ba582467096a0f862114d97baa218512f39c82c984aa29deee724950d7f0929f726173dd42bc35566b0dbfbf5d2a1552ba6f132de301846714215b64e7f82" },
+ { "Skein-Mac-1024-384", "490dbbd049403e602ee3535181a70ee2eb5ade6d83b519953dd0d93c45729f098b679efcd64b5e3f03cd2fa9f1e70d69" },
+ { "Skein-Mac-1024-512", "ce7f1052fa486309d73058d1d4986f886d966a849c72d196bb2b97fc9fb0b1e69f43a521ebd979f5a5581bd12a0dbd0d1ee27af0929881f1d35c875cc0542ecf" },
+ { "Skein-Mac-1024-1024", "60cd8c755b331bcefe97be5a9fe6f63146d12520ca7b20dbc5c5370dae2ff9815c95fab564329a01eced76f0ecb1944ad52a74e89fa1b6cdcdcee4c71c2c18909c4d1324d279fac5ca2280eea0fa70521cf4ea8c616a3ac6082c2244bec5c1ab3a173faf29d84bec7fb852e278ed57785535c979b33b81465c437cd998c04b95" },
+ };
+
+ static private String[][] shortHMacVectors =
+ {
+ { "HMAC-Skein-256-128", "926a445d5218605286dfe0542a437012" },
+ { "HMAC-Skein-256-160", "5ebc30295e4562a879f94db531ada465073b8bb7" },
+ { "HMAC-Skein-256-224", "a05b3cfc6b86fda7f5dcf0afbb707dc745fa55279a3f80e2c9977ff1" },
+ { "HMAC-Skein-256-256", "51741f6e8ebf133216ac8e05c7a75a6339351fd2dcc4db04e418521c628a2111" },
+ { "HMAC-Skein-512-128", "ad51f8c7b1b347fe52f0f5c71ae9b8eb" },
+ { "HMAC-Skein-512-160", "e0d06c2d406f32bb14dbb2129176219b62d4f89f" },
+ { "HMAC-Skein-512-224", "e7e5327e2aaa88d0038049e8112db31df223be4c31da24abf03731a8" },
+ { "HMAC-Skein-512-256", "30177414f6e35019cacc2e3ae474b25765e6e0e541e16d754c3dad19df763ab0" },
+ { "HMAC-Skein-512-384", "7f0ba3c1c642cf09eb03d0e3760fe172f22fb263006b1fba5bdea1bfaf6e971c17e039abb0030d1a40ac94a747732cce" },
+ { "HMAC-Skein-512-512", "70d864e7f6cbd446778914a951d1961e646ee17a3da8eae551d29f4fafc540b0457cc9f8064c511b80dc29f8369fb5dc258559542abb5342c4892f22934bf5f1" },
+ { "HMAC-Skein-1024-384", "e7d3465b30b5089e24244e747a91f7cb255596b49843466497c07e120c5c2232f51151b185a1e8a5610f041a85cc59ee" },
+ { "HMAC-Skein-1024-512", "c428059ae2d17ba13e461384c4a64cb0be694909e7a04e4983a4fc16476d644c7764e0019b33ea2a8719f731a579f4f7015da7ec1bc56a4920071ac41da836fe" },
+ { "HMAC-Skein-1024-1024", "3ebd13ec7bf1533c343ac78e1b5146225ce7629787f3997b646139c1b80d6f54cd562b7625419ede8710d76410dfb8617514ca3f7abf17657d2bc96722071adb2a6ecd9795a1ef5e4734b450d588efcbc3220faf53c880e61438bb953e024e48db6a745d2368375ac792be858cd01915e28590d4d6d599be95f6e6ceed7d7d91" },
+ };
+
+ static private byte[] shortMacMessage = Hex.decode("d3090c72167517f7");
+ static private byte[] shortMacKey = Hex.decode("cb41f1706cde09651203c2d0efbaddf8");
+
+ static private byte[] keyIdentifier = "asecretkey".getBytes();
+ static private byte[] keyIdentifierVector = Hex.decode("ca9970a83997e1c346c4348b54cfc9ba7e19bfba");
+
+ public String getName()
+ {
+ return "Skein";
+ }
+
+ void test(String type, String algorithm, byte[] message, String expected) throws Exception
+ {
+ MessageDigest digest = MessageDigest.getInstance(algorithm, provider);
+
+ byte[] result = digest.digest(message);
+ byte[] result2 = digest.digest(message);
+
+ // test zero results valid
+ if (!MessageDigest.isEqual(result, Hex.decode(expected)))
+ {
+ fail(type + " result not equal for " + algorithm, expected, new String(Hex.encode(result)));
+ }
+
+ // test one digest the same message with the same instance
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail(type + " result object 1 not equal");
+ }
+
+ if (!MessageDigest.isEqual(result, Hex.decode(expected)))
+ {
+ fail(type + " result object 1 not equal");
+ }
+
+ // test two, single byte updates
+ for (int i = 0; i < message.length; i++)
+ {
+ digest.update(message[i]);
+ }
+ result2 = digest.digest();
+
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail(type + " result object 2 not equal");
+ }
+
+ // test three, two half updates
+ digest.update(message, 0, message.length / 2);
+ digest.update(message, message.length / 2, message.length - message.length / 2);
+ result2 = digest.digest();
+
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail(type + " result object 3 not equal");
+ }
+
+ // test four, clone test
+ digest.update(message, 0, message.length / 2);
+ MessageDigest d = (MessageDigest)digest.clone();
+ digest.update(message, message.length / 2, message.length - message.length / 2);
+ result2 = digest.digest();
+
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail(type + " result object 4(a) not equal");
+ }
+
+ d.update(message, message.length / 2, message.length - message.length / 2);
+ result2 = d.digest();
+
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail(type + " result object 4(b) not equal");
+ }
+
+ // test five, check reset() method
+ digest.update(message, 0, message.length / 2);
+ digest.reset();
+ digest.update(message, 0, message.length / 2);
+ digest.update(message, message.length / 2, message.length - message.length / 2);
+ result2 = digest.digest();
+
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail(type + " result object 5 not equal");
+ }
+ }
+
+ private void testMac(String algorithm, byte[] message, byte[] key, String expected) throws Exception
+ {
+ Mac mac = Mac.getInstance(algorithm, provider);
+
+ mac.init(new SecretKeySpec(key, algorithm));
+
+ byte[] result = mac.doFinal(message);
+ byte[] result2 = mac.doFinal(message);
+
+ // test zero results valid
+ if (!MessageDigest.isEqual(result, Hex.decode(expected)))
+ {
+ fail("null result not equal for " + algorithm, expected, new String(Hex.encode(result)));
+ }
+
+ // test one digest the same message with the same instance
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail("Result object 1 not equal");
+ }
+
+ if (!MessageDigest.isEqual(result, Hex.decode(expected)))
+ {
+ fail("Result object 1 not equal");
+ }
+
+ // test two, single byte updates
+ for (int i = 0; i < message.length; i++)
+ {
+ mac.update(message[i]);
+ }
+ result2 = mac.doFinal();
+
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail("Result object 2 not equal");
+ }
+
+ // test three, two half updates
+ mac.update(message, 0, message.length / 2);
+ mac.update(message, message.length / 2, message.length - message.length / 2);
+ result2 = mac.doFinal();
+
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail("Result object 3 not equal");
+ }
+
+ // test five, check reset() method
+ mac.update(message, 0, message.length / 2);
+ mac.reset();
+ mac.update(message, 0, message.length / 2);
+ mac.update(message, message.length / 2, message.length - message.length / 2);
+ result2 = mac.doFinal();
+
+ if (!MessageDigest.isEqual(result, result2))
+ {
+ fail("Result object 5 not equal");
+ }
+
+ // test six, check KeyGenerator
+ KeyGenerator generator = KeyGenerator.getInstance(algorithm, provider);
+
+ mac = Mac.getInstance(algorithm, provider);
+ final SecretKey generatedKey = generator.generateKey();
+ if (generatedKey.getEncoded().length != mac.getMacLength())
+ {
+ fail("Default mac key length for " + algorithm);
+ }
+ mac.init(generatedKey);
+ mac.update(message);
+ mac.doFinal();
+ }
+
+ private void testParameters() throws Exception
+ {
+ Mac mac = Mac.getInstance("Skein-Mac-512-160", provider);
+
+ // test six, init using SkeinParameters
+ mac.init(new SecretKeySpec(shortMacKey, "Skein-Mac-512-160"),
+ new SkeinParameterSpec.Builder().setKeyIdentifier(keyIdentifier).build());
+ byte[] result = mac.doFinal(shortMacMessage);
+
+ if (!MessageDigest.isEqual(result, keyIdentifierVector))
+ {
+ fail("Mac with key identifier failed.", new String(Hex.encode(keyIdentifierVector)), new String(Hex.encode(result)));
+ }
+ }
+
+ private void testMacKeyGenerators(String algorithm) throws Exception
+ {
+ KeyGenerator gen = KeyGenerator.getInstance(algorithm);
+
+ int outputSize = Integer.parseInt(algorithm.substring(algorithm.lastIndexOf('-') + 1));
+ SecretKey key = gen.generateKey();
+
+ if (key.getEncoded().length != (outputSize / 8)) {
+ fail(algorithm + " key length should be equal to output size " + (outputSize) + ", but was " + key.getEncoded().length * 8);
+ }
+ }
+
+ public void performTest() throws Exception
+ {
+ for (int i = 0; i < nullVectors.length; i++)
+ {
+ test("Null message", nullVectors[i][0], nullMsg, nullVectors[i][1]);
+ }
+ for (int i = 0; i < shortVectors.length; i++)
+ {
+ test("Short message", shortVectors[i][0], shortMsg, shortVectors[i][1]);
+ }
+ for (int i = 0; i < shortMacVectors.length; i++)
+ {
+ testMac(shortMacVectors[i][0], shortMacMessage, shortMacKey, shortMacVectors[i][1]);
+ testMacKeyGenerators(shortMacVectors[i][0]);
+ }
+
+ for (int i = 0; i < shortHMacVectors.length; i++)
+ {
+ testMac(shortHMacVectors[i][0], shortMacMessage, shortMacKey, shortHMacVectors[i][1]);
+ testMacKeyGenerators(shortHMacVectors[i][0]);
+ }
+ testParameters();
+ }
+
+ public static void main(String[] args)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+
+ runTest(new SkeinTest());
+ }
+}
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 84ebf70..b3d239e 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECNamedCurveSpec.java
@@ -49,7 +49,8 @@ public class ECNamedCurveSpec
private static ECPoint convertPoint(
org.bouncycastle.math.ec.ECPoint g)
{
- return new ECPoint(g.getX().toBigInteger(), g.getY().toBigInteger());
+ g = g.normalize();
+ return new ECPoint(g.getAffineXCoord().toBigInteger(), g.getAffineYCoord().toBigInteger());
}
public ECNamedCurveSpec(
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java
index e774a11..df91412 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECParameterSpec.java
@@ -24,7 +24,7 @@ public class ECParameterSpec
BigInteger n)
{
this.curve = curve;
- this.G = G;
+ this.G = G.normalize();
this.n = n;
this.h = BigInteger.valueOf(1);
this.seed = null;
@@ -37,7 +37,7 @@ public class ECParameterSpec
BigInteger h)
{
this.curve = curve;
- this.G = G;
+ this.G = G.normalize();
this.n = n;
this.h = h;
this.seed = null;
@@ -51,7 +51,7 @@ public class ECParameterSpec
byte[] seed)
{
this.curve = curve;
- this.G = G;
+ this.G = G.normalize();
this.n = n;
this.h = h;
this.seed = seed;
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java
index debab00..0e21a5b 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/ECPublicKeySpec.java
@@ -22,7 +22,14 @@ public class ECPublicKeySpec
{
super(spec);
- this.q = q;
+ if (q.getCurve() != null)
+ {
+ this.q = q.normalize();
+ }
+ else
+ {
+ this.q = q;
+ }
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java
index 384d871..d03fbfe 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/GOST28147ParameterSpec.java
@@ -1,73 +1,48 @@
-package org.bouncycastle.jce.spec;
-
-import java.security.spec.AlgorithmParameterSpec;
-
-import org.bouncycastle.crypto.engines.GOST28147Engine;
+package org.bouncycastle.jce.spec;
/**
* A parameter spec for the GOST-28147 cipher.
+ * @deprecated use org.bouncycastle.jcajce.spec.GOST28147ParameterSpec
*/
public class GOST28147ParameterSpec
- implements AlgorithmParameterSpec
+ extends org.bouncycastle.jcajce.spec.GOST28147ParameterSpec
{
- private byte[] iv = null;
- private byte[] sBox = null;
-
+ /**
+ * @deprecated
+ */
public GOST28147ParameterSpec(
byte[] sBox)
{
- this.sBox = new byte[sBox.length];
-
- System.arraycopy(sBox, 0, this.sBox, 0, sBox.length);
+ super(sBox);
}
+ /**
+ * @deprecated
+ */
public GOST28147ParameterSpec(
byte[] sBox,
byte[] iv)
{
- this(sBox);
- this.iv = new byte[iv.length];
-
- System.arraycopy(iv, 0, this.iv, 0, iv.length);
+ super(sBox, iv);
+
}
-
+
+ /**
+ * @deprecated
+ */
public GOST28147ParameterSpec(
String sBoxName)
{
- this.sBox = GOST28147Engine.getSBox(sBoxName);
+ super(sBoxName);
}
+ /**
+ * @deprecated
+ */
public GOST28147ParameterSpec(
String sBoxName,
byte[] iv)
{
- this(sBoxName);
- this.iv = new byte[iv.length];
-
- System.arraycopy(iv, 0, this.iv, 0, iv.length);
- }
-
- public byte[] getSbox()
- {
- return sBox;
- }
-
- /**
- * Returns the IV or null if this parameter set does not contain an IV.
- *
- * @return the IV or null if this parameter set does not contain an IV.
- */
- public byte[] getIV()
- {
- if (iv == null)
- {
- return null;
- }
-
- byte[] tmp = new byte[iv.length];
-
- System.arraycopy(iv, 0, tmp, 0, tmp.length);
-
- return tmp;
+ super(sBoxName, iv);
}
} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java b/bcprov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java
index 2a7ceb5..4111072 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/spec/RepeatedSecretKeySpec.java
@@ -1,34 +1,17 @@
package org.bouncycastle.jce.spec;
-
-import javax.crypto.SecretKey;
-
/**
* A simple object to indicate that a symmetric cipher should reuse the
* last key provided.
+ * @deprecated use super class org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec
*/
public class RepeatedSecretKeySpec
- implements SecretKey
+ extends org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec
{
private String algorithm;
public RepeatedSecretKeySpec(String algorithm)
{
- this.algorithm = algorithm;
- }
-
- public String getAlgorithm()
- {
- return algorithm;
- }
-
- public String getFormat()
- {
- return null;
- }
-
- public byte[] getEncoded()
- {
- return null;
+ super(algorithm);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/spec/package.html b/bcprov/src/main/java/org/bouncycastle/jce/spec/package.html
deleted file mode 100644
index 6f37057..0000000
--- a/bcprov/src/main/java/org/bouncycastle/jce/spec/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Parameter specifications for supporting El Gamal, and Elliptic Curve.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
new file mode 100644
index 0000000..69ab797
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/AbstractECMultiplier.java
@@ -0,0 +1,20 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public abstract class AbstractECMultiplier implements ECMultiplier
+{
+ public ECPoint multiply(ECPoint p, BigInteger k)
+ {
+ int sign = k.signum();
+ if (sign == 0 || p.isInfinity())
+ {
+ return p.getCurve().getInfinity();
+ }
+
+ ECPoint positive = multiplyPositive(p, k.abs());
+ return sign > 0 ? positive : positive.negate();
+ }
+
+ protected abstract ECPoint multiplyPositive(ECPoint p, BigInteger k);
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java
new file mode 100644
index 0000000..aae2e00
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/DoubleAddMultiplier.java
@@ -0,0 +1,24 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public class DoubleAddMultiplier extends AbstractECMultiplier
+{
+ /**
+ * Joye's double-add algorithm.
+ */
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ ECPoint[] R = new ECPoint[]{ p.getCurve().getInfinity(), p };
+
+ int n = k.bitLength();
+ for (int i = 0; i < n; ++i)
+ {
+ int b = k.testBit(i) ? 1 : 0;
+ int bp = 1 - b;
+ R[bp] = R[bp].twicePlus(R[b]);
+ }
+
+ return R[0];
+ }
+}
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 78a7a8f..d640b5f 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
@@ -7,16 +7,13 @@ public class ECAlgorithms
public static ECPoint sumOfTwoMultiplies(ECPoint P, BigInteger a,
ECPoint Q, BigInteger b)
{
- ECCurve c = P.getCurve();
- if (!c.equals(Q.getCurve()))
- {
- throw new IllegalArgumentException("P and Q must be on same curve");
- }
+ ECCurve cp = P.getCurve();
+ Q = importPoint(cp, Q);
// Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
- if (c instanceof ECCurve.F2m)
+ if (cp instanceof ECCurve.F2m)
{
- ECCurve.F2m f2mCurve = (ECCurve.F2m)c;
+ ECCurve.F2m f2mCurve = (ECCurve.F2m)cp;
if (f2mCurve.isKoblitz())
{
return P.multiply(a).add(Q.multiply(b));
@@ -48,43 +45,83 @@ public class ECAlgorithms
public static ECPoint shamirsTrick(ECPoint P, BigInteger k,
ECPoint Q, BigInteger l)
{
- if (!P.getCurve().equals(Q.getCurve()))
+ ECCurve cp = P.getCurve();
+ Q = importPoint(cp, Q);
+
+ return implShamirsTrick(P, k, Q, l);
+ }
+
+ public static ECPoint importPoint(ECCurve c, ECPoint p)
+ {
+ ECCurve cp = p.getCurve();
+ if (!c.equals(cp))
{
- throw new IllegalArgumentException("P and Q must be on same curve");
+ throw new IllegalArgumentException("Point must be on the same curve");
}
+ return c.importPoint(p);
+ }
- return implShamirsTrick(P, k, Q, l);
+ static void implMontgomeryTrick(ECFieldElement[] zs, int off, int len)
+ {
+ /*
+ * Uses the "Montgomery Trick" to invert many field elements, with only a single actual
+ * field inversion. See e.g. the paper:
+ * "Fast Multi-scalar Multiplication Methods on Elliptic Curves with Precomputation Strategy Using Montgomery Trick"
+ * by Katsuyuki Okeya, Kouichi Sakurai.
+ */
+
+ ECFieldElement[] c = new ECFieldElement[len];
+ c[0] = zs[off];
+
+ int i = 0;
+ while (++i < len)
+ {
+ c[i] = c[i - 1].multiply(zs[off + i]);
+ }
+
+ ECFieldElement u = c[--i].invert();
+
+ while (i > 0)
+ {
+ int j = off + i--;
+ ECFieldElement tmp = zs[j];
+ zs[j] = c[i].multiply(u);
+ u = u.multiply(tmp);
+ }
+
+ zs[off] = u;
}
- private static ECPoint implShamirsTrick(ECPoint P, BigInteger k,
+ static ECPoint implShamirsTrick(ECPoint P, BigInteger k,
ECPoint Q, BigInteger l)
{
- int m = Math.max(k.bitLength(), l.bitLength());
- ECPoint Z = P.add(Q);
- ECPoint R = P.getCurve().getInfinity();
+ ECCurve curve = P.getCurve();
+ ECPoint infinity = curve.getInfinity();
+
+ // TODO conjugate co-Z addition (ZADDC) can return both of these
+ ECPoint PaddQ = P.add(Q);
+ ECPoint PsubQ = P.subtract(Q);
+
+ ECPoint[] points = new ECPoint[]{ Q, PsubQ, P, PaddQ };
+ curve.normalizeAll(points);
- for (int i = m - 1; i >= 0; --i)
+ ECPoint[] table = new ECPoint[] {
+ points[3].negate(), points[2].negate(), points[1].negate(),
+ points[0].negate(), infinity, points[0],
+ points[1], points[2], points[3] };
+
+ byte[] jsf = WNafUtil.generateJSF(k, l);
+
+ ECPoint R = infinity;
+
+ int i = jsf.length;
+ while (--i >= 0)
{
- R = R.twice();
+ int jsfi = jsf[i];
+ int kDigit = (jsfi >> 4), lDigit = ((jsfi << 28) >> 28);
- if (k.testBit(i))
- {
- if (l.testBit(i))
- {
- R = R.add(Z);
- }
- else
- {
- R = R.add(P);
- }
- }
- else
- {
- if (l.testBit(i))
- {
- R = R.add(Q);
- }
- }
+ int index = 4 + (kDigit * 3) + lDigit;
+ R = R.twicePlus(table[index]);
}
return R;
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
index 58281af..19f0062 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
@@ -3,18 +3,199 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
import java.util.Random;
+import org.bouncycastle.util.BigIntegers;
+
/**
* base class for an elliptic curve
*/
public abstract class ECCurve
{
- ECFieldElement a, b;
+ public static final int COORD_AFFINE = 0;
+ public static final int COORD_HOMOGENEOUS = 1;
+ public static final int COORD_JACOBIAN = 2;
+ public static final int COORD_JACOBIAN_CHUDNOVSKY = 3;
+ public static final int COORD_JACOBIAN_MODIFIED = 4;
+ public static final int COORD_LAMBDA_AFFINE = 5;
+ public static final int COORD_LAMBDA_PROJECTIVE = 6;
+ public static final int COORD_SKEWED = 7;
+
+ public static int[] getAllCoordinateSystems()
+ {
+ return new int[]{ COORD_AFFINE, COORD_HOMOGENEOUS, COORD_JACOBIAN, COORD_JACOBIAN_CHUDNOVSKY,
+ COORD_JACOBIAN_MODIFIED, COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE, COORD_SKEWED };
+ }
+
+ public class Config
+ {
+ protected int coord;
+ protected ECMultiplier multiplier;
+
+ Config(int coord, ECMultiplier multiplier)
+ {
+ this.coord = coord;
+ this.multiplier = multiplier;
+ }
+
+ public Config setCoordinateSystem(int coord)
+ {
+ this.coord = coord;
+ return this;
+ }
+
+ public Config setMultiplier(ECMultiplier multiplier)
+ {
+ this.multiplier = multiplier;
+ return this;
+ }
+
+ public ECCurve create()
+ {
+ if (!supportsCoordinateSystem(coord))
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+
+ ECCurve c = cloneCurve();
+ if (c == ECCurve.this)
+ {
+ throw new IllegalStateException("implementation returned current curve");
+ }
+
+ c.coord = coord;
+ c.multiplier = multiplier;
+
+ return c;
+ }
+ }
+
+ protected ECFieldElement a, b;
+ protected int coord = COORD_AFFINE;
+ protected ECMultiplier multiplier = null;
public abstract int getFieldSize();
public abstract ECFieldElement fromBigInteger(BigInteger x);
- public abstract ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression);
+ public Config configure()
+ {
+ return new Config(this.coord, this.multiplier);
+ }
+
+ public ECPoint createPoint(BigInteger x, BigInteger y)
+ {
+ return createPoint(x, y, false);
+ }
+
+ /**
+ * @deprecated per-point compression property will be removed, use {@link #createPoint(BigInteger, BigInteger)}
+ * and refer {@link ECPoint#getEncoded(boolean)}
+ */
+ public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
+ {
+ return createRawPoint(fromBigInteger(x), fromBigInteger(y), withCompression);
+ }
+
+ protected abstract ECCurve cloneCurve();
+
+ protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression);
+
+ protected ECMultiplier createDefaultMultiplier()
+ {
+ return new WNafL2RMultiplier();
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ return coord == COORD_AFFINE;
+ }
+
+ public PreCompInfo getPreCompInfo(ECPoint p)
+ {
+ checkPoint(p);
+ return p.preCompInfo;
+ }
+
+ /**
+ * Sets the <code>PreCompInfo</code> for a point on this curve. Used by
+ * <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use
+ * by subsequent multiplication.
+ *
+ * @param point
+ * The <code>ECPoint</code> to store precomputations for.
+ * @param preCompInfo
+ * The values precomputed by the <code>ECMultiplier</code>.
+ */
+ public void setPreCompInfo(ECPoint point, PreCompInfo preCompInfo)
+ {
+ checkPoint(point);
+ point.preCompInfo = preCompInfo;
+ }
+
+ public ECPoint importPoint(ECPoint p)
+ {
+ if (this == p.getCurve())
+ {
+ return p;
+ }
+ if (p.isInfinity())
+ {
+ return getInfinity();
+ }
+
+ // TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates.
+ p = p.normalize();
+
+ return createPoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression);
+ }
+
+ /**
+ * Normalization ensures that any projective coordinate is 1, and therefore that the x, y
+ * coordinates reflect those of the equivalent point in an affine coordinate system. Where more
+ * than one point is to be normalized, this method will generally be more efficient than
+ * normalizing each point separately.
+ *
+ * @param points
+ * An array of points that will be updated in place with their normalized versions,
+ * where necessary
+ */
+ public void normalizeAll(ECPoint[] points)
+ {
+ checkPoints(points);
+
+ if (this.getCoordinateSystem() == ECCurve.COORD_AFFINE)
+ {
+ return;
+ }
+
+ /*
+ * Figure out which of the points actually need to be normalized
+ */
+ ECFieldElement[] zs = new ECFieldElement[points.length];
+ int[] indices = new int[points.length];
+ int count = 0;
+ for (int i = 0; i < points.length; ++i)
+ {
+ ECPoint p = points[i];
+ if (null != p && !p.isNormalized())
+ {
+ zs[count] = p.getZCoord(0);
+ indices[count++] = i;
+ }
+ }
+
+ if (count == 0)
+ {
+ return;
+ }
+
+ ECAlgorithms.implMontgomeryTrick(zs, 0, count);
+
+ for (int j = 0; j < count; ++j)
+ {
+ int index = indices[j];
+ points[index] = points[index].normalize(zs[j]);
+ }
+ }
public abstract ECPoint getInfinity();
@@ -28,9 +209,26 @@ public abstract class ECCurve
return b;
}
+ public int getCoordinateSystem()
+ {
+ return coord;
+ }
+
protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1);
/**
+ * Sets the default <code>ECMultiplier</code>, unless already set.
+ */
+ public ECMultiplier getMultiplier()
+ {
+ if (this.multiplier == null)
+ {
+ this.multiplier = createDefaultMultiplier();
+ }
+ return this.multiplier;
+ }
+
+ /**
* Decode a point on this curve from its ASN.1 encoding. The different
* encodings are taken account of, including point compression for
* <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
@@ -62,9 +260,9 @@ public abstract class ECCurve
}
int yTilde = encoded[0] & 1;
- BigInteger X1 = fromArray(encoded, 1, expectedLength);
+ BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
- p = decompressPoint(yTilde, X1);
+ p = decompressPoint(yTilde, X);
break;
}
case 0x04: // uncompressed
@@ -76,10 +274,10 @@ public abstract class ECCurve
throw new IllegalArgumentException("Incorrect length for uncompressed/hybrid encoding");
}
- BigInteger X1 = fromArray(encoded, 1, expectedLength);
- BigInteger Y1 = fromArray(encoded, 1 + expectedLength, expectedLength);
+ BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength);
+ BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength);
- p = createPoint(X1, Y1, false);
+ p = createPoint(X, Y);
break;
}
default:
@@ -89,11 +287,29 @@ public abstract class ECCurve
return p;
}
- private static BigInteger fromArray(byte[] buf, int off, int length)
+ protected void checkPoint(ECPoint point)
{
- byte[] mag = new byte[length];
- System.arraycopy(buf, off, mag, 0, length);
- return new BigInteger(1, mag);
+ if (null == point || (this != point.getCurve()))
+ {
+ throw new IllegalArgumentException("'point' must be non-null and on this curve");
+ }
+ }
+
+ protected void checkPoints(ECPoint[] points)
+ {
+ if (points == null)
+ {
+ throw new IllegalArgumentException("'points' cannot be null");
+ }
+
+ for (int i = 0; i < points.length; ++i)
+ {
+ ECPoint point = points[i];
+ if (null != point && this != point.getCurve())
+ {
+ throw new IllegalArgumentException("'points' entries must be null or on this curve");
+ }
+ }
}
/**
@@ -101,15 +317,50 @@ public abstract class ECCurve
*/
public static class Fp extends ECCurve
{
- BigInteger q;
+ private static final int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
+
+ BigInteger q, r;
ECPoint.Fp infinity;
public Fp(BigInteger q, BigInteger a, BigInteger b)
{
this.q = q;
+ this.r = ECFieldElement.Fp.calculateResidue(q);
+ this.infinity = new ECPoint.Fp(this, null, null);
+
this.a = fromBigInteger(a);
this.b = fromBigInteger(b);
+ this.coord = FP_DEFAULT_COORDS;
+ }
+
+ protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)
+ {
+ this.q = q;
+ this.r = r;
this.infinity = new ECPoint.Fp(this, null, null);
+
+ this.a = a;
+ this.b = b;
+ this.coord = FP_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new Fp(q, r, a, b);
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_AFFINE:
+ case COORD_HOMOGENEOUS:
+ case COORD_JACOBIAN:
+ case COORD_JACOBIAN_MODIFIED:
+ return true;
+ default:
+ return false;
+ }
}
public BigInteger getQ()
@@ -124,12 +375,34 @@ public abstract class ECCurve
public ECFieldElement fromBigInteger(BigInteger x)
{
- return new ECFieldElement.Fp(this.q, x);
+ return new ECFieldElement.Fp(this.q, this.r, x);
}
- public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
{
- return new ECPoint.Fp(this, fromBigInteger(x), fromBigInteger(y), withCompression);
+ return new ECPoint.Fp(this, x, y, withCompression);
+ }
+
+ public ECPoint importPoint(ECPoint p)
+ {
+ if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity())
+ {
+ switch (p.getCurve().getCoordinateSystem())
+ {
+ case COORD_JACOBIAN:
+ case COORD_JACOBIAN_CHUDNOVSKY:
+ case COORD_JACOBIAN_MODIFIED:
+ return new ECPoint.Fp(this,
+ fromBigInteger(p.x.toBigInteger()),
+ fromBigInteger(p.y.toBigInteger()),
+ new ECFieldElement[]{ fromBigInteger(p.zs[0].toBigInteger()) },
+ p.withCompression);
+ default:
+ break;
+ }
+ }
+
+ return super.importPoint(p);
}
protected ECPoint decompressPoint(int yTilde, BigInteger X1)
@@ -148,9 +421,7 @@ public abstract class ECCurve
}
BigInteger betaValue = beta.toBigInteger();
- int bit0 = betaValue.testBit(0) ? 1 : 0;
-
- if (bit0 != yTilde)
+ if (betaValue.testBit(0) != (yTilde == 1))
{
// Use the other root
beta = fromBigInteger(q.subtract(betaValue));
@@ -195,6 +466,8 @@ public abstract class ECCurve
*/
public static class F2m extends ECCurve
{
+ private static final int F2M_DEFAULT_COORDS = COORD_AFFINE;
+
/**
* The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
*/
@@ -401,9 +674,53 @@ public abstract class ECCurve
}
}
+ this.infinity = new ECPoint.F2m(this, null, null);
this.a = fromBigInteger(a);
this.b = fromBigInteger(b);
+ this.coord = F2M_DEFAULT_COORDS;
+ }
+
+ protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger n, BigInteger h)
+ {
+ this.m = m;
+ this.k1 = k1;
+ this.k2 = k2;
+ this.k3 = k3;
+ this.n = n;
+ this.h = h;
+
this.infinity = new ECPoint.F2m(this, null, null);
+ this.a = a;
+ this.b = b;
+ this.coord = F2M_DEFAULT_COORDS;
+ }
+
+ protected ECCurve cloneCurve()
+ {
+ return new F2m(m, k1, k2, k3, a, b, n, h);
+ }
+
+ public boolean supportsCoordinateSystem(int coord)
+ {
+ switch (coord)
+ {
+ case COORD_AFFINE:
+ case COORD_HOMOGENEOUS:
+ case COORD_LAMBDA_PROJECTIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected ECMultiplier createDefaultMultiplier()
+ {
+ if (isKoblitz())
+ {
+ return new WTauNafMultiplier();
+ }
+
+ return super.createDefaultMultiplier();
}
public int getFieldSize()
@@ -418,7 +735,32 @@ public abstract class ECCurve
public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
{
- return new ECPoint.F2m(this, fromBigInteger(x), fromBigInteger(y), withCompression);
+ ECFieldElement X = fromBigInteger(x), Y = fromBigInteger(y);
+
+ switch (this.getCoordinateSystem())
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ if (!X.isZero())
+ {
+ // Y becomes Lambda (X + Y/X) here
+ Y = Y.divide(X).add(X);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return createRawPoint(X, Y, withCompression);
+ }
+
+ protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ return new ECPoint.F2m(this, x, y, withCompression);
}
public ECPoint getInfinity()
@@ -432,10 +774,7 @@ public abstract class ECCurve
*/
public boolean isKoblitz()
{
- return ((n != null) && (h != null) &&
- ((a.toBigInteger().equals(ECConstants.ZERO)) ||
- (a.toBigInteger().equals(ECConstants.ONE))) &&
- (b.toBigInteger().equals(ECConstants.ONE)));
+ return n != null && h != null && a.bitLength() <= 1 && b.bitLength() == 1;
}
/**
@@ -480,7 +819,7 @@ public abstract class ECCurve
{
ECFieldElement xp = fromBigInteger(X1);
ECFieldElement yp = null;
- if (xp.toBigInteger().equals(ECConstants.ZERO))
+ if (xp.isZero())
{
yp = (ECFieldElement.F2m)b;
for (int i = 0; i < m - 1; i++)
@@ -491,17 +830,31 @@ public abstract class ECCurve
else
{
ECFieldElement beta = xp.add(a).add(b.multiply(xp.square().invert()));
- ECFieldElement z = solveQuadradicEquation(beta);
+ ECFieldElement z = solveQuadraticEquation(beta);
if (z == null)
{
throw new IllegalArgumentException("Invalid point compression");
}
- int zBit = z.toBigInteger().testBit(0) ? 1 : 0;
- if (zBit != yTilde)
+ if (z.testBitZero() != (yTilde == 1))
{
- z = z.add(fromBigInteger(ECConstants.ONE));
+ z = z.addOne();
}
+
yp = xp.multiply(z);
+
+ switch (this.getCoordinateSystem())
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ yp = yp.divide(xp).add(xp);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
}
return new ECPoint.F2m(this, xp, yp, true);
@@ -512,28 +865,26 @@ public abstract class ECCurve
* D.1.6) The other solution is <code>z + 1</code>.
*
* @param beta
- * The value to solve the qradratic equation for.
+ * The value to solve the quadratic equation for.
* @return the solution for <code>z<sup>2</sup> + z = beta</code> or
* <code>null</code> if no solution exists.
*/
- private ECFieldElement solveQuadradicEquation(ECFieldElement beta)
+ private ECFieldElement solveQuadraticEquation(ECFieldElement beta)
{
- ECFieldElement zeroElement = new ECFieldElement.F2m(
- this.m, this.k1, this.k2, this.k3, ECConstants.ZERO);
-
- if (beta.toBigInteger().equals(ECConstants.ZERO))
+ if (beta.isZero())
{
- return zeroElement;
+ return beta;
}
+ ECFieldElement zeroElement = fromBigInteger(ECConstants.ZERO);
+
ECFieldElement z = null;
- ECFieldElement gamma = zeroElement;
+ ECFieldElement gamma = null;
Random rand = new Random();
do
{
- ECFieldElement t = new ECFieldElement.F2m(this.m, this.k1,
- this.k2, this.k3, new BigInteger(m, rand));
+ ECFieldElement t = fromBigInteger(new BigInteger(m, rand));
z = zeroElement;
ECFieldElement w = beta;
for (int i = 1; i <= m - 1; i++)
@@ -542,13 +893,13 @@ public abstract class ECCurve
z = z.square().add(w2.multiply(t));
w = w2.add(beta);
}
- if (!w.toBigInteger().equals(ECConstants.ZERO))
+ if (!w.isZero())
{
return null;
}
gamma = z.square().add(z);
}
- while (gamma.toBigInteger().equals(ECConstants.ZERO));
+ while (gamma.isZero());
return z;
}
@@ -567,7 +918,7 @@ public abstract class ECCurve
}
ECCurve.F2m other = (ECCurve.F2m)anObject;
-
+
return (this.m == other.m) && (this.k1 == other.k1)
&& (this.k2 == other.k2) && (this.k3 == other.k3)
&& a.equals(other.a) && b.equals(other.b);
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 b5e9aa5..87608eb 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECFieldElement.java
@@ -3,14 +3,17 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
import java.util.Random;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.BigIntegers;
+
public abstract class ECFieldElement
implements ECConstants
{
-
public abstract BigInteger toBigInteger();
public abstract String getFieldName();
public abstract int getFieldSize();
public abstract ECFieldElement add(ECFieldElement b);
+ public abstract ECFieldElement addOne();
public abstract ECFieldElement subtract(ECFieldElement b);
public abstract ECFieldElement multiply(ECFieldElement b);
public abstract ECFieldElement divide(ECFieldElement b);
@@ -19,27 +22,99 @@ public abstract class ECFieldElement
public abstract ECFieldElement invert();
public abstract ECFieldElement sqrt();
+ public int bitLength()
+ {
+ return toBigInteger().bitLength();
+ }
+
+ public boolean isZero()
+ {
+ return 0 == toBigInteger().signum();
+ }
+
+ public boolean testBitZero()
+ {
+ return toBigInteger().testBit(0);
+ }
+
public String toString()
{
- return this.toBigInteger().toString(2);
+ return this.toBigInteger().toString(16);
+ }
+
+ public byte[] getEncoded()
+ {
+ return BigIntegers.asUnsignedByteArray((getFieldSize() + 7) / 8, toBigInteger());
}
public static class Fp extends ECFieldElement
{
- BigInteger x;
+ BigInteger q, r, x;
- BigInteger q;
-
+// static int[] calculateNaf(BigInteger p)
+// {
+// int[] naf = WNafUtil.generateCompactNaf(p);
+//
+// int bit = 0;
+// for (int i = 0; i < naf.length; ++i)
+// {
+// int ni = naf[i];
+// int digit = ni >> 16, zeroes = ni & 0xFFFF;
+//
+// bit += zeroes;
+// naf[i] = digit < 0 ? ~bit : bit;
+// ++bit;
+// }
+//
+// int last = naf.length - 1;
+// if (last > 0 && last <= 16)
+// {
+// int top = naf[last], top2 = naf[last - 1];
+// if (top2 < 0)
+// {
+// top2 = ~top2;
+// }
+// if (top - top2 >= 64)
+// {
+// return naf;
+// }
+// }
+//
+// return null;
+// }
+
+ static BigInteger calculateResidue(BigInteger p)
+ {
+ int bitLength = p.bitLength();
+ if (bitLength > 128)
+ {
+ BigInteger firstWord = p.shiftRight(bitLength - 64);
+ if (firstWord.longValue() == -1L)
+ {
+ return ONE.shiftLeft(bitLength).subtract(p);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @deprecated Use ECCurve.fromBigInteger to construct field elements
+ */
public Fp(BigInteger q, BigInteger x)
{
- this.x = x;
-
- if (x.compareTo(q) >= 0)
+ this(q, calculateResidue(q), x);
+ }
+
+ Fp(BigInteger q, BigInteger r, BigInteger x)
+ {
+ if (x == null || x.signum() < 0 || x.compareTo(q) >= 0)
{
- throw new IllegalArgumentException("x value too large in field element");
+ throw new IllegalArgumentException("x value invalid in Fp field element");
}
this.q = q;
+ this.r = r;
+ this.x = x;
}
public BigInteger toBigInteger()
@@ -66,40 +141,70 @@ public abstract class ECFieldElement
{
return q;
}
-
+
public ECFieldElement add(ECFieldElement b)
{
- return new Fp(q, x.add(b.toBigInteger()).mod(q));
+ return new Fp(q, r, modAdd(x, b.toBigInteger()));
+ }
+
+ public ECFieldElement addOne()
+ {
+ BigInteger x2 = x.add(ECConstants.ONE);
+ if (x2.compareTo(q) == 0)
+ {
+ x2 = ECConstants.ZERO;
+ }
+ return new Fp(q, r, x2);
}
public ECFieldElement subtract(ECFieldElement b)
{
- return new Fp(q, x.subtract(b.toBigInteger()).mod(q));
+ BigInteger x2 = b.toBigInteger();
+ BigInteger x3 = x.subtract(x2);
+ if (x3.signum() < 0)
+ {
+ x3 = x3.add(q);
+ }
+ return new Fp(q, r, x3);
}
public ECFieldElement multiply(ECFieldElement b)
{
- return new Fp(q, x.multiply(b.toBigInteger()).mod(q));
+ return new Fp(q, r, modMult(x, b.toBigInteger()));
}
public ECFieldElement divide(ECFieldElement b)
{
- return new Fp(q, x.multiply(b.toBigInteger().modInverse(q)).mod(q));
+ return new Fp(q, modMult(x, b.toBigInteger().modInverse(q)));
}
public ECFieldElement negate()
{
- return new Fp(q, x.negate().mod(q));
+ BigInteger x2;
+ if (x.signum() == 0)
+ {
+ x2 = x;
+ }
+ else if (ONE.equals(r))
+ {
+ x2 = q.xor(x);
+ }
+ else
+ {
+ x2 = q.subtract(x);
+ }
+ return new Fp(q, r, x2);
}
public ECFieldElement square()
{
- return new Fp(q, x.multiply(x).mod(q));
+ return new Fp(q, r, modMult(x, x));
}
public ECFieldElement invert()
{
- return new Fp(q, x.modInverse(q));
+ // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
+ return new Fp(q, r, x.modInverse(q));
}
// D.1.4 91
@@ -120,7 +225,7 @@ public abstract class ECFieldElement
if (q.testBit(1))
{
// z = g^(u+1) + p, p = 4u + 3
- ECFieldElement z = new Fp(q, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q));
+ ECFieldElement z = new Fp(q, r, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q));
return z.square().equals(this) ? z : null;
}
@@ -138,7 +243,7 @@ public abstract class ECFieldElement
BigInteger k = u.shiftLeft(1).add(ECConstants.ONE);
BigInteger Q = this.x;
- BigInteger fourQ = Q.shiftLeft(2).mod(q);
+ BigInteger fourQ = modDouble(modDouble(Q));
BigInteger U, V;
Random rand = new Random();
@@ -152,11 +257,11 @@ public abstract class ECFieldElement
while (P.compareTo(q) >= 0
|| !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne)));
- BigInteger[] result = lucasSequence(q, P, Q, k);
+ BigInteger[] result = lucasSequence(P, Q, k);
U = result[0];
V = result[1];
- if (V.multiply(V).mod(q).equals(fourQ))
+ if (modMult(V, V).equals(fourQ))
{
// Integer division by 2, mod q
if (V.testBit(0))
@@ -168,7 +273,7 @@ public abstract class ECFieldElement
//assert V.multiply(V).mod(q).equals(x);
- return new ECFieldElement.Fp(q, V);
+ return new ECFieldElement.Fp(q, r, V);
}
}
while (U.equals(ECConstants.ONE) || U.equals(qMinusOne));
@@ -230,8 +335,7 @@ public abstract class ECFieldElement
// return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p);
// }
- private static BigInteger[] lucasSequence(
- BigInteger p,
+ private BigInteger[] lucasSequence(
BigInteger P,
BigInteger Q,
BigInteger k)
@@ -247,40 +351,122 @@ public abstract class ECFieldElement
for (int j = n - 1; j >= s + 1; --j)
{
- Ql = Ql.multiply(Qh).mod(p);
+ Ql = modMult(Ql, Qh);
if (k.testBit(j))
{
- Qh = Ql.multiply(Q).mod(p);
- Uh = Uh.multiply(Vh).mod(p);
- Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
- Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p);
+ Qh = modMult(Ql, Q);
+ Uh = modMult(Uh, Vh);
+ Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql)));
+ Vh = modReduce(Vh.multiply(Vh).subtract(Qh.shiftLeft(1)));
}
else
{
Qh = Ql;
- Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
- Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
- Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
+ Uh = modReduce(Uh.multiply(Vl).subtract(Ql));
+ Vh = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql)));
+ Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1)));
}
}
- Ql = Ql.multiply(Qh).mod(p);
- Qh = Ql.multiply(Q).mod(p);
- Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
- Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
- Ql = Ql.multiply(Qh).mod(p);
+ Ql = modMult(Ql, Qh);
+ Qh = modMult(Ql, Q);
+ Uh = modReduce(Uh.multiply(Vl).subtract(Ql));
+ Vl = modReduce(Vh.multiply(Vl).subtract(P.multiply(Ql)));
+ Ql = modMult(Ql, Qh);
for (int j = 1; j <= s; ++j)
{
- Uh = Uh.multiply(Vl).mod(p);
- Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
- Ql = Ql.multiply(Ql).mod(p);
+ Uh = modMult(Uh, Vl);
+ Vl = modReduce(Vl.multiply(Vl).subtract(Ql.shiftLeft(1)));
+ Ql = modMult(Ql, Ql);
}
return new BigInteger[]{ Uh, Vl };
}
-
+
+ protected BigInteger modAdd(BigInteger x1, BigInteger x2)
+ {
+ BigInteger x3 = x1.add(x2);
+ if (x3.compareTo(q) >= 0)
+ {
+ x3 = x3.subtract(q);
+ }
+ return x3;
+ }
+
+ protected BigInteger modDouble(BigInteger x)
+ {
+ BigInteger _2x = x.shiftLeft(1);
+ if (_2x.compareTo(q) >= 0)
+ {
+ _2x = _2x.subtract(q);
+ }
+ return _2x;
+ }
+
+ protected BigInteger modMult(BigInteger x1, BigInteger x2)
+ {
+ return modReduce(x1.multiply(x2));
+ }
+
+ protected BigInteger modReduce(BigInteger x)
+ {
+// if (naf != null)
+// {
+// int last = naf.length - 1;
+// int bits = naf[last];
+// while (x.bitLength() > (bits + 1))
+// {
+// BigInteger u = x.shiftRight(bits);
+// BigInteger v = x.subtract(u.shiftLeft(bits));
+//
+// x = v;
+//
+// for (int i = 0; i < last; ++i)
+// {
+// int ni = naf[i];
+// if (ni < 0)
+// {
+// x = x.add(u.shiftLeft(~ni));
+// }
+// else
+// {
+// x = x.subtract(u.shiftLeft(ni));
+// }
+// }
+// }
+// while (x.compareTo(q) >= 0)
+// {
+// x = x.subtract(q);
+// }
+// }
+// else
+ if (r != null)
+ {
+ int qLen = q.bitLength();
+ while (x.bitLength() > (qLen + 1))
+ {
+ BigInteger u = x.shiftRight(qLen);
+ BigInteger v = x.subtract(u.shiftLeft(qLen));
+ if (!r.equals(ONE))
+ {
+ u = u.multiply(r);
+ }
+ x = u.add(v);
+ }
+ while (x.compareTo(q) >= 0)
+ {
+ x = x.subtract(q);
+ }
+ }
+ else
+ {
+ x = x.mod(q);
+ }
+ return x;
+ }
+
public boolean equals(Object other)
{
if (other == this)
@@ -669,7 +855,7 @@ public abstract class ECFieldElement
// g1z = g1z.xor(g2z.shiftLeft(j));
//// if (g1z.bitLength() > this.m) {
//// throw new ArithmeticException(
-//// "deg(g1z) >= m, g1z = " + g1z.toString(2));
+//// "deg(g1z) >= m, g1z = " + g1z.toString(16));
//// }
// }
// return new ECFieldElement.F2m(
@@ -801,41 +987,38 @@ public abstract class ECFieldElement
*/
private int m;
- /**
- * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
- * x<sup>k</sup> + 1</code> represents the reduction polynomial
- * <code>f(z)</code>.<br>
- * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- private int k1;
-
- /**
- * TPB: Always set to <code>0</code><br>
- * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- private int k2;
-
- /**
- * TPB: Always set to <code>0</code><br>
- * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
- * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
- * represents the reduction polynomial <code>f(z)</code>.<br>
- */
- private int k3;
+// /**
+// * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
+// * x<sup>k</sup> + 1</code> represents the reduction polynomial
+// * <code>f(z)</code>.<br>
+// * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
+// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+// * represents the reduction polynomial <code>f(z)</code>.<br>
+// */
+// private int k1;
+//
+// /**
+// * TPB: Always set to <code>0</code><br>
+// * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
+// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+// * represents the reduction polynomial <code>f(z)</code>.<br>
+// */
+// private int k2;
+//
+// /**
+// * TPB: Always set to <code>0</code><br>
+// * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
+// * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+// * represents the reduction polynomial <code>f(z)</code>.<br>
+// */
+// private int k3;
- /**
- * The <code>IntArray</code> holding the bits.
- */
- private IntArray x;
+ private int[] ks;
/**
- * The number of <code>int</code>s required to hold <code>m</code> bits.
+ * The <code>LongArray</code> holding the bits.
*/
- private int t;
+ private LongArray x;
/**
* Constructor for PPB.
@@ -851,6 +1034,7 @@ public abstract class ECFieldElement
* x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
* represents the reduction polynomial <code>f(z)</code>.
* @param x The BigInteger representing the value of the field element.
+ * @deprecated Use ECCurve.fromBigInteger to construct field elements
*/
public F2m(
int m,
@@ -859,13 +1043,10 @@ public abstract class ECFieldElement
int k3,
BigInteger x)
{
- // t = m / 32 rounded up to the next integer
- t = (m + 31) >> 5;
- this.x = new IntArray(x, t);
-
if ((k2 == 0) && (k3 == 0))
{
this.representation = TPB;
+ this.ks = new int[]{ k1 };
}
else
{
@@ -880,17 +1061,11 @@ public abstract class ECFieldElement
"k2 must be larger than 0");
}
this.representation = PPB;
- }
-
- if (x.signum() < 0)
- {
- throw new IllegalArgumentException("x value cannot be negative");
+ this.ks = new int[]{ k1, k2, k3 };
}
this.m = m;
- this.k1 = k1;
- this.k2 = k2;
- this.k3 = k3;
+ this.x = new LongArray(x);
}
/**
@@ -901,6 +1076,7 @@ public abstract class ECFieldElement
* 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)
{
@@ -908,24 +1084,27 @@ public abstract class ECFieldElement
this(m, k, 0, 0, x);
}
- private F2m(int m, int k1, int k2, int k3, IntArray x)
+ private F2m(int m, int[] ks, LongArray x)
{
- t = (m + 31) >> 5;
- this.x = x;
this.m = m;
- this.k1 = k1;
- this.k2 = k2;
- this.k3 = k3;
+ this.representation = (ks.length == 1) ? TPB : PPB;
+ this.ks = ks;
+ this.x = x;
+ }
- if ((k2 == 0) && (k3 == 0))
- {
- this.representation = TPB;
- }
- else
- {
- this.representation = PPB;
- }
+ public int bitLength()
+ {
+ return x.degree();
+ }
+
+ public boolean isZero()
+ {
+ return x.isZero();
+ }
+ public boolean testBitZero()
+ {
+ return x.testBitZero();
}
public BigInteger toBigInteger()
@@ -967,19 +1146,15 @@ public abstract class ECFieldElement
ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
- if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1)
- || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3))
+ if (aF2m.representation != bF2m.representation)
{
- throw new IllegalArgumentException("Field elements are not "
- + "elements of the same field F2m");
+ // Should never occur
+ throw new IllegalArgumentException("One of the F2m field elements has incorrect representation");
}
- if (aF2m.representation != bF2m.representation)
+ if ((aF2m.m != bF2m.m) || !Arrays.areEqual(aF2m.ks, bF2m.ks))
{
- // Should never occur
- throw new IllegalArgumentException(
- "One of the field "
- + "elements are not elements has incorrect representation");
+ throw new IllegalArgumentException("Field elements are not elements of the same field F2m");
}
}
@@ -988,10 +1163,15 @@ public abstract class ECFieldElement
// No check performed here for performance reasons. Instead the
// elements involved are checked in ECPoint.F2m
// checkFieldElements(this, b);
- IntArray iarrClone = (IntArray)this.x.clone();
+ LongArray iarrClone = (LongArray)this.x.clone();
F2m bF2m = (F2m)b;
- iarrClone.addShifted(bF2m.x, 0);
- return new F2m(m, k1, k2, k3, iarrClone);
+ iarrClone.addShiftedByWords(bF2m.x, 0);
+ return new F2m(m, ks, iarrClone);
+ }
+
+ public ECFieldElement addOne()
+ {
+ return new F2m(m, ks, x.addOne());
}
public ECFieldElement subtract(final ECFieldElement b)
@@ -1002,17 +1182,14 @@ public abstract class ECFieldElement
public ECFieldElement multiply(final ECFieldElement b)
{
- // Right-to-left comb multiplication in the IntArray
+ // Right-to-left comb multiplication in the LongArray
// Input: Binary polynomials a(z) and b(z) of degree at most m-1
// Output: c(z) = a(z) * b(z) mod f(z)
// No check performed here for performance reasons. Instead the
// elements involved are checked in ECPoint.F2m
// checkFieldElements(this, b);
- F2m bF2m = (F2m)b;
- IntArray mult = x.multiply(bF2m.x, m);
- mult.reduce(m, new int[]{k1, k2, k3});
- return new F2m(m, k1, k2, k3, mult);
+ return new F2m(m, ks, x.modMultiply(((F2m)b).x, m, ks));
}
public ECFieldElement divide(final ECFieldElement b)
@@ -1030,80 +1207,12 @@ public abstract class ECFieldElement
public ECFieldElement square()
{
- IntArray squared = x.square(m);
- squared.reduce(m, new int[]{k1, k2, k3});
- return new F2m(m, k1, k2, k3, squared);
+ return new F2m(m, ks, x.modSquare(m, ks));
}
-
public ECFieldElement invert()
{
- // Inversion in F2m using the extended Euclidean algorithm
- // Input: A nonzero polynomial a(z) of degree at most m-1
- // Output: a(z)^(-1) mod f(z)
-
- // u(z) := a(z)
- IntArray uz = (IntArray)this.x.clone();
-
- // v(z) := f(z)
- IntArray vz = new IntArray(t);
- vz.setBit(m);
- vz.setBit(0);
- vz.setBit(this.k1);
- if (this.representation == PPB)
- {
- vz.setBit(this.k2);
- vz.setBit(this.k3);
- }
-
- // g1(z) := 1, g2(z) := 0
- IntArray g1z = new IntArray(t);
- g1z.setBit(0);
- IntArray g2z = new IntArray(t);
-
- // while u != 0
- while (!uz.isZero())
-// while (uz.getUsedLength() > 0)
-// while (uz.bitLength() > 1)
- {
- // j := deg(u(z)) - deg(v(z))
- int j = uz.bitLength() - vz.bitLength();
-
- // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j
- if (j < 0)
- {
- final IntArray uzCopy = uz;
- uz = vz;
- vz = uzCopy;
-
- final IntArray g1zCopy = g1z;
- g1z = g2z;
- g2z = g1zCopy;
-
- j = -j;
- }
-
- // u(z) := u(z) + z^j * v(z)
- // Note, that no reduction modulo f(z) is required, because
- // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z)))
- // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z))
- // = deg(u(z))
- // uz = uz.xor(vz.shiftLeft(j));
- // jInt = n / 32
- int jInt = j >> 5;
- // jInt = n % 32
- int jBit = j & 0x1F;
- IntArray vzShift = vz.shiftLeft(jBit);
- uz.addShifted(vzShift, jInt);
-
- // g1(z) := g1(z) + z^j * g2(z)
-// g1z = g1z.xor(g2z.shiftLeft(j));
- IntArray g2zShift = g2z.shiftLeft(jBit);
- g1z.addShifted(g2zShift, jInt);
-
- }
- return new ECFieldElement.F2m(
- this.m, this.k1, this.k2, this.k3, g2z);
+ return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks));
}
public ECFieldElement sqrt()
@@ -1143,7 +1252,7 @@ public abstract class ECFieldElement
*/
public int getK1()
{
- return this.k1;
+ return this.ks[0];
}
/**
@@ -1154,7 +1263,7 @@ public abstract class ECFieldElement
*/
public int getK2()
{
- return this.k2;
+ return this.ks.length >= 2 ? this.ks[1] : 0;
}
/**
@@ -1165,7 +1274,7 @@ public abstract class ECFieldElement
*/
public int getK3()
{
- return this.k3;
+ return this.ks.length >= 3 ? this.ks[2] : 0;
}
public boolean equals(Object anObject)
@@ -1182,15 +1291,15 @@ public abstract class ECFieldElement
ECFieldElement.F2m b = (ECFieldElement.F2m)anObject;
- return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2)
- && (this.k3 == b.k3)
+ return ((this.m == b.m)
&& (this.representation == b.representation)
+ && Arrays.areEqual(this.ks, b.ks)
&& (this.x.equals(b.x)));
}
public int hashCode()
{
- return x.hashCode() ^ m ^ k1 ^ k2 ^ k3;
+ return x.hashCode() ^ m ^ Arrays.hashCode(ks);
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java
index 4d72e33..da1013a 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECMultiplier.java
@@ -6,14 +6,14 @@ import java.math.BigInteger;
* Interface for classes encapsulating a point multiplication algorithm
* for <code>ECPoint</code>s.
*/
-interface ECMultiplier
+public interface ECMultiplier
{
/**
* Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e.
* <code>p</code> is added <code>k</code> times to itself.
* @param p The <code>ECPoint</code> to be multiplied.
- * @param k The factor by which <code>p</code> i multiplied.
+ * @param k The factor by which <code>p</code> is multiplied.
* @return <code>p</code> multiplied by <code>k</code>.
*/
- ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo);
+ ECPoint multiply(ECPoint p, BigInteger k);
}
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 cbc5aaf..7f740e4 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
@@ -2,59 +2,324 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
-import org.bouncycastle.asn1.x9.X9IntegerConverter;
-
/**
* base class for points on elliptic curves.
*/
public abstract class ECPoint
{
- ECCurve curve;
- ECFieldElement x;
- ECFieldElement y;
+ protected static ECFieldElement[] EMPTY_ZS = new ECFieldElement[0];
- protected boolean withCompression;
+ protected static ECFieldElement[] getInitialZCoords(ECCurve curve)
+ {
+ // Cope with null curve, most commonly used by implicitlyCa
+ int coord = null == curve ? ECCurve.COORD_AFFINE : curve.getCoordinateSystem();
- protected ECMultiplier multiplier = null;
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ return EMPTY_ZS;
+ default:
+ break;
+ }
- protected PreCompInfo preCompInfo = null;
+ ECFieldElement one = curve.fromBigInteger(ECConstants.ONE);
- private static X9IntegerConverter converter = new X9IntegerConverter();
+ switch (coord)
+ {
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ return new ECFieldElement[]{ one };
+ case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+ return new ECFieldElement[]{ one, one, one };
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ return new ECFieldElement[]{ one, curve.getA() };
+ default:
+ throw new IllegalArgumentException("unknown coordinate system");
+ }
+ }
+
+ protected ECCurve curve;
+ protected ECFieldElement x;
+ protected ECFieldElement y;
+ protected ECFieldElement[] zs;
+
+ protected boolean withCompression;
+
+ protected PreCompInfo preCompInfo = null;
protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
{
+ this(curve, x, y, getInitialZCoords(curve));
+ }
+
+ protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs)
+ {
this.curve = curve;
this.x = x;
this.y = y;
+ this.zs = zs;
}
-
+
public ECCurve getCurve()
{
return curve;
}
-
+
+ protected int getCurveCoordinateSystem()
+ {
+ // Cope with null curve, most commonly used by implicitlyCa
+ return null == curve ? ECCurve.COORD_AFFINE : curve.getCoordinateSystem();
+ }
+
+ /**
+ * 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 x;
+ 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
+ * @throws IllegalStateException if the point is not normalized
+ */
+ public ECFieldElement getAffineXCoord()
+ {
+ checkNormalized();
+ return getXCoord();
+ }
+
+ /**
+ * Returns the affine y-coordinate after checking that this point is normalized
+ *
+ * @return The affine y-coordinate of this point
+ * @throws IllegalStateException if the point is not normalized
+ */
+ public ECFieldElement getAffineYCoord()
+ {
+ checkNormalized();
+ return getYCoord();
+ }
+
+ /**
+ * Returns the x-coordinate.
+ *
+ * Caution: depending on the curve's coordinate system, this may not be the same value as in an
+ * affine coordinate system; use normalize() to get a point where the coordinates have their
+ * affine values, or use getAffineXCoord if you expect the point to already have been
+ * normalized.
+ *
+ * @return the x-coordinate of this point
+ */
+ public ECFieldElement getXCoord()
+ {
+ return x;
+ }
+
+ /**
+ * Returns the y-coordinate.
+ *
+ * Caution: depending on the curve's coordinate system, this may not be the same value as in an
+ * affine coordinate system; use normalize() to get a point where the coordinates have their
+ * affine values, or use getAffineYCoord if you expect the point to already have been
+ * normalized.
+ *
+ * @return the y-coordinate of this point
+ */
+ public ECFieldElement getYCoord()
+ {
return y;
}
+ public ECFieldElement getZCoord(int index)
+ {
+ return (index < 0 || index >= zs.length) ? null : zs[index];
+ }
+
+ public ECFieldElement[] getZCoords()
+ {
+ int zsLen = zs.length;
+ if (zsLen == 0)
+ {
+ return zs;
+ }
+ ECFieldElement[] copy = new ECFieldElement[zsLen];
+ System.arraycopy(zs, 0, copy, 0, zsLen);
+ return copy;
+ }
+
+ protected ECFieldElement getRawXCoord()
+ {
+ return x;
+ }
+
+ protected ECFieldElement getRawYCoord()
+ {
+ return y;
+ }
+
+ protected void checkNormalized()
+ {
+ if (!isNormalized())
+ {
+ throw new IllegalStateException("point not in normal form");
+ }
+ }
+
+ public boolean isNormalized()
+ {
+ int coord = this.getCurveCoordinateSystem();
+
+ return coord == ECCurve.COORD_AFFINE
+ || coord == ECCurve.COORD_LAMBDA_AFFINE
+ || isInfinity()
+ || zs[0].bitLength() == 1;
+ }
+
+ /**
+ * Normalization ensures that any projective coordinate is 1, and therefore that the x, y
+ * coordinates reflect those of the equivalent point in an affine coordinate system.
+ *
+ * @return a new ECPoint instance representing the same point, but with normalized coordinates
+ */
+ public ECPoint normalize()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ return this;
+ }
+ default:
+ {
+ ECFieldElement Z1 = getZCoord(0);
+ if (Z1.bitLength() == 1)
+ {
+ return this;
+ }
+
+ return normalize(Z1.invert());
+ }
+ }
+ }
+
+ ECPoint normalize(ECFieldElement zInv)
+ {
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ return createScaledPoint(zInv, zInv);
+ }
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ ECFieldElement zInv2 = zInv.square(), zInv3 = zInv2.multiply(zInv);
+ return createScaledPoint(zInv2, zInv3);
+ }
+ default:
+ {
+ throw new IllegalStateException("not a projective coordinate system");
+ }
+ }
+ }
+
+ protected ECPoint createScaledPoint(ECFieldElement sx, ECFieldElement sy)
+ {
+ return this.getCurve().createRawPoint(getRawXCoord().multiply(sx), getRawYCoord().multiply(sy), this.withCompression);
+ }
+
public boolean isInfinity()
{
- return x == null && y == null;
+ return x == null || y == null || (zs.length > 0 && zs[0].isZero());
}
public boolean isCompressed()
{
- return withCompression;
+ return this.withCompression;
+ }
+
+ public boolean equals(ECPoint other)
+ {
+ if (null == other)
+ {
+ return false;
+ }
+
+ ECCurve c1 = this.getCurve(), c2 = other.getCurve();
+ boolean n1 = (null == c1), n2 = (null == c2);
+ boolean i1 = isInfinity(), i2 = other.isInfinity();
+
+ if (i1 || i2)
+ {
+ return (i1 && i2) && (n1 || n2 || c1.equals(c2));
+ }
+
+ ECPoint p1 = this, p2 = other;
+ if (n1 && n2)
+ {
+ // Points with null curve are in affine form, so already normalized
+ }
+ else if (n1)
+ {
+ p2 = p2.normalize();
+ }
+ else if (n2)
+ {
+ p1 = p1.normalize();
+ }
+ else if (!c1.equals(c2))
+ {
+ return false;
+ }
+ else
+ {
+ // TODO Consider just requiring already normalized, to avoid silent performance degradation
+
+ ECPoint[] points = new ECPoint[]{ this, c1.importPoint(p2) };
+
+ // TODO This is a little strong, really only requires coZNormalizeAll to get Zs equal
+ c1.normalizeAll(points);
+
+ p1 = points[0];
+ p2 = points[1];
+ }
+
+ return p1.getXCoord().equals(p2.getXCoord()) && p1.getYCoord().equals(p2.getYCoord());
}
- public boolean equals(
- Object other)
+ public boolean equals(Object other)
{
if (other == this)
{
@@ -66,69 +331,117 @@ public abstract class ECPoint
return false;
}
- ECPoint o = (ECPoint)other;
+ return equals((ECPoint)other);
+ }
- if (this.isInfinity())
+ public int hashCode()
+ {
+ ECCurve c = this.getCurve();
+ int hc = (null == c) ? 0 : ~c.hashCode();
+
+ if (!this.isInfinity())
{
- return o.isInfinity();
+ // TODO Consider just requiring already normalized, to avoid silent performance degradation
+
+ ECPoint p = normalize();
+
+ hc ^= p.getXCoord().hashCode() * 17;
+ hc ^= p.getYCoord().hashCode() * 257;
}
- return x.equals(o.x) && y.equals(o.y);
+ return hc;
}
- public int hashCode()
+ public String toString()
{
if (this.isInfinity())
{
- return 0;
+ return "INF";
}
-
- return x.hashCode() ^ y.hashCode();
+
+ StringBuffer sb = new StringBuffer();
+ sb.append('(');
+ sb.append(getRawXCoord());
+ sb.append(',');
+ sb.append(getRawYCoord());
+ for (int i = 0; i < zs.length; ++i)
+ {
+ sb.append(',');
+ sb.append(zs[i]);
+ }
+ sb.append(')');
+ return sb.toString();
}
-// /**
-// * Mainly for testing. Explicitly set the <code>ECMultiplier</code>.
-// * @param multiplier The <code>ECMultiplier</code> to be used to multiply
-// * this <code>ECPoint</code>.
-// */
-// public void setECMultiplier(ECMultiplier multiplier)
-// {
-// this.multiplier = multiplier;
-// }
+ public byte[] getEncoded()
+ {
+ return getEncoded(this.withCompression);
+ }
/**
- * Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s
- * to save the precomputation for this <code>ECPoint</code> to store the
- * precomputation result for use by subsequent multiplication.
- * @param preCompInfo The values precomputed by the
- * <code>ECMultiplier</code>.
+ * return the field element encoded with point compression. (S 4.3.6)
*/
- void setPreCompInfo(PreCompInfo preCompInfo)
+ public byte[] getEncoded(boolean compressed)
{
- this.preCompInfo = preCompInfo;
- }
+ if (this.isInfinity())
+ {
+ return new byte[1];
+ }
- public byte[] getEncoded()
- {
- return getEncoded(withCompression);
+ ECPoint normed = normalize();
+
+ byte[] X = normed.getXCoord().getEncoded();
+
+ if (compressed)
+ {
+ byte[] PO = new byte[X.length + 1];
+ PO[0] = (byte)(normed.getCompressionYTilde() ? 0x03 : 0x02);
+ System.arraycopy(X, 0, PO, 1, X.length);
+ return PO;
+ }
+
+ byte[] Y = normed.getYCoord().getEncoded();
+
+ byte[] PO = new byte[X.length + Y.length + 1];
+ PO[0] = 0x04;
+ System.arraycopy(X, 0, PO, 1, X.length);
+ System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
+ return PO;
}
- public abstract byte[] getEncoded(boolean compressed);
+ protected abstract boolean getCompressionYTilde();
public abstract ECPoint add(ECPoint b);
- public abstract ECPoint subtract(ECPoint b);
+
public abstract ECPoint negate();
- public abstract ECPoint twice();
- /**
- * Sets the default <code>ECMultiplier</code>, unless already set.
- */
- synchronized void assertECMultiplier()
+ public abstract ECPoint subtract(ECPoint b);
+
+ public ECPoint timesPow2(int e)
{
- if (this.multiplier == null)
+ if (e < 0)
+ {
+ throw new IllegalArgumentException("'e' cannot be negative");
+ }
+
+ ECPoint p = this;
+ while (--e >= 0)
{
- this.multiplier = new FpNafMultiplier();
+ p = p.twice();
}
+ return p;
+ }
+
+ public abstract ECPoint twice();
+
+ public ECPoint twicePlus(ECPoint b)
+ {
+ return twice().add(b);
+ }
+
+ public ECPoint threeTimes()
+ {
+ return twicePlus(this);
}
/**
@@ -138,23 +451,7 @@ public abstract class ECPoint
*/
public ECPoint multiply(BigInteger k)
{
- if (k.signum() < 0)
- {
- throw new IllegalArgumentException("The multiplicator cannot be negative");
- }
-
- if (this.isInfinity())
- {
- return this;
- }
-
- if (k.signum() == 0)
- {
- return this.curve.getInfinity();
- }
-
- assertECMultiplier();
- return this.multiplier.multiply(this, k, preCompInfo);
+ return this.getCurve().getMultiplier().multiply(this, k);
}
/**
@@ -162,13 +459,14 @@ public abstract class ECPoint
*/
public static class Fp extends ECPoint
{
-
/**
* Create a point which encodes with point compression.
*
* @param curve the curve to use
* @param x affine x co-ordinate
* @param y affine y co-ordinate
+ *
+ * @deprecated Use ECCurve.createPoint to construct points
*/
public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
{
@@ -182,6 +480,8 @@ public abstract class ECPoint
* @param x affine x co-ordinate
* @param y affine y co-ordinate
* @param withCompression if true encode with point compression
+ *
+ * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
*/
public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
{
@@ -194,112 +494,537 @@ public abstract class ECPoint
this.withCompression = withCompression;
}
-
- /**
- * return the field element encoded with point compression. (S 4.3.6)
- */
- public byte[] getEncoded(boolean compressed)
+
+ Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
{
- if (this.isInfinity())
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+ }
+
+ protected boolean getCompressionYTilde()
+ {
+ return this.getAffineYCoord().testBitZero();
+ }
+
+ public ECFieldElement getZCoord(int index)
+ {
+ if (index == 1 && ECCurve.COORD_JACOBIAN_MODIFIED == this.getCurveCoordinateSystem())
{
- return new byte[1];
+ return getJacobianModifiedW();
}
- int qLength = converter.getByteLength(x);
-
- if (compressed)
+ return super.getZCoord(index);
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
{
- byte PC;
-
- if (this.getY().toBigInteger().testBit(0))
+ return b;
+ }
+ if (b.isInfinity())
+ {
+ return this;
+ }
+ if (this == b)
+ {
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement X1 = this.x, Y1 = this.y;
+ ECFieldElement X2 = b.x, Y2 = b.y;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement dx = X2.subtract(X1), dy = Y2.subtract(Y1);
+
+ if (dx.isZero())
{
- PC = 0x03;
+ if (dy.isZero())
+ {
+ // this == b, i.e. this must be doubled
+ return twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
}
- else
+
+ ECFieldElement gamma = dy.divide(dx);
+ ECFieldElement X3 = gamma.square().subtract(X1).subtract(X2);
+ ECFieldElement Y3 = gamma.multiply(X1.subtract(X3)).subtract(Y1);
+
+ return new ECPoint.Fp(curve, X3, Y3, this.withCompression);
+ }
+
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Z1 = this.zs[0];
+ ECFieldElement Z2 = b.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ boolean Z2IsOne = Z2.bitLength() == 1;
+
+ ECFieldElement u1 = Z1IsOne ? Y2 : Y2.multiply(Z1);
+ ECFieldElement u2 = Z2IsOne ? Y1 : Y1.multiply(Z2);
+ ECFieldElement u = u1.subtract(u2);
+ ECFieldElement v1 = Z1IsOne ? X2 : X2.multiply(Z1);
+ ECFieldElement v2 = Z2IsOne ? X1 : X1.multiply(Z2);
+ ECFieldElement v = v1.subtract(v2);
+
+ // Check if b == this or b == -this
+ if (v.isZero())
{
- PC = 0x02;
+ if (u.isZero())
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
}
+
+ // TODO Optimize for when w == 1
+ ECFieldElement w = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.multiply(Z2);
+ ECFieldElement vSquared = v.square();
+ ECFieldElement vCubed = vSquared.multiply(v);
+ ECFieldElement vSquaredV2 = vSquared.multiply(v2);
+ ECFieldElement A = u.square().multiply(w).subtract(vCubed).subtract(two(vSquaredV2));
+
+ ECFieldElement X3 = v.multiply(A);
+ ECFieldElement Y3 = vSquaredV2.subtract(A).multiply(u).subtract(vCubed.multiply(u2));
+ ECFieldElement Z3 = vCubed.multiply(w);
+
+ return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ case ECCurve.COORD_JACOBIAN:
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ ECFieldElement Z1 = this.zs[0];
+ ECFieldElement Z2 = b.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+
+ ECFieldElement X3, Y3, Z3, Z3Squared = null;
+
+ if (!Z1IsOne && Z1.equals(Z2))
+ {
+ // TODO Make this available as public method coZAdd?
+
+ ECFieldElement dx = X1.subtract(X2), dy = Y1.subtract(Y2);
+ if (dx.isZero())
+ {
+ if (dy.isZero())
+ {
+ return twice();
+ }
+ return curve.getInfinity();
+ }
+
+ ECFieldElement C = dx.square();
+ ECFieldElement W1 = X1.multiply(C), W2 = X2.multiply(C);
+ ECFieldElement A1 = W1.subtract(W2).multiply(Y1);
+
+ X3 = dy.square().subtract(W1).subtract(W2);
+ Y3 = W1.subtract(X3).multiply(dy).subtract(A1);
+ Z3 = dx;
+
+ if (Z1IsOne)
+ {
+ Z3Squared = C;
+ }
+ else
+ {
+ Z3 = Z3.multiply(Z1);
+ }
+ }
+ else
+ {
+ ECFieldElement Z1Squared, U2, S2;
+ if (Z1IsOne)
+ {
+ Z1Squared = Z1; U2 = X2; S2 = Y2;
+ }
+ else
+ {
+ Z1Squared = Z1.square();
+ U2 = Z1Squared.multiply(X2);
+ ECFieldElement Z1Cubed = Z1Squared.multiply(Z1);
+ S2 = Z1Cubed.multiply(Y2);
+ }
+
+ boolean Z2IsOne = Z2.bitLength() == 1;
+ ECFieldElement Z2Squared, U1, S1;
+ if (Z2IsOne)
+ {
+ Z2Squared = Z2; U1 = X1; S1 = Y1;
+ }
+ else
+ {
+ Z2Squared = Z2.square();
+ U1 = Z2Squared.multiply(X1);
+ ECFieldElement Z2Cubed = Z2Squared.multiply(Z2);
+ S1 = Z2Cubed.multiply(Y1);
+ }
+
+ ECFieldElement H = U1.subtract(U2);
+ ECFieldElement R = S1.subtract(S2);
+
+ // Check if b == this or b == -this
+ if (H.isZero())
+ {
+ if (R.isZero())
+ {
+ // this == b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this == -b, i.e. the result is the point at infinity
+ return curve.getInfinity();
+ }
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
- byte[] PO = new byte[X.length + 1];
+ ECFieldElement HSquared = H.square();
+ ECFieldElement G = HSquared.multiply(H);
+ ECFieldElement V = HSquared.multiply(U1);
- PO[0] = PC;
- System.arraycopy(X, 0, PO, 1, X.length);
+ X3 = R.square().add(G).subtract(two(V));
+ Y3 = V.subtract(X3).multiply(R).subtract(S1.multiply(G));
- return PO;
+ Z3 = H;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.multiply(Z1);
+ }
+ if (!Z2IsOne)
+ {
+ Z3 = Z3.multiply(Z2);
+ }
+
+ // Alternative calculation of Z3 using fast square
+ // X3 = four(X3);
+ // Y3 = eight(Y3);
+ // Z3 = doubleProductFromSquares(Z1, Z2, Z1Squared, Z2Squared).multiply(H);
+
+ if (Z3 == H)
+ {
+ Z3Squared = HSquared;
+ }
+ }
+
+ ECFieldElement[] zs;
+ if (coord == ECCurve.COORD_JACOBIAN_MODIFIED)
+ {
+ // TODO If the result will only be used in a subsequent addition, we don't need W3
+ ECFieldElement W3 = calculateJacobianModifiedW(Z3, Z3Squared);
+
+ zs = new ECFieldElement[]{ Z3, W3 };
+ }
+ else
+ {
+ zs = new ECFieldElement[]{ Z3 };
+ }
+
+ return new ECPoint.Fp(curve, X3, Y3, zs, this.withCompression);
}
- else
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return curve.getInfinity();
+ }
+
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement X1 = this.x;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement X1Squared = X1.square();
+ ECFieldElement gamma = three(X1Squared).add(this.getCurve().getA()).divide(two(Y1));
+ ECFieldElement X3 = gamma.square().subtract(two(X1));
+ ECFieldElement Y3 = gamma.multiply(X1.subtract(X3)).subtract(Y1);
+
+ return new ECPoint.Fp(curve, X3, Y3, this.withCompression);
+ }
+
+ case ECCurve.COORD_HOMOGENEOUS:
{
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
- byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength);
- byte[] PO = new byte[X.length + Y.length + 1];
+ ECFieldElement Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
+
+ // TODO Optimize for small negative a4 and -3
+ ECFieldElement w = curve.getA();
+ if (!Z1IsOne)
+ {
+ w = w.multiply(Z1Squared);
+ }
+ w = w.add(three(X1.square()));
- PO[0] = 0x04;
- System.arraycopy(X, 0, PO, 1, X.length);
- System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
+ ECFieldElement s = Z1IsOne ? Y1 : Y1.multiply(Z1);
+ ECFieldElement t = Z1IsOne ? Y1.square() : s.multiply(Y1);
+ ECFieldElement B = X1.multiply(t);
+ ECFieldElement _4B = four(B);
+ ECFieldElement h = w.square().subtract(two(_4B));
+
+ ECFieldElement X3 = two(h.multiply(s));
+ ECFieldElement Y3 = w.multiply(_4B.subtract(h)).subtract(two(two(t).square()));
+ ECFieldElement _4sSquared = Z1IsOne ? four(t) : two(s).square();
+ ECFieldElement Z3 = two(_4sSquared).multiply(s);
+
+ return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ case ECCurve.COORD_JACOBIAN:
+ {
+ ECFieldElement Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
+
+ ECFieldElement Y1Squared = Y1.square();
+ ECFieldElement T = Y1Squared.square();
+
+ ECFieldElement a4 = curve.getA();
+ ECFieldElement a4Neg = a4.negate();
+
+ ECFieldElement M, S;
+ if (a4Neg.toBigInteger().equals(BigInteger.valueOf(3)))
+ {
+ M = three(X1.add(Z1Squared).multiply(X1.subtract(Z1Squared)));
+ S = four(Y1Squared.multiply(X1));
+ }
+ else
+ {
+ ECFieldElement X1Squared = X1.square();
+ M = three(X1Squared);
+ if (Z1IsOne)
+ {
+ M = M.add(a4);
+ }
+ else
+ {
+ ECFieldElement Z1Pow4 = Z1Squared.square();
+ if (a4Neg.bitLength() < a4.bitLength())
+ {
+ M = M.subtract(Z1Pow4.multiply(a4Neg));
+ }
+ else
+ {
+ M = M.add(Z1Pow4.multiply(a4));
+ }
+ }
+ S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
+ }
+
+ ECFieldElement X3 = M.square().subtract(two(S));
+ ECFieldElement Y3 = S.subtract(X3).multiply(M).subtract(eight(T));
+
+ ECFieldElement Z3 = two(Y1);
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.multiply(Z1);
+ }
- return PO;
+ // Alternative calculation of Z3 using fast square
+// ECFieldElement Z3 = doubleProductFromSquares(Y1, Z1, Y1Squared, Z1Squared);
+
+ return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ return twiceJacobianModified(true);
+ }
+
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
}
}
- // B.3 pg 62
- public ECPoint add(ECPoint b)
+ public ECPoint twicePlus(ECPoint b)
{
+ if (this == b)
+ {
+ return threeTimes();
+ }
if (this.isInfinity())
{
return b;
}
-
if (b.isInfinity())
{
- return this;
+ return twice();
+ }
+
+ ECFieldElement Y1 = this.y;
+ if (Y1.isZero())
+ {
+ return b;
}
- // Check if b = this or b = -this
- if (this.x.equals(b.x))
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
{
- if (this.y.equals(b.y))
+ ECFieldElement X1 = this.x;
+ ECFieldElement X2 = b.x, Y2 = b.y;
+
+ ECFieldElement dx = X2.subtract(X1), dy = Y2.subtract(Y1);
+
+ if (dx.isZero())
{
- // this = b, i.e. this must be doubled
- return this.twice();
+ if (dy.isZero())
+ {
+ // this == b i.e. the result is 3P
+ return threeTimes();
+ }
+
+ // this == -b, i.e. the result is P
+ return this;
}
- // this = -b, i.e. the result is the point at infinity
- return this.curve.getInfinity();
- }
+ /*
+ * Optimized calculation of 2P + Q, as described in "Trading Inversions for
+ * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery.
+ */
- ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x));
+ ECFieldElement X = dx.square(), Y = dy.square();
+ ECFieldElement d = X.multiply(two(X1).add(X2)).subtract(Y);
+ if (d.isZero())
+ {
+ return curve.getInfinity();
+ }
- ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x);
- ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
+ ECFieldElement D = d.multiply(dx);
+ ECFieldElement I = D.invert();
+ ECFieldElement L1 = d.multiply(I).multiply(dy);
+ ECFieldElement L2 = two(Y1).multiply(X).multiply(dx).multiply(I).subtract(L1);
+ ECFieldElement X4 = (L2.subtract(L1)).multiply(L1.add(L2)).add(X2);
+ ECFieldElement Y4 = (X1.subtract(X4)).multiply(L2).subtract(Y1);
- return new ECPoint.Fp(curve, x3, y3, withCompression);
+ return new ECPoint.Fp(curve, X4, Y4, this.withCompression);
+ }
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ return twiceJacobianModified(false).add(b);
+ }
+ default:
+ {
+ return twice().add(b);
+ }
+ }
}
- // B.3 pg 62
- public ECPoint twice()
+ public ECPoint threeTimes()
{
- if (this.isInfinity())
+ if (this.isInfinity() || this.y.isZero())
{
- // Twice identity element (point at infinity) is identity
return this;
}
- if (this.y.toBigInteger().signum() == 0)
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
{
- // if y1 == 0, then (x1, y1) == (x1, -y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- return this.curve.getInfinity();
+ ECFieldElement X1 = this.x, Y1 = this.y;
+
+ ECFieldElement _2Y1 = two(Y1);
+ ECFieldElement X = _2Y1.square();
+ ECFieldElement Z = three(X1.square()).add(this.getCurve().getA());
+ ECFieldElement Y = Z.square();
+
+ ECFieldElement d = three(X1).multiply(X).subtract(Y);
+ if (d.isZero())
+ {
+ return this.getCurve().getInfinity();
+ }
+
+ ECFieldElement D = d.multiply(_2Y1);
+ ECFieldElement I = D.invert();
+ ECFieldElement L1 = d.multiply(I).multiply(Z);
+ ECFieldElement L2 = X.square().multiply(I).subtract(L1);
+
+ ECFieldElement X4 = (L2.subtract(L1)).multiply(L1.add(L2)).add(X1);
+ ECFieldElement Y4 = (X1.subtract(X4)).multiply(L2).subtract(Y1);
+ return new ECPoint.Fp(curve, X4, Y4, this.withCompression);
+ }
+ case ECCurve.COORD_JACOBIAN_MODIFIED:
+ {
+ return twiceJacobianModified(false).add(this);
+ }
+ default:
+ {
+ // NOTE: Be careful about recursions between twicePlus and threeTimes
+ return twice().add(this);
}
+ }
+ }
- ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
- ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
- ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO));
+ protected ECFieldElement two(ECFieldElement x)
+ {
+ return x.add(x);
+ }
- ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO));
- ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-
- return new ECPoint.Fp(curve, x3, y3, this.withCompression);
+ protected ECFieldElement three(ECFieldElement x)
+ {
+ return two(x).add(x);
+ }
+
+ protected ECFieldElement four(ECFieldElement x)
+ {
+ return two(two(x));
+ }
+
+ protected ECFieldElement eight(ECFieldElement x)
+ {
+ return four(two(x));
+ }
+
+ protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b,
+ ECFieldElement aSquared, ECFieldElement bSquared)
+ {
+ /*
+ * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
+ * way to calculate 2.A.B, if A^2 and B^2 are already known.
+ */
+ return a.add(b).square().subtract(aSquared).subtract(bSquared);
}
// D.3.2 pg 102 (see Note:)
@@ -316,18 +1041,70 @@ public abstract class ECPoint
public ECPoint negate()
{
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ if (ECCurve.COORD_AFFINE != coord)
+ {
+ return new ECPoint.Fp(curve, this.x, this.y.negate(), this.zs, this.withCompression);
+ }
+
return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression);
}
- /**
- * Sets the default <code>ECMultiplier</code>, unless already set.
- */
- synchronized void assertECMultiplier()
+ protected ECFieldElement calculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared)
{
- if (this.multiplier == null)
+ if (ZSquared == null)
+ {
+ ZSquared = Z.square();
+ }
+
+ ECFieldElement W = ZSquared.square();
+ ECFieldElement a4 = this.getCurve().getA();
+ ECFieldElement a4Neg = a4.negate();
+ if (a4Neg.bitLength() < a4.bitLength())
{
- this.multiplier = new WNafMultiplier();
+ W = W.multiply(a4Neg).negate();
}
+ else
+ {
+ W = W.multiply(a4);
+ }
+ return W;
+ }
+
+ protected ECFieldElement getJacobianModifiedW()
+ {
+ ECFieldElement W = this.zs[1];
+ if (W == null)
+ {
+ // NOTE: Rarely, twicePlus will result in the need for a lazy W1 calculation here
+ this.zs[1] = W = calculateJacobianModifiedW(this.zs[0], null);
+ }
+ return W;
+ }
+
+ protected ECPoint.Fp twiceJacobianModified(boolean calculateW)
+ {
+ ECFieldElement X1 = this.x, Y1 = this.y, Z1 = this.zs[0], W1 = getJacobianModifiedW();
+
+ ECFieldElement X1Squared = X1.square();
+ ECFieldElement M = three(X1Squared).add(W1);
+ ECFieldElement Y1Squared = Y1.square();
+ ECFieldElement T = Y1Squared.square();
+ ECFieldElement S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
+ ECFieldElement X3 = M.square().subtract(two(S));
+ ECFieldElement _8T = eight(T);
+ ECFieldElement Y3 = M.multiply(S.subtract(X3)).subtract(_8T);
+ ECFieldElement W3 = calculateW ? two(_8T.multiply(W1)) : null;
+ ECFieldElement Z3 = two(Z1.bitLength() == 1 ? Y1 : Y1.multiply(Z1));
+
+ return new ECPoint.Fp(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression);
}
}
@@ -340,6 +1117,8 @@ 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)
{
@@ -351,6 +1130,8 @@ public abstract class ECPoint
* @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)}
*/
public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
{
@@ -360,71 +1141,91 @@ public abstract class ECPoint
{
throw new IllegalArgumentException("Exactly one of the field elements is null");
}
-
+
if (x != null)
{
// Check if x and y are elements of the same field
ECFieldElement.F2m.checkFieldElements(this.x, this.y);
-
+
// Check if x and a are elements of the same field
if (curve != null)
{
ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA());
}
}
-
+
this.withCompression = withCompression;
+
+// checkCurveEquation();
}
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#getEncoded()
- */
- public byte[] getEncoded(boolean compressed)
+ F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression)
{
- if (this.isInfinity())
- {
- return new byte[1];
- }
+ super(curve, x, y, zs);
+
+ this.withCompression = withCompression;
+
+// checkCurveEquation();
+ }
- int byteCount = converter.getByteLength(this.x);
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount);
- byte[] PO;
+ public ECFieldElement getYCoord()
+ {
+ int coord = this.getCurveCoordinateSystem();
- if (compressed)
+ switch (coord)
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
{
- // See X9.62 4.3.6 and 4.2.2
- PO = new byte[byteCount + 1];
+ // TODO The X == 0 stuff needs further thought
+ if (this.isInfinity() || x.isZero())
+ {
+ return y;
+ }
- PO[0] = 0x02;
- // X9.62 4.2.2 and 4.3.6:
- // if x = 0 then ypTilde := 0, else ypTilde is the rightmost
- // bit of y * x^(-1)
- // if ypTilde = 0, then PC := 02, else PC := 03
- // Note: PC === PO[0]
- if (!(this.getX().toBigInteger().equals(ECConstants.ZERO)))
+ // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+ ECFieldElement X = x, L = y;
+ ECFieldElement Y = L.subtract(X).multiply(X);
+ if (ECCurve.COORD_LAMBDA_PROJECTIVE == coord)
{
- if (this.getY().multiply(this.getX().invert())
- .toBigInteger().testBit(0))
+ ECFieldElement Z = zs[0];
+ if (Z.bitLength() != 1)
{
- // ypTilde = 1, hence PC = 03
- PO[0] = 0x03;
+ Y = Y.divide(Z);
}
}
-
- System.arraycopy(X, 0, PO, 1, byteCount);
+ return Y;
}
- else
+ default:
{
- byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount);
-
- PO = new byte[byteCount + byteCount + 1];
-
- PO[0] = 0x04;
- System.arraycopy(X, 0, PO, 1, byteCount);
- System.arraycopy(Y, 0, PO, byteCount + 1, byteCount);
+ return y;
+ }
+ }
+ }
+
+ protected boolean getCompressionYTilde()
+ {
+ ECFieldElement X = this.getRawXCoord();
+ if (X.isZero())
+ {
+ return false;
}
- return PO;
+ ECFieldElement Y = this.getRawYCoord();
+
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ // Y is actually Lambda (X + Y/X) here
+ return Y.subtract(X).testBitZero();
+ }
+ default:
+ {
+ return Y.divide(X).testBitZero();
+ }
+ }
}
/**
@@ -437,7 +1238,7 @@ public abstract class ECPoint
private static void checkPoints(ECPoint a, ECPoint b)
{
// Check, if points are on the same curve
- if (!(a.curve.equals(b.curve)))
+ if (a.curve != b.curve)
{
throw new IllegalArgumentException("Only points on the same "
+ "curve can be added or subtracted");
@@ -466,43 +1267,162 @@ public abstract class ECPoint
*/
public ECPoint.F2m addSimple(ECPoint.F2m b)
{
- ECPoint.F2m other = b;
if (this.isInfinity())
{
- return other;
+ return b;
}
-
- if (other.isInfinity())
+ if (b.isInfinity())
{
return this;
}
- ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX();
- ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY();
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement X1 = this.x;
+ ECFieldElement X2 = b.x;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement Y1 = this.y;
+ ECFieldElement Y2 = b.y;
+
+ if (X1.equals(X2))
+ {
+ if (Y1.equals(Y2))
+ {
+ return (ECPoint.F2m)twice();
+ }
+
+ return (ECPoint.F2m)curve.getInfinity();
+ }
+
+ ECFieldElement sumX = X1.add(X2);
+ ECFieldElement L = Y1.add(Y2).divide(sumX);
+
+ ECFieldElement X3 = L.square().add(L).add(sumX).add(curve.getA());
+ ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
- // Check if other = this or other = -this
- if (this.x.equals(x2))
+ return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
{
- if (this.y.equals(y2))
+ ECFieldElement Y1 = this.y, Z1 = this.zs[0];
+ ECFieldElement Y2 = b.y, Z2 = b.zs[0];
+
+ boolean Z2IsOne = Z2.bitLength() == 1;
+
+ ECFieldElement U1 = Z1.multiply(Y2);
+ ECFieldElement U2 = Z2IsOne ? Y1 : Y1.multiply(Z2);
+ ECFieldElement U = U1.subtract(U2);
+ ECFieldElement V1 = Z1.multiply(X2);
+ ECFieldElement V2 = Z2IsOne ? X1 : X1.multiply(Z2);
+ ECFieldElement V = V1.subtract(V2);
+
+ if (V1.equals(V2))
{
- // this = other, i.e. this must be doubled
- return (ECPoint.F2m)this.twice();
+ if (U1.equals(U2))
+ {
+ return (ECPoint.F2m)twice();
+ }
+
+ return (ECPoint.F2m)curve.getInfinity();
}
- // this = -other, i.e. the result is the point at infinity
- return (ECPoint.F2m)this.curve.getInfinity();
+ ECFieldElement VSq = V.square();
+ ECFieldElement W = Z2IsOne ? Z1 : Z1.multiply(Z2);
+ ECFieldElement A = U.square().add(U.multiply(V).add(VSq.multiply(curve.getA()))).multiply(W).add(V.multiply(VSq));
+
+ ECFieldElement X3 = V.multiply(A);
+ ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.multiply(Z2);
+ ECFieldElement Y3 = VSqZ2.multiply(U.multiply(X1).add(Y1.multiply(V))).add(A.multiply(U.add(V)));
+ ECFieldElement Z3 = VSq.multiply(V).multiply(W);
+
+ return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
}
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ if (X1.isZero())
+ {
+ return b.addSimple(this);
+ }
- ECFieldElement.F2m lambda
- = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2));
+ ECFieldElement L1 = this.y, Z1 = this.zs[0];
+ ECFieldElement L2 = b.y, Z2 = b.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement U2 = X2, S2 = L2;
+ if (!Z1IsOne)
+ {
+ U2 = U2.multiply(Z1);
+ S2 = S2.multiply(Z1);
+ }
- ECFieldElement.F2m x3
- = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA());
+ boolean Z2IsOne = Z2.bitLength() == 1;
+ ECFieldElement U1 = X1, S1 = L1;
+ if (!Z2IsOne)
+ {
+ U1 = U1.multiply(Z2);
+ S1 = S1.multiply(Z2);
+ }
- ECFieldElement.F2m y3
- = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y);
+ ECFieldElement A = S1.add(S2);
+ ECFieldElement B = U1.add(U2);
- return new ECPoint.F2m(curve, x3, y3, withCompression);
+ if (B.isZero())
+ {
+ if (A.isZero())
+ {
+ return (ECPoint.F2m)twice();
+ }
+
+ return (ECPoint.F2m)curve.getInfinity();
+ }
+
+ ECFieldElement X3, L3, Z3;
+ if (X2.isZero())
+ {
+ // TODO This can probably be optimized quite a bit
+
+ ECFieldElement Y1 = getYCoord(), Y2 = L2;
+ ECFieldElement L = Y1.add(Y2).divide(X1);
+
+ X3 = L.square().add(L).add(X1).add(curve.getA());
+ ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1);
+ L3 = X3.isZero() ? Y3 : Y3.divide(X3).add(X3);
+ Z3 = curve.fromBigInteger(ECConstants.ONE);
+ }
+ else
+ {
+ B = B.square();
+
+ ECFieldElement AU1 = A.multiply(U1);
+ ECFieldElement AU2 = A.multiply(U2);
+ ECFieldElement ABZ2 = A.multiply(B);
+ if (!Z2IsOne)
+ {
+ ABZ2 = ABZ2.multiply(Z2);
+ }
+
+ X3 = AU1.multiply(AU2);
+ L3 = AU2.add(B).square().add(ABZ2.multiply(L1.add(Z1)));
+
+ Z3 = ABZ2;
+ if (!Z1IsOne)
+ {
+ Z3 = Z3.multiply(Z1);
+ }
+ }
+
+ return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
}
/* (non-Javadoc)
@@ -534,59 +1454,279 @@ public abstract class ECPoint
return addSimple((ECPoint.F2m)b.negate());
}
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#twice()
- */
+ public ECPoint.F2m tau()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECCurve curve = this.getCurve();
+ int coord = curve.getCoordinateSystem();
+
+ ECFieldElement X1 = this.x;
+
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ ECFieldElement Y1 = this.y;
+ return new ECPoint.F2m(curve, X1.square(), Y1.square(), this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement Y1 = this.y, Z1 = this.zs[0];
+ return new ECPoint.F2m(curve, X1.square(), Y1.square(), new ECFieldElement[]{ Z1.square() }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
+ }
+
public ECPoint twice()
{
if (this.isInfinity())
{
- // Twice identity element (point at infinity) is identity
return this;
}
- if (this.x.toBigInteger().signum() == 0)
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement X1 = this.x;
+ if (X1.isZero())
{
- // if x1 == 0, then (x1, y1) == (x1, x1 + y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- return this.curve.getInfinity();
+ // A point with X == 0 is it's own additive inverse
+ return curve.getInfinity();
}
- ECFieldElement.F2m lambda
- = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x));
+ int coord = curve.getCoordinateSystem();
- ECFieldElement.F2m x3
- = (ECFieldElement.F2m)lambda.square().add(lambda).
- add(this.curve.getA());
+ switch (coord)
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement Y1 = this.y;
- ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE);
- ECFieldElement.F2m y3
- = (ECFieldElement.F2m)this.x.square().add(
- x3.multiply(lambda.add(ONE)));
+ ECFieldElement L1 = Y1.divide(X1).add(X1);
- return new ECPoint.F2m(this.curve, x3, y3, withCompression);
- }
+ ECFieldElement X3 = L1.square().add(L1).add(curve.getA());
+ ECFieldElement Y3 = X1.square().add(X3.multiply(L1.addOne()));
- public ECPoint negate()
- {
- return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression);
+ return new ECPoint.F2m(curve, X3, Y3, this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Y1 = this.y, Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1);
+ ECFieldElement Y1Z1 = Z1IsOne ? Y1 : Y1.multiply(Z1);
+
+ ECFieldElement X1Sq = X1.square();
+ ECFieldElement S = X1Sq.add(Y1Z1);
+ ECFieldElement V = X1Z1;
+ ECFieldElement vSquared = V.square();
+ ECFieldElement h = S.square().add(S.multiply(V)).add(curve.getA().multiply(vSquared));
+
+ ECFieldElement X3 = V.multiply(h);
+ ECFieldElement Y3 = h.multiply(S.add(V)).add(X1Sq.square().multiply(V));
+ ECFieldElement Z3 = V.multiply(vSquared);
+
+ return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ ECFieldElement L1 = this.y, Z1 = this.zs[0];
+
+ boolean Z1IsOne = Z1.bitLength() == 1;
+ ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.multiply(Z1);
+ ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.square();
+ ECFieldElement a = curve.getA();
+ ECFieldElement aZ1Sq = Z1IsOne ? a : a.multiply(Z1Sq);
+ ECFieldElement T = L1.square().add(L1Z1).add(aZ1Sq);
+
+ ECFieldElement X3 = T.square();
+ ECFieldElement Z3 = Z1IsOne ? T : T.multiply(Z1Sq);
+
+ ECFieldElement b = curve.getB();
+ ECFieldElement L3;
+ if (b.bitLength() < (curve.getFieldSize() >> 1))
+ {
+ ECFieldElement t1 = L1.add(X1).square();
+ ECFieldElement t2 = aZ1Sq.square();
+ ECFieldElement t3 = curve.getB().multiply(Z1Sq.square());
+ L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2.add(t3)).add(X3).add(a.addOne().multiply(Z3));
+ }
+ else
+ {
+ ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1);
+ L3 = X1Z1.square().add(X3).add(T.multiply(L1Z1)).add(Z3);
+ }
+
+ return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
+ }
}
- /**
- * Sets the appropriate <code>ECMultiplier</code>, unless already set.
- */
- synchronized void assertECMultiplier()
+ public ECPoint twicePlus(ECPoint b)
{
- if (this.multiplier == null)
+ if (this.isInfinity())
+ {
+ return b;
+ }
+ if (b.isInfinity())
{
- if (((ECCurve.F2m)this.curve).isKoblitz())
+ return twice();
+ }
+
+ ECCurve curve = this.getCurve();
+
+ ECFieldElement X1 = this.x;
+ if (X1.isZero())
+ {
+ // A point with X == 0 is it's own additive inverse
+ return b;
+ }
+
+ int coord = curve.getCoordinateSystem();
+
+ switch (coord)
+ {
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ // NOTE: twicePlus() only optimized for lambda-affine argument
+ ECFieldElement X2 = b.x, Z2 = b.zs[0];
+ if (X2.isZero() || Z2.bitLength() != 1)
{
- this.multiplier = new WTauNafMultiplier();
+ return twice().add(b);
}
- else
+
+ ECFieldElement L1 = this.y, Z1 = this.zs[0];
+ ECFieldElement L2 = b.y;
+
+ ECFieldElement X1Sq = X1.square();
+ ECFieldElement L1Sq = L1.square();
+ ECFieldElement Z1Sq = Z1.square();
+ ECFieldElement L1Z1 = L1.multiply(Z1);
+
+ ECFieldElement T = curve.getA().multiply(Z1Sq).add(L1Sq).add(L1Z1);
+ ECFieldElement L2plus1 = L2.addOne();
+ ECFieldElement A = curve.getA().add(L2plus1).multiply(Z1Sq).add(L1Sq).multiply(T).add(X1Sq.multiply(Z1Sq));
+ ECFieldElement X2Z1Sq = X2.multiply(Z1Sq);
+ ECFieldElement B = X2Z1Sq.add(T).square();
+
+ ECFieldElement X3 = A.square().multiply(X2Z1Sq);
+ ECFieldElement Z3 = A.multiply(B).multiply(Z1Sq);
+ ECFieldElement L3 = A.add(B).square().multiply(T).add(L2plus1.multiply(Z3));
+
+ return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression);
+ }
+ default:
+ {
+ return twice().add(b);
+ }
+ }
+ }
+
+ protected void checkCurveEquation()
+ {
+ if (this.isInfinity())
+ {
+ return;
+ }
+
+ ECFieldElement Z;
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ Z = curve.fromBigInteger(ECConstants.ONE);
+ break;
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ Z = this.zs[0];
+ break;
+ default:
+ return;
+ }
+
+ if (Z.isZero())
+ {
+ throw new IllegalStateException();
+ }
+
+ ECFieldElement X = this.x;
+ if (X.isZero())
+ {
+ // NOTE: For x == 0, we expect the affine-y instead of the lambda-y
+ ECFieldElement Y = this.y;
+ if (!Y.square().equals(curve.getB().multiply(Z)))
{
- this.multiplier = new WNafMultiplier();
+ throw new IllegalStateException();
}
+
+ return;
+ }
+
+ ECFieldElement L = this.y;
+ ECFieldElement XSq = X.square();
+ ECFieldElement ZSq = Z.square();
+
+ ECFieldElement lhs = L.square().add(L.multiply(Z)).add(this.getCurve().getA().multiply(ZSq)).multiply(XSq);
+ ECFieldElement rhs = ZSq.square().multiply(this.getCurve().getB()).add(XSq.square());
+
+ if (!lhs.equals(rhs))
+ {
+ throw new IllegalStateException("F2m Lambda-Projective invariant broken");
+ }
+ }
+
+ public ECPoint negate()
+ {
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ ECFieldElement X = this.x;
+ if (X.isZero())
+ {
+ return this;
+ }
+
+ switch (this.getCurveCoordinateSystem())
+ {
+ case ECCurve.COORD_AFFINE:
+ {
+ ECFieldElement Y = this.y;
+ return new ECPoint.F2m(curve, X, Y.add(X), this.withCompression);
+ }
+ case ECCurve.COORD_HOMOGENEOUS:
+ {
+ ECFieldElement Y = this.y, Z = this.zs[0];
+ return new ECPoint.F2m(curve, X, Y.add(X), new ECFieldElement[]{ Z }, this.withCompression);
+ }
+ case ECCurve.COORD_LAMBDA_AFFINE:
+ {
+ ECFieldElement L = this.y;
+ return new ECPoint.F2m(curve, X, L.addOne(), this.withCompression);
+ }
+ case ECCurve.COORD_LAMBDA_PROJECTIVE:
+ {
+ // L is actually Lambda (X + Y/X) here
+ ECFieldElement L = this.y, Z = this.zs[0];
+ return new ECPoint.F2m(curve, X, L.add(Z), new ECFieldElement[]{ Z }, this.withCompression);
+ }
+ default:
+ {
+ throw new IllegalStateException("unsupported coordinate system");
+ }
}
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java
deleted file mode 100644
index 35e601d..0000000
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/FpNafMultiplier.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm.
- */
-class FpNafMultiplier implements ECMultiplier
-{
- /**
- * D.3.2 pg 101
- * @see org.bouncycastle.math.ec.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger)
- */
- public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
- {
- // TODO Probably should try to add this
- // BigInteger e = k.mod(n); // n == order of p
- BigInteger e = k;
- BigInteger h = e.multiply(BigInteger.valueOf(3));
-
- ECPoint neg = p.negate();
- ECPoint R = p;
-
- for (int i = h.bitLength() - 2; i > 0; --i)
- {
- R = R.twice();
-
- boolean hBit = h.testBit(i);
- boolean eBit = e.testBit(i);
-
- if (hBit != eBit)
- {
- R = R.add(hBit ? p : neg);
- }
- }
-
- return R;
- }
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java b/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java
index ead38c4..34395a5 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/IntArray.java
@@ -6,6 +6,60 @@ import java.math.BigInteger;
class IntArray
{
+// private static int DEINTERLEAVE_MASK = 0x55555555;
+
+ /*
+ * This expands 8 bit indices into 16 bit contents, by inserting 0s between bits.
+ * In a binary field, this operation is the same as squaring an 8 bit number.
+ */
+ private static final int[] INTERLEAVE_TABLE = new int[] { 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014,
+ 0x0015, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, 0x0100, 0x0101, 0x0104, 0x0105, 0x0110,
+ 0x0111, 0x0114, 0x0115, 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, 0x0400, 0x0401, 0x0404,
+ 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, 0x0500,
+ 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554,
+ 0x0555, 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, 0x1040, 0x1041, 0x1044, 0x1045, 0x1050,
+ 0x1051, 0x1054, 0x1055, 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, 0x1140, 0x1141, 0x1144,
+ 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, 0x1440,
+ 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514,
+ 0x1515, 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, 0x4000, 0x4001, 0x4004, 0x4005, 0x4010,
+ 0x4011, 0x4014, 0x4015, 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, 0x4100, 0x4101, 0x4104,
+ 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, 0x4400,
+ 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454,
+ 0x4455, 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, 0x4540, 0x4541, 0x4544, 0x4545, 0x4550,
+ 0x4551, 0x4554, 0x4555, 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, 0x5040, 0x5041, 0x5044,
+ 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, 0x5140,
+ 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414,
+ 0x5415, 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, 0x5500, 0x5501, 0x5504, 0x5505, 0x5510,
+ 0x5511, 0x5514, 0x5515, 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 };
+
+ // For toString(); must have length 32
+ private static final String ZEROES = "00000000000000000000000000000000";
+
+ private final static byte[] bitLengths =
+ {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
+ };
+
+ public static int getWordLength(int bits)
+ {
+ return (bits + 31) >>> 5;
+ }
+
// TODO make m fixed for the IntArray, and hence compute T once and for all
private int[] m_ints;
@@ -22,16 +76,12 @@ class IntArray
public IntArray(BigInteger bigInt)
{
- this(bigInt, 0);
- }
-
- public IntArray(BigInteger bigInt, int minIntLen)
- {
- if (bigInt.signum() == -1)
+ if (bigInt == null || bigInt.signum() < 0)
{
- throw new IllegalArgumentException("Only positive Integers allowed");
+ throw new IllegalArgumentException("invalid F2m field value");
}
- if (bigInt.equals(ECConstants.ZERO))
+
+ if (bigInt.signum() == 0)
{
m_ints = new int[] { 0 };
return;
@@ -48,14 +98,7 @@ class IntArray
barrStart = 1;
}
int intLen = (barrLen + 3) / 4;
- if (intLen < minIntLen)
- {
- m_ints = new int[minIntLen];
- }
- else
- {
- m_ints = new int[intLen];
- }
+ m_ints = new int[intLen];
int iarrJ = intLen - 1;
int rem = barrLen % 4 + barrStart;
@@ -66,11 +109,7 @@ class IntArray
for (; barrI < rem; barrI++)
{
temp <<= 8;
- int barrBarrI = barr[barrI];
- if (barrBarrI < 0)
- {
- barrBarrI += 256;
- }
+ int barrBarrI = barr[barrI] & 0xFF;
temp |= barrBarrI;
}
m_ints[iarrJ--] = temp;
@@ -82,11 +121,7 @@ class IntArray
for (int i = 0; i < 4; i++)
{
temp <<= 8;
- int barrBarrI = barr[barrI++];
- if (barrBarrI < 0)
- {
- barrBarrI += 256;
- }
+ int barrBarrI = barr[barrI++] & 0xFF;
temp |= barrBarrI;
}
m_ints[iarrJ] = temp;
@@ -95,88 +130,86 @@ class IntArray
public boolean isZero()
{
- return m_ints.length == 0
- || (m_ints[0] == 0 && getUsedLength() == 0);
+ int[] a = m_ints;
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
}
public int getUsedLength()
{
- int highestIntPos = m_ints.length;
+ return getUsedLengthFrom(m_ints.length);
+ }
- if (highestIntPos < 1)
+ public int getUsedLengthFrom(int from)
+ {
+ int[] a = m_ints;
+ from = Math.min(from, a.length);
+
+ if (from < 1)
{
return 0;
}
// Check if first element will act as sentinel
- if (m_ints[0] != 0)
+ if (a[0] != 0)
{
- while (m_ints[--highestIntPos] == 0)
+ while (a[--from] == 0)
{
}
- return highestIntPos + 1;
+ return from + 1;
}
do
{
- if (m_ints[--highestIntPos] != 0)
+ if (a[--from] != 0)
{
- return highestIntPos + 1;
+ return from + 1;
}
}
- while (highestIntPos > 0);
+ while (from > 0);
return 0;
}
- public int bitLength()
+ public int degree()
{
- // JDK 1.5: see Integer.numberOfLeadingZeros()
- int intLen = getUsedLength();
- if (intLen == 0)
- {
- return 0;
- }
-
- int last = intLen - 1;
- int highest = m_ints[last];
- int bits = (last << 5) + 1;
-
- // A couple of binary search steps
- if ((highest & 0xffff0000) != 0)
+ int i = m_ints.length, w;
+ do
{
- if ((highest & 0xff000000) != 0)
- {
- bits += 24;
- highest >>>= 24;
- }
- else
+ if (i == 0)
{
- bits += 16;
- highest >>>= 16;
+ return 0;
}
+ w = m_ints[--i];
}
- else if (highest > 0x000000ff)
- {
- bits += 8;
- highest >>>= 8;
- }
+ while (w == 0);
- while (highest != 1)
+ return (i << 5) + bitLength(w);
+ }
+
+ private static int bitLength(int w)
+ {
+ int t = w >>> 16;
+ if (t == 0)
{
- ++bits;
- highest >>>= 1;
+ t = w >>> 8;
+ return (t == 0) ? bitLengths[w] : 8 + bitLengths[t];
}
- return bits;
+ int u = t >>> 8;
+ return (u == 0) ? 16 + bitLengths[t] : 24 + bitLengths[u];
}
private int[] resizedInts(int newLen)
{
int[] newInts = new int[newLen];
- int oldLen = m_ints.length;
- int copyLen = oldLen < newLen ? oldLen : newLen;
- System.arraycopy(m_ints, 0, newInts, 0, copyLen);
+ System.arraycopy(m_ints, 0, newInts, 0, Math.min(m_ints.length, newLen));
return newInts;
}
@@ -220,86 +253,128 @@ class IntArray
return new BigInteger(1, barr);
}
- public void shiftLeft()
+ private static int shiftLeft(int[] x, int count)
{
- int usedLen = getUsedLength();
- if (usedLen == 0)
+ int prev = 0;
+ for (int i = 0; i < count; ++i)
+ {
+ int next = x[i];
+ x[i] = (next << 1) | prev;
+ prev = next >>> 31;
+ }
+ return prev;
+ }
+
+ public void addOneShifted(int shift)
+ {
+ if (shift >= m_ints.length)
+ {
+ m_ints = resizedInts(shift + 1);
+ }
+
+ m_ints[shift] ^= 1;
+ }
+
+ private void addShiftedByBits(IntArray other, int bits)
+ {
+ int words = bits >>> 5;
+ int shift = bits & 0x1F;
+
+ if (shift == 0)
+ {
+ addShiftedByWords(other, words);
+ return;
+ }
+
+ int otherUsedLen = other.getUsedLength();
+ if (otherUsedLen == 0)
{
return;
}
- if (m_ints[usedLen - 1] < 0)
+
+ int minLen = otherUsedLen + words + 1;
+ if (minLen > m_ints.length)
{
- // highest bit of highest used byte is set, so shifting left will
- // make the IntArray one byte longer
- usedLen++;
- if (usedLen > m_ints.length)
- {
- // make the m_ints one byte longer, because we need one more
- // byte which is not available in m_ints
- m_ints = resizedInts(m_ints.length + 1);
- }
+ m_ints = resizedInts(minLen);
}
- boolean carry = false;
- for (int i = 0; i < usedLen; i++)
+ int shiftInv = 32 - shift, prev = 0;
+ for (int i = 0; i < otherUsedLen; ++i)
{
- // nextCarry is true if highest bit is set
- boolean nextCarry = m_ints[i] < 0;
- m_ints[i] <<= 1;
- if (carry)
- {
- // set lowest bit
- m_ints[i] |= 1;
- }
- carry = nextCarry;
+ int next = other.m_ints[i];
+ m_ints[i + words] ^= (next << shift) | prev;
+ prev = next >>> shiftInv;
}
+ m_ints[otherUsedLen + words] ^= prev;
}
- public IntArray shiftLeft(int n)
+ private static int addShiftedByBits(int[] x, int[] y, int count, int shift)
{
- int usedLen = getUsedLength();
- if (usedLen == 0)
+ int shiftInv = 32 - shift, prev = 0;
+ for (int i = 0; i < count; ++i)
{
- return this;
+ int next = y[i];
+ x[i] ^= (next << shift) | prev;
+ prev = next >>> shiftInv;
}
+ return prev;
+ }
- if (n == 0)
+ private static int addShiftedByBits(int[] x, int xOff, int[] y, int yOff, int count, int shift)
+ {
+ int shiftInv = 32 - shift, prev = 0;
+ for (int i = 0; i < count; ++i)
{
- return this;
+ int next = y[yOff + i];
+ x[xOff + i] ^= (next << shift) | prev;
+ prev = next >>> shiftInv;
}
+ return prev;
+ }
- if (n > 31)
+ public void addShiftedByWords(IntArray other, int words)
+ {
+ int otherUsedLen = other.getUsedLength();
+ if (otherUsedLen == 0)
{
- throw new IllegalArgumentException("shiftLeft() for max 31 bits "
- + ", " + n + "bit shift is not possible");
+ return;
}
- int[] newInts = new int[usedLen + 1];
+ int minLen = otherUsedLen + words;
+ if (minLen > m_ints.length)
+ {
+ m_ints = resizedInts(minLen);
+ }
- int nm32 = 32 - n;
- newInts[0] = m_ints[0] << n;
- for (int i = 1; i < usedLen; i++)
+ for (int i = 0; i < otherUsedLen; i++)
{
- newInts[i] = (m_ints[i] << n) | (m_ints[i - 1] >>> nm32);
+ m_ints[words + i] ^= other.m_ints[i];
}
- newInts[usedLen] = m_ints[usedLen - 1] >>> nm32;
+ }
- return new IntArray(newInts);
+ private static void addShiftedByWords(int[] x, int xOff, int[] y, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ x[xOff + i] ^= y[i];
+ }
}
- public void addShifted(IntArray other, int shift)
+ private static void add(int[] x, int[] y, int count)
{
- int usedLenOther = other.getUsedLength();
- int newMinUsedLen = usedLenOther + shift;
- if (newMinUsedLen > m_ints.length)
+ for (int i = 0; i < count; ++i)
{
- m_ints = resizedInts(newMinUsedLen);
- //System.out.println("Resize required");
+ x[i] ^= y[i];
}
+ }
- for (int i = 0; i < usedLenOther; i++)
+ private static void distribute(int[] x, int dst1, int dst2, int src, int count)
+ {
+ for (int i = 0; i < count; ++i)
{
- m_ints[i + shift] ^= other.m_ints[i];
+ int v = x[src + i];
+ x[dst1 + i] ^= v;
+ x[dst2 + i] ^= v;
}
}
@@ -308,10 +383,58 @@ class IntArray
return m_ints.length;
}
+ public void flipWord(int bit, int word)
+ {
+ int len = m_ints.length;
+ int n = bit >>> 5;
+ if (n < len)
+ {
+ int shift = bit & 0x1F;
+ if (shift == 0)
+ {
+ m_ints[n] ^= word;
+ }
+ else
+ {
+ m_ints[n] ^= word << shift;
+ if (++n < len)
+ {
+ m_ints[n] ^= word >>> (32 - shift);
+ }
+ }
+ }
+ }
+
+ public int getWord(int bit)
+ {
+ int len = m_ints.length;
+ int n = bit >>> 5;
+ if (n >= len)
+ {
+ return 0;
+ }
+ int shift = bit & 0x1F;
+ if (shift == 0)
+ {
+ return m_ints[n];
+ }
+ int result = m_ints[n] >>> shift;
+ if (++n < len)
+ {
+ result |= m_ints[n] << (32 - shift);
+ }
+ return result;
+ }
+
+ public boolean testBitZero()
+ {
+ return m_ints.length > 0 && (m_ints[0] & 1) != 0;
+ }
+
public boolean testBit(int n)
{
// theInt = n / 32
- int theInt = n >> 5;
+ int theInt = n >>> 5;
// theBit = n % 32
int theBit = n & 0x1F;
int tester = 1 << theBit;
@@ -321,7 +444,7 @@ class IntArray
public void flipBit(int n)
{
// theInt = n / 32
- int theInt = n >> 5;
+ int theInt = n >>> 5;
// theBit = n % 32
int theBit = n & 0x1F;
int flipper = 1 << theBit;
@@ -331,127 +454,344 @@ class IntArray
public void setBit(int n)
{
// theInt = n / 32
- int theInt = n >> 5;
+ int theInt = n >>> 5;
// theBit = n % 32
int theBit = n & 0x1F;
int setter = 1 << theBit;
m_ints[theInt] |= setter;
}
+ public void clearBit(int n)
+ {
+ // theInt = n / 32
+ int theInt = n >>> 5;
+ // theBit = n % 32
+ int theBit = n & 0x1F;
+ int setter = 1 << theBit;
+ m_ints[theInt] &= ~setter;
+ }
+
public IntArray multiply(IntArray other, int m)
{
- // Lenght of c is 2m bits rounded up to the next int (32 bit)
- int t = (m + 31) >> 5;
- if (m_ints.length < t)
+ int aLen = getUsedLength();
+ if (aLen == 0)
+ {
+ return new IntArray(1);
+ }
+
+ int bLen = other.getUsedLength();
+ if (bLen == 0)
+ {
+ return new IntArray(1);
+ }
+
+ IntArray A = this, B = other;
+ if (aLen > bLen)
+ {
+ A = other; B = this;
+ int tmp = aLen; aLen = bLen; bLen = tmp;
+ }
+
+ if (aLen == 1)
+ {
+ int a = A.m_ints[0];
+ int[] b = B.m_ints;
+ int[] c = new int[aLen + bLen];
+ if ((a & 1) != 0)
+ {
+ add(c, b, bLen);
+ }
+ int k = 1;
+ while ((a >>>= 1) != 0)
+ {
+ if ((a & 1) != 0)
+ {
+ addShiftedByBits(c, b, bLen, k);
+ }
+ ++k;
+ }
+ return new IntArray(c);
+ }
+
+ // TODO It'd be better to be able to tune the width directly (need support for interleaving arbitrary widths)
+ int complexity = aLen <= 8 ? 1 : 2;
+
+ int width = 1 << complexity;
+ int shifts = (32 >>> complexity);
+
+ int bExt = bLen;
+ if ((B.m_ints[bLen - 1] >>> (33 - shifts)) != 0)
{
- m_ints = resizedInts(t);
+ ++bExt;
}
- IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
- IntArray c = new IntArray((m + m + 31) >> 5);
- // IntArray c = new IntArray(t + t);
- int testBit = 1;
- for (int k = 0; k < 32; k++)
+ int cLen = bExt + aLen;
+
+ int[] c = new int[cLen << width];
+ System.arraycopy(B.m_ints, 0, c, 0, bLen);
+ interleave(A.m_ints, 0, c, bExt, aLen, complexity);
+
+ int[] ci = new int[1 << width];
+ for (int i = 1; i < ci.length; ++i)
+ {
+ ci[i] = ci[i - 1] + cLen;
+ }
+
+ int MASK = (1 << width) - 1;
+
+ int k = 0;
+ for (;;)
{
- for (int j = 0; j < t; j++)
+ for (int aPos = 0; aPos < aLen; ++aPos)
{
- if ((m_ints[j] & testBit) != 0)
+ int index = (c[bExt + aPos] >>> k) & MASK;
+ if (index != 0)
{
- // The kth bit of m_ints[j] is set
- c.addShifted(b, j);
+ addShiftedByWords(c, aPos + ci[index], c, bExt);
}
}
- testBit <<= 1;
- b.shiftLeft();
- }
- return c;
- }
-
- // public IntArray multiplyLeftToRight(IntArray other, int m) {
- // // Lenght of c is 2m bits rounded up to the next int (32 bit)
- // int t = (m + 31) / 32;
- // if (m_ints.length < t) {
- // m_ints = resizedInts(t);
- // }
- //
- // IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
- // IntArray c = new IntArray((m + m + 31) / 32);
- // // IntArray c = new IntArray(t + t);
- // int testBit = 1 << 31;
- // for (int k = 31; k >= 0; k--) {
- // for (int j = 0; j < t; j++) {
- // if ((m_ints[j] & testBit) != 0) {
- // // The kth bit of m_ints[j] is set
- // c.addShifted(b, j);
- // }
- // }
- // testBit >>>= 1;
- // if (k > 0) {
- // c.shiftLeft();
- // }
- // }
- // return c;
- // }
-
- // TODO note, redPol.length must be 3 for TPB and 5 for PPB
- public void reduce(int m, int[] redPol)
- {
- for (int i = m + m - 2; i >= m; i--)
+
+ if ((k += width) >= 32)
+ {
+ break;
+ }
+
+ shiftLeft(c, bExt);
+ }
+
+ int ciPos = ci.length, pow2 = ciPos >>> 1, offset = 32;
+ while (--ciPos > 1)
+ {
+ if (ciPos == pow2)
+ {
+ offset -= shifts;
+ addShiftedByBits(c, ci[1], c, ci[pow2], cLen, offset);
+ pow2 >>>= 1;
+ }
+ else
+ {
+ distribute(c, ci[pow2], ci[ciPos - pow2], ci[ciPos], cLen);
+ }
+ }
+
+ // TODO reduce in place to avoid extra copying
+ IntArray p = new IntArray(cLen);
+ System.arraycopy(c, ci[1], p.m_ints, 0, cLen);
+ return p;
+ }
+
+// private static void deInterleave(int[] x, int xOff, int[] z, int zOff, int count, int rounds)
+// {
+// for (int i = 0; i < count; ++i)
+// {
+// z[zOff + i] = deInterleave(x[zOff + i], rounds);
+// }
+// }
+//
+// private static int deInterleave(int x, int rounds)
+// {
+// while (--rounds >= 0)
+// {
+// x = deInterleave16(x & DEINTERLEAVE_MASK) | (deInterleave16((x >>> 1) & DEINTERLEAVE_MASK) << 16);
+// }
+// return x;
+// }
+//
+// private static int deInterleave16(int x)
+// {
+// x = (x | (x >>> 1)) & 0x33333333;
+// x = (x | (x >>> 2)) & 0x0F0F0F0F;
+// x = (x | (x >>> 4)) & 0x00FF00FF;
+// x = (x | (x >>> 8)) & 0x0000FFFF;
+// return x;
+// }
+
+ public void reduce(int m, int[] ks)
+ {
+ int len = getUsedLength();
+ int mLen = (m + 31) >>> 5;
+ if (len < mLen)
+ {
+ return;
+ }
+
+ int _2m = m << 1;
+ int pos = Math.min(_2m - 2, (len << 5) - 1);
+
+ int kMax = ks[ks.length - 1];
+ if (kMax < m - 31)
+ {
+ reduceWordWise(pos, m, ks);
+ }
+ else
+ {
+ reduceBitWise(pos, m, ks);
+ }
+
+ // Instead of flipping the high bits in the loop, explicitly clear any partial word above m bits
+ int partial = m & 0x1F;
+ if (partial != 0)
+ {
+ m_ints[mLen - 1] &= (1 << partial) - 1;
+ }
+
+ if (len > mLen)
+ {
+ m_ints = resizedInts(mLen);
+ }
+ }
+
+ private void reduceBitWise(int from, int m, int[] ks)
+ {
+ for (int i = from; i >= m; --i)
{
if (testBit(i))
{
+// clearBit(i);
int bit = i - m;
flipBit(bit);
- flipBit(i);
- int l = redPol.length;
- while (--l >= 0)
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipBit(ks[j] + bit);
+ }
+ }
+ }
+ }
+
+ private void reduceWordWise(int from, int m, int[] ks)
+ {
+ int pos = m + ((from - m) & ~0x1F);
+ for (int i = pos; i >= m; i -= 32)
+ {
+ int word = getWord(i);
+ if (word != 0)
+ {
+// flipWord(i);
+ int bit = i - m;
+ flipWord(bit, word);
+ int j = ks.length;
+ while (--j >= 0)
{
- flipBit(redPol[l] + bit);
+ flipWord(ks[j] + bit, word);
}
}
}
- m_ints = resizedInts((m + 31) >> 5);
}
public IntArray square(int m)
{
- // TODO make the table static final
- final int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40,
- 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 };
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
- int t = (m + 31) >> 5;
- if (m_ints.length < t)
+ int _2len = len << 1;
+ int[] r = new int[_2len];
+
+ int pos = 0;
+ while (pos < _2len)
{
- m_ints = resizedInts(t);
+ int mi = m_ints[pos >>> 1];
+ r[pos++] = interleave16(mi & 0xFFFF);
+ r[pos++] = interleave16(mi >>> 16);
}
- IntArray c = new IntArray(t + t);
+ return new IntArray(r);
+ }
- // TODO twice the same code, put in separate private method
- for (int i = 0; i < t; i++)
+ private static void interleave(int[] x, int xOff, int[] z, int zOff, int count, int rounds)
+ {
+ for (int i = 0; i < count; ++i)
{
- int v0 = 0;
- for (int j = 0; j < 4; j++)
+ z[zOff + i] = interleave(x[xOff + i], rounds);
+ }
+ }
+
+ private static int interleave(int x, int rounds)
+ {
+ while (--rounds >= 0)
+ {
+ x = interleave16(x & 0xFFFF) | (interleave16(x >>> 16) << 1);
+ }
+ return x;
+ }
+
+ private static int interleave16(int n)
+ {
+ return INTERLEAVE_TABLE[n & 0xFF] | INTERLEAVE_TABLE[n >>> 8] << 16;
+ }
+
+ public IntArray modInverse(int m, int[] ks)
+ {
+ // Inversion in F2m using the extended Euclidean algorithm
+ // Input: A nonzero polynomial a(z) of degree at most m-1
+ // Output: a(z)^(-1) mod f(z)
+
+ int uzDegree = degree();
+ if (uzDegree == 1)
+ {
+ return this;
+ }
+
+ // u(z) := a(z)
+ IntArray uz = (IntArray)clone();
+
+ int t = getWordLength(m);
+
+ // v(z) := f(z)
+ IntArray vz = new IntArray(t);
+ vz.setBit(m);
+ vz.setBit(0);
+ vz.setBit(ks[0]);
+ if (ks.length > 1)
+ {
+ vz.setBit(ks[1]);
+ vz.setBit(ks[2]);
+ }
+
+ // g1(z) := 1, g2(z) := 0
+ IntArray g1z = new IntArray(t);
+ g1z.setBit(0);
+ IntArray g2z = new IntArray(t);
+
+ while (uzDegree != 0)
+ {
+ // j := deg(u(z)) - deg(v(z))
+ int j = uzDegree - vz.degree();
+
+ // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j
+ if (j < 0)
{
- v0 = v0 >>> 8;
- int u = (m_ints[i] >>> (j * 4)) & 0xF;
- int w = table[u] << 24;
- v0 |= w;
+ final IntArray uzCopy = uz;
+ uz = vz;
+ vz = uzCopy;
+
+ final IntArray g1zCopy = g1z;
+ g1z = g2z;
+ g2z = g1zCopy;
+
+ j = -j;
}
- c.m_ints[i + i] = v0;
- v0 = 0;
- int upper = m_ints[i] >>> 16;
- for (int j = 0; j < 4; j++)
+ // u(z) := u(z) + z^j * v(z)
+ // Note, that no reduction modulo f(z) is required, because
+ // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z)))
+ // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z))
+ // = deg(u(z))
+ // uz = uz.xor(vz.shiftLeft(j));
+ uz.addShiftedByBits(vz, j);
+ uzDegree = uz.degree();
+
+ // g1(z) := g1(z) + z^j * g2(z)
+// g1z = g1z.xor(g2z.shiftLeft(j));
+ if (uzDegree != 0)
{
- v0 = v0 >>> 8;
- int u = (upper >>> (j * 4)) & 0xF;
- int w = table[u] << 24;
- v0 |= w;
+ g1z.addShiftedByBits(g2z, j);
}
- c.m_ints[i + i + 1] = v0;
}
- return c;
+ return g2z;
}
public boolean equals(Object o)
@@ -482,7 +822,8 @@ class IntArray
int hash = 1;
for (int i = 0; i < usedLen; i++)
{
- hash = hash * 31 + m_ints[i];
+ hash *= 31;
+ hash ^= m_ints[i];
}
return hash;
}
@@ -494,25 +835,26 @@ class IntArray
public String toString()
{
- int usedLen = getUsedLength();
- if (usedLen == 0)
+ int i = getUsedLength();
+ if (i == 0)
{
return "0";
}
- StringBuffer sb = new StringBuffer(Integer
- .toBinaryString(m_ints[usedLen - 1]));
- for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
+ StringBuffer sb = new StringBuffer(Integer.toBinaryString(m_ints[--i]));
+ while (--i >= 0)
{
- String hexString = Integer.toBinaryString(m_ints[iarrJ]);
+ String s = Integer.toBinaryString(m_ints[i]);
- // Add leading zeroes, except for highest significant int
- for (int i = hexString.length(); i < 8; i++)
+ // Add leading zeroes, except for highest significant word
+ int len = s.length();
+ if (len < 32)
{
- hexString = "0" + hexString;
+ sb.append(ZEROES.substring(len));
}
- sb.append(hexString);
+
+ sb.append(s);
}
return sb.toString();
}
-}
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java b/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java
new file mode 100644
index 0000000..7e8b172
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/LongArray.java
@@ -0,0 +1,1995 @@
+package org.bouncycastle.math.ec;
+
+import org.bouncycastle.util.Arrays;
+
+import java.math.BigInteger;
+
+class LongArray
+{
+// private static long DEINTERLEAVE_MASK = 0x5555555555555555L;
+
+ /*
+ * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits.
+ * In a binary field, this operation is the same as squaring an 8 bit number.
+ */
+ private static final int[] INTERLEAVE2_TABLE = new int[]
+ {
+ 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
+ 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
+ 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
+ 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
+ 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
+ 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
+ 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
+ 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
+ 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
+ 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
+ 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
+ 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
+ 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
+ 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
+ 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
+ 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
+ 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
+ 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
+ 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
+ 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
+ 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
+ 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
+ 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
+ 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
+ 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
+ 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
+ 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
+ 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
+ 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
+ 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
+ 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
+ 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
+ };
+
+ /*
+ * This expands 7 bit indices into 21 bit contents (high bit 18), by inserting 0s between bits.
+ */
+ private static final int[] INTERLEAVE3_TABLE = new int[]
+ {
+ 0x00000, 0x00001, 0x00008, 0x00009, 0x00040, 0x00041, 0x00048, 0x00049,
+ 0x00200, 0x00201, 0x00208, 0x00209, 0x00240, 0x00241, 0x00248, 0x00249,
+ 0x01000, 0x01001, 0x01008, 0x01009, 0x01040, 0x01041, 0x01048, 0x01049,
+ 0x01200, 0x01201, 0x01208, 0x01209, 0x01240, 0x01241, 0x01248, 0x01249,
+ 0x08000, 0x08001, 0x08008, 0x08009, 0x08040, 0x08041, 0x08048, 0x08049,
+ 0x08200, 0x08201, 0x08208, 0x08209, 0x08240, 0x08241, 0x08248, 0x08249,
+ 0x09000, 0x09001, 0x09008, 0x09009, 0x09040, 0x09041, 0x09048, 0x09049,
+ 0x09200, 0x09201, 0x09208, 0x09209, 0x09240, 0x09241, 0x09248, 0x09249,
+ 0x40000, 0x40001, 0x40008, 0x40009, 0x40040, 0x40041, 0x40048, 0x40049,
+ 0x40200, 0x40201, 0x40208, 0x40209, 0x40240, 0x40241, 0x40248, 0x40249,
+ 0x41000, 0x41001, 0x41008, 0x41009, 0x41040, 0x41041, 0x41048, 0x41049,
+ 0x41200, 0x41201, 0x41208, 0x41209, 0x41240, 0x41241, 0x41248, 0x41249,
+ 0x48000, 0x48001, 0x48008, 0x48009, 0x48040, 0x48041, 0x48048, 0x48049,
+ 0x48200, 0x48201, 0x48208, 0x48209, 0x48240, 0x48241, 0x48248, 0x48249,
+ 0x49000, 0x49001, 0x49008, 0x49009, 0x49040, 0x49041, 0x49048, 0x49049,
+ 0x49200, 0x49201, 0x49208, 0x49209, 0x49240, 0x49241, 0x49248, 0x49249
+ };
+
+ /*
+ * This expands 8 bit indices into 32 bit contents (high bit 28), by inserting 0s between bits.
+ */
+ private static final int[] INTERLEAVE4_TABLE = new int[]
+ {
+ 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, 0x00000101, 0x00000110, 0x00000111,
+ 0x00001000, 0x00001001, 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, 0x00001111,
+ 0x00010000, 0x00010001, 0x00010010, 0x00010011, 0x00010100, 0x00010101, 0x00010110, 0x00010111,
+ 0x00011000, 0x00011001, 0x00011010, 0x00011011, 0x00011100, 0x00011101, 0x00011110, 0x00011111,
+ 0x00100000, 0x00100001, 0x00100010, 0x00100011, 0x00100100, 0x00100101, 0x00100110, 0x00100111,
+ 0x00101000, 0x00101001, 0x00101010, 0x00101011, 0x00101100, 0x00101101, 0x00101110, 0x00101111,
+ 0x00110000, 0x00110001, 0x00110010, 0x00110011, 0x00110100, 0x00110101, 0x00110110, 0x00110111,
+ 0x00111000, 0x00111001, 0x00111010, 0x00111011, 0x00111100, 0x00111101, 0x00111110, 0x00111111,
+ 0x01000000, 0x01000001, 0x01000010, 0x01000011, 0x01000100, 0x01000101, 0x01000110, 0x01000111,
+ 0x01001000, 0x01001001, 0x01001010, 0x01001011, 0x01001100, 0x01001101, 0x01001110, 0x01001111,
+ 0x01010000, 0x01010001, 0x01010010, 0x01010011, 0x01010100, 0x01010101, 0x01010110, 0x01010111,
+ 0x01011000, 0x01011001, 0x01011010, 0x01011011, 0x01011100, 0x01011101, 0x01011110, 0x01011111,
+ 0x01100000, 0x01100001, 0x01100010, 0x01100011, 0x01100100, 0x01100101, 0x01100110, 0x01100111,
+ 0x01101000, 0x01101001, 0x01101010, 0x01101011, 0x01101100, 0x01101101, 0x01101110, 0x01101111,
+ 0x01110000, 0x01110001, 0x01110010, 0x01110011, 0x01110100, 0x01110101, 0x01110110, 0x01110111,
+ 0x01111000, 0x01111001, 0x01111010, 0x01111011, 0x01111100, 0x01111101, 0x01111110, 0x01111111,
+ 0x10000000, 0x10000001, 0x10000010, 0x10000011, 0x10000100, 0x10000101, 0x10000110, 0x10000111,
+ 0x10001000, 0x10001001, 0x10001010, 0x10001011, 0x10001100, 0x10001101, 0x10001110, 0x10001111,
+ 0x10010000, 0x10010001, 0x10010010, 0x10010011, 0x10010100, 0x10010101, 0x10010110, 0x10010111,
+ 0x10011000, 0x10011001, 0x10011010, 0x10011011, 0x10011100, 0x10011101, 0x10011110, 0x10011111,
+ 0x10100000, 0x10100001, 0x10100010, 0x10100011, 0x10100100, 0x10100101, 0x10100110, 0x10100111,
+ 0x10101000, 0x10101001, 0x10101010, 0x10101011, 0x10101100, 0x10101101, 0x10101110, 0x10101111,
+ 0x10110000, 0x10110001, 0x10110010, 0x10110011, 0x10110100, 0x10110101, 0x10110110, 0x10110111,
+ 0x10111000, 0x10111001, 0x10111010, 0x10111011, 0x10111100, 0x10111101, 0x10111110, 0x10111111,
+ 0x11000000, 0x11000001, 0x11000010, 0x11000011, 0x11000100, 0x11000101, 0x11000110, 0x11000111,
+ 0x11001000, 0x11001001, 0x11001010, 0x11001011, 0x11001100, 0x11001101, 0x11001110, 0x11001111,
+ 0x11010000, 0x11010001, 0x11010010, 0x11010011, 0x11010100, 0x11010101, 0x11010110, 0x11010111,
+ 0x11011000, 0x11011001, 0x11011010, 0x11011011, 0x11011100, 0x11011101, 0x11011110, 0x11011111,
+ 0x11100000, 0x11100001, 0x11100010, 0x11100011, 0x11100100, 0x11100101, 0x11100110, 0x11100111,
+ 0x11101000, 0x11101001, 0x11101010, 0x11101011, 0x11101100, 0x11101101, 0x11101110, 0x11101111,
+ 0x11110000, 0x11110001, 0x11110010, 0x11110011, 0x11110100, 0x11110101, 0x11110110, 0x11110111,
+ 0x11111000, 0x11111001, 0x11111010, 0x11111011, 0x11111100, 0x11111101, 0x11111110, 0x11111111
+ };
+
+ /*
+ * This expands 7 bit indices into 35 bit contents (high bit 30), by inserting 0s between bits.
+ */
+ private static final int[] INTERLEAVE5_TABLE = new int[] {
+ 0x00000000, 0x00000001, 0x00000020, 0x00000021, 0x00000400, 0x00000401, 0x00000420, 0x00000421,
+ 0x00008000, 0x00008001, 0x00008020, 0x00008021, 0x00008400, 0x00008401, 0x00008420, 0x00008421,
+ 0x00100000, 0x00100001, 0x00100020, 0x00100021, 0x00100400, 0x00100401, 0x00100420, 0x00100421,
+ 0x00108000, 0x00108001, 0x00108020, 0x00108021, 0x00108400, 0x00108401, 0x00108420, 0x00108421,
+ 0x02000000, 0x02000001, 0x02000020, 0x02000021, 0x02000400, 0x02000401, 0x02000420, 0x02000421,
+ 0x02008000, 0x02008001, 0x02008020, 0x02008021, 0x02008400, 0x02008401, 0x02008420, 0x02008421,
+ 0x02100000, 0x02100001, 0x02100020, 0x02100021, 0x02100400, 0x02100401, 0x02100420, 0x02100421,
+ 0x02108000, 0x02108001, 0x02108020, 0x02108021, 0x02108400, 0x02108401, 0x02108420, 0x02108421,
+ 0x40000000, 0x40000001, 0x40000020, 0x40000021, 0x40000400, 0x40000401, 0x40000420, 0x40000421,
+ 0x40008000, 0x40008001, 0x40008020, 0x40008021, 0x40008400, 0x40008401, 0x40008420, 0x40008421,
+ 0x40100000, 0x40100001, 0x40100020, 0x40100021, 0x40100400, 0x40100401, 0x40100420, 0x40100421,
+ 0x40108000, 0x40108001, 0x40108020, 0x40108021, 0x40108400, 0x40108401, 0x40108420, 0x40108421,
+ 0x42000000, 0x42000001, 0x42000020, 0x42000021, 0x42000400, 0x42000401, 0x42000420, 0x42000421,
+ 0x42008000, 0x42008001, 0x42008020, 0x42008021, 0x42008400, 0x42008401, 0x42008420, 0x42008421,
+ 0x42100000, 0x42100001, 0x42100020, 0x42100021, 0x42100400, 0x42100401, 0x42100420, 0x42100421,
+ 0x42108000, 0x42108001, 0x42108020, 0x42108021, 0x42108400, 0x42108401, 0x42108420, 0x42108421
+ };
+
+ /*
+ * This expands 9 bit indices into 63 bit (long) contents (high bit 56), by inserting 0s between bits.
+ */
+ private static final long[] INTERLEAVE7_TABLE = new long[]
+ {
+ 0x0000000000000000L, 0x0000000000000001L, 0x0000000000000080L, 0x0000000000000081L,
+ 0x0000000000004000L, 0x0000000000004001L, 0x0000000000004080L, 0x0000000000004081L,
+ 0x0000000000200000L, 0x0000000000200001L, 0x0000000000200080L, 0x0000000000200081L,
+ 0x0000000000204000L, 0x0000000000204001L, 0x0000000000204080L, 0x0000000000204081L,
+ 0x0000000010000000L, 0x0000000010000001L, 0x0000000010000080L, 0x0000000010000081L,
+ 0x0000000010004000L, 0x0000000010004001L, 0x0000000010004080L, 0x0000000010004081L,
+ 0x0000000010200000L, 0x0000000010200001L, 0x0000000010200080L, 0x0000000010200081L,
+ 0x0000000010204000L, 0x0000000010204001L, 0x0000000010204080L, 0x0000000010204081L,
+ 0x0000000800000000L, 0x0000000800000001L, 0x0000000800000080L, 0x0000000800000081L,
+ 0x0000000800004000L, 0x0000000800004001L, 0x0000000800004080L, 0x0000000800004081L,
+ 0x0000000800200000L, 0x0000000800200001L, 0x0000000800200080L, 0x0000000800200081L,
+ 0x0000000800204000L, 0x0000000800204001L, 0x0000000800204080L, 0x0000000800204081L,
+ 0x0000000810000000L, 0x0000000810000001L, 0x0000000810000080L, 0x0000000810000081L,
+ 0x0000000810004000L, 0x0000000810004001L, 0x0000000810004080L, 0x0000000810004081L,
+ 0x0000000810200000L, 0x0000000810200001L, 0x0000000810200080L, 0x0000000810200081L,
+ 0x0000000810204000L, 0x0000000810204001L, 0x0000000810204080L, 0x0000000810204081L,
+ 0x0000040000000000L, 0x0000040000000001L, 0x0000040000000080L, 0x0000040000000081L,
+ 0x0000040000004000L, 0x0000040000004001L, 0x0000040000004080L, 0x0000040000004081L,
+ 0x0000040000200000L, 0x0000040000200001L, 0x0000040000200080L, 0x0000040000200081L,
+ 0x0000040000204000L, 0x0000040000204001L, 0x0000040000204080L, 0x0000040000204081L,
+ 0x0000040010000000L, 0x0000040010000001L, 0x0000040010000080L, 0x0000040010000081L,
+ 0x0000040010004000L, 0x0000040010004001L, 0x0000040010004080L, 0x0000040010004081L,
+ 0x0000040010200000L, 0x0000040010200001L, 0x0000040010200080L, 0x0000040010200081L,
+ 0x0000040010204000L, 0x0000040010204001L, 0x0000040010204080L, 0x0000040010204081L,
+ 0x0000040800000000L, 0x0000040800000001L, 0x0000040800000080L, 0x0000040800000081L,
+ 0x0000040800004000L, 0x0000040800004001L, 0x0000040800004080L, 0x0000040800004081L,
+ 0x0000040800200000L, 0x0000040800200001L, 0x0000040800200080L, 0x0000040800200081L,
+ 0x0000040800204000L, 0x0000040800204001L, 0x0000040800204080L, 0x0000040800204081L,
+ 0x0000040810000000L, 0x0000040810000001L, 0x0000040810000080L, 0x0000040810000081L,
+ 0x0000040810004000L, 0x0000040810004001L, 0x0000040810004080L, 0x0000040810004081L,
+ 0x0000040810200000L, 0x0000040810200001L, 0x0000040810200080L, 0x0000040810200081L,
+ 0x0000040810204000L, 0x0000040810204001L, 0x0000040810204080L, 0x0000040810204081L,
+ 0x0002000000000000L, 0x0002000000000001L, 0x0002000000000080L, 0x0002000000000081L,
+ 0x0002000000004000L, 0x0002000000004001L, 0x0002000000004080L, 0x0002000000004081L,
+ 0x0002000000200000L, 0x0002000000200001L, 0x0002000000200080L, 0x0002000000200081L,
+ 0x0002000000204000L, 0x0002000000204001L, 0x0002000000204080L, 0x0002000000204081L,
+ 0x0002000010000000L, 0x0002000010000001L, 0x0002000010000080L, 0x0002000010000081L,
+ 0x0002000010004000L, 0x0002000010004001L, 0x0002000010004080L, 0x0002000010004081L,
+ 0x0002000010200000L, 0x0002000010200001L, 0x0002000010200080L, 0x0002000010200081L,
+ 0x0002000010204000L, 0x0002000010204001L, 0x0002000010204080L, 0x0002000010204081L,
+ 0x0002000800000000L, 0x0002000800000001L, 0x0002000800000080L, 0x0002000800000081L,
+ 0x0002000800004000L, 0x0002000800004001L, 0x0002000800004080L, 0x0002000800004081L,
+ 0x0002000800200000L, 0x0002000800200001L, 0x0002000800200080L, 0x0002000800200081L,
+ 0x0002000800204000L, 0x0002000800204001L, 0x0002000800204080L, 0x0002000800204081L,
+ 0x0002000810000000L, 0x0002000810000001L, 0x0002000810000080L, 0x0002000810000081L,
+ 0x0002000810004000L, 0x0002000810004001L, 0x0002000810004080L, 0x0002000810004081L,
+ 0x0002000810200000L, 0x0002000810200001L, 0x0002000810200080L, 0x0002000810200081L,
+ 0x0002000810204000L, 0x0002000810204001L, 0x0002000810204080L, 0x0002000810204081L,
+ 0x0002040000000000L, 0x0002040000000001L, 0x0002040000000080L, 0x0002040000000081L,
+ 0x0002040000004000L, 0x0002040000004001L, 0x0002040000004080L, 0x0002040000004081L,
+ 0x0002040000200000L, 0x0002040000200001L, 0x0002040000200080L, 0x0002040000200081L,
+ 0x0002040000204000L, 0x0002040000204001L, 0x0002040000204080L, 0x0002040000204081L,
+ 0x0002040010000000L, 0x0002040010000001L, 0x0002040010000080L, 0x0002040010000081L,
+ 0x0002040010004000L, 0x0002040010004001L, 0x0002040010004080L, 0x0002040010004081L,
+ 0x0002040010200000L, 0x0002040010200001L, 0x0002040010200080L, 0x0002040010200081L,
+ 0x0002040010204000L, 0x0002040010204001L, 0x0002040010204080L, 0x0002040010204081L,
+ 0x0002040800000000L, 0x0002040800000001L, 0x0002040800000080L, 0x0002040800000081L,
+ 0x0002040800004000L, 0x0002040800004001L, 0x0002040800004080L, 0x0002040800004081L,
+ 0x0002040800200000L, 0x0002040800200001L, 0x0002040800200080L, 0x0002040800200081L,
+ 0x0002040800204000L, 0x0002040800204001L, 0x0002040800204080L, 0x0002040800204081L,
+ 0x0002040810000000L, 0x0002040810000001L, 0x0002040810000080L, 0x0002040810000081L,
+ 0x0002040810004000L, 0x0002040810004001L, 0x0002040810004080L, 0x0002040810004081L,
+ 0x0002040810200000L, 0x0002040810200001L, 0x0002040810200080L, 0x0002040810200081L,
+ 0x0002040810204000L, 0x0002040810204001L, 0x0002040810204080L, 0x0002040810204081L,
+ 0x0100000000000000L, 0x0100000000000001L, 0x0100000000000080L, 0x0100000000000081L,
+ 0x0100000000004000L, 0x0100000000004001L, 0x0100000000004080L, 0x0100000000004081L,
+ 0x0100000000200000L, 0x0100000000200001L, 0x0100000000200080L, 0x0100000000200081L,
+ 0x0100000000204000L, 0x0100000000204001L, 0x0100000000204080L, 0x0100000000204081L,
+ 0x0100000010000000L, 0x0100000010000001L, 0x0100000010000080L, 0x0100000010000081L,
+ 0x0100000010004000L, 0x0100000010004001L, 0x0100000010004080L, 0x0100000010004081L,
+ 0x0100000010200000L, 0x0100000010200001L, 0x0100000010200080L, 0x0100000010200081L,
+ 0x0100000010204000L, 0x0100000010204001L, 0x0100000010204080L, 0x0100000010204081L,
+ 0x0100000800000000L, 0x0100000800000001L, 0x0100000800000080L, 0x0100000800000081L,
+ 0x0100000800004000L, 0x0100000800004001L, 0x0100000800004080L, 0x0100000800004081L,
+ 0x0100000800200000L, 0x0100000800200001L, 0x0100000800200080L, 0x0100000800200081L,
+ 0x0100000800204000L, 0x0100000800204001L, 0x0100000800204080L, 0x0100000800204081L,
+ 0x0100000810000000L, 0x0100000810000001L, 0x0100000810000080L, 0x0100000810000081L,
+ 0x0100000810004000L, 0x0100000810004001L, 0x0100000810004080L, 0x0100000810004081L,
+ 0x0100000810200000L, 0x0100000810200001L, 0x0100000810200080L, 0x0100000810200081L,
+ 0x0100000810204000L, 0x0100000810204001L, 0x0100000810204080L, 0x0100000810204081L,
+ 0x0100040000000000L, 0x0100040000000001L, 0x0100040000000080L, 0x0100040000000081L,
+ 0x0100040000004000L, 0x0100040000004001L, 0x0100040000004080L, 0x0100040000004081L,
+ 0x0100040000200000L, 0x0100040000200001L, 0x0100040000200080L, 0x0100040000200081L,
+ 0x0100040000204000L, 0x0100040000204001L, 0x0100040000204080L, 0x0100040000204081L,
+ 0x0100040010000000L, 0x0100040010000001L, 0x0100040010000080L, 0x0100040010000081L,
+ 0x0100040010004000L, 0x0100040010004001L, 0x0100040010004080L, 0x0100040010004081L,
+ 0x0100040010200000L, 0x0100040010200001L, 0x0100040010200080L, 0x0100040010200081L,
+ 0x0100040010204000L, 0x0100040010204001L, 0x0100040010204080L, 0x0100040010204081L,
+ 0x0100040800000000L, 0x0100040800000001L, 0x0100040800000080L, 0x0100040800000081L,
+ 0x0100040800004000L, 0x0100040800004001L, 0x0100040800004080L, 0x0100040800004081L,
+ 0x0100040800200000L, 0x0100040800200001L, 0x0100040800200080L, 0x0100040800200081L,
+ 0x0100040800204000L, 0x0100040800204001L, 0x0100040800204080L, 0x0100040800204081L,
+ 0x0100040810000000L, 0x0100040810000001L, 0x0100040810000080L, 0x0100040810000081L,
+ 0x0100040810004000L, 0x0100040810004001L, 0x0100040810004080L, 0x0100040810004081L,
+ 0x0100040810200000L, 0x0100040810200001L, 0x0100040810200080L, 0x0100040810200081L,
+ 0x0100040810204000L, 0x0100040810204001L, 0x0100040810204080L, 0x0100040810204081L,
+ 0x0102000000000000L, 0x0102000000000001L, 0x0102000000000080L, 0x0102000000000081L,
+ 0x0102000000004000L, 0x0102000000004001L, 0x0102000000004080L, 0x0102000000004081L,
+ 0x0102000000200000L, 0x0102000000200001L, 0x0102000000200080L, 0x0102000000200081L,
+ 0x0102000000204000L, 0x0102000000204001L, 0x0102000000204080L, 0x0102000000204081L,
+ 0x0102000010000000L, 0x0102000010000001L, 0x0102000010000080L, 0x0102000010000081L,
+ 0x0102000010004000L, 0x0102000010004001L, 0x0102000010004080L, 0x0102000010004081L,
+ 0x0102000010200000L, 0x0102000010200001L, 0x0102000010200080L, 0x0102000010200081L,
+ 0x0102000010204000L, 0x0102000010204001L, 0x0102000010204080L, 0x0102000010204081L,
+ 0x0102000800000000L, 0x0102000800000001L, 0x0102000800000080L, 0x0102000800000081L,
+ 0x0102000800004000L, 0x0102000800004001L, 0x0102000800004080L, 0x0102000800004081L,
+ 0x0102000800200000L, 0x0102000800200001L, 0x0102000800200080L, 0x0102000800200081L,
+ 0x0102000800204000L, 0x0102000800204001L, 0x0102000800204080L, 0x0102000800204081L,
+ 0x0102000810000000L, 0x0102000810000001L, 0x0102000810000080L, 0x0102000810000081L,
+ 0x0102000810004000L, 0x0102000810004001L, 0x0102000810004080L, 0x0102000810004081L,
+ 0x0102000810200000L, 0x0102000810200001L, 0x0102000810200080L, 0x0102000810200081L,
+ 0x0102000810204000L, 0x0102000810204001L, 0x0102000810204080L, 0x0102000810204081L,
+ 0x0102040000000000L, 0x0102040000000001L, 0x0102040000000080L, 0x0102040000000081L,
+ 0x0102040000004000L, 0x0102040000004001L, 0x0102040000004080L, 0x0102040000004081L,
+ 0x0102040000200000L, 0x0102040000200001L, 0x0102040000200080L, 0x0102040000200081L,
+ 0x0102040000204000L, 0x0102040000204001L, 0x0102040000204080L, 0x0102040000204081L,
+ 0x0102040010000000L, 0x0102040010000001L, 0x0102040010000080L, 0x0102040010000081L,
+ 0x0102040010004000L, 0x0102040010004001L, 0x0102040010004080L, 0x0102040010004081L,
+ 0x0102040010200000L, 0x0102040010200001L, 0x0102040010200080L, 0x0102040010200081L,
+ 0x0102040010204000L, 0x0102040010204001L, 0x0102040010204080L, 0x0102040010204081L,
+ 0x0102040800000000L, 0x0102040800000001L, 0x0102040800000080L, 0x0102040800000081L,
+ 0x0102040800004000L, 0x0102040800004001L, 0x0102040800004080L, 0x0102040800004081L,
+ 0x0102040800200000L, 0x0102040800200001L, 0x0102040800200080L, 0x0102040800200081L,
+ 0x0102040800204000L, 0x0102040800204001L, 0x0102040800204080L, 0x0102040800204081L,
+ 0x0102040810000000L, 0x0102040810000001L, 0x0102040810000080L, 0x0102040810000081L,
+ 0x0102040810004000L, 0x0102040810004001L, 0x0102040810004080L, 0x0102040810004081L,
+ 0x0102040810200000L, 0x0102040810200001L, 0x0102040810200080L, 0x0102040810200081L,
+ 0x0102040810204000L, 0x0102040810204001L, 0x0102040810204080L, 0x0102040810204081L
+ };
+
+ // For toString(); must have length 64
+ private static final String ZEROES = "0000000000000000000000000000000000000000000000000000000000000000";
+
+ final static byte[] bitLengths =
+ {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
+ };
+
+ // TODO make m fixed for the LongArray, and hence compute T once and for all
+
+ private long[] m_ints;
+
+ public LongArray(int intLen)
+ {
+ m_ints = new long[intLen];
+ }
+
+ public LongArray(long[] ints)
+ {
+ m_ints = ints;
+ }
+
+ public LongArray(long[] ints, int off, int len)
+ {
+ if (off == 0 && len == ints.length)
+ {
+ m_ints = ints;
+ }
+ else
+ {
+ m_ints = new long[len];
+ System.arraycopy(ints, off, m_ints, 0, len);
+ }
+ }
+
+ public LongArray(BigInteger bigInt)
+ {
+ if (bigInt == null || bigInt.signum() < 0)
+ {
+ throw new IllegalArgumentException("invalid F2m field value");
+ }
+
+ if (bigInt.signum() == 0)
+ {
+ m_ints = new long[] { 0L };
+ return;
+ }
+
+ byte[] barr = bigInt.toByteArray();
+ int barrLen = barr.length;
+ int barrStart = 0;
+ if (barr[0] == 0)
+ {
+ // First byte is 0 to enforce highest (=sign) bit is zero.
+ // In this case ignore barr[0].
+ barrLen--;
+ barrStart = 1;
+ }
+ int intLen = (barrLen + 7) / 8;
+ m_ints = new long[intLen];
+
+ int iarrJ = intLen - 1;
+ int rem = barrLen % 8 + barrStart;
+ long temp = 0;
+ int barrI = barrStart;
+ if (barrStart < rem)
+ {
+ for (; barrI < rem; barrI++)
+ {
+ temp <<= 8;
+ int barrBarrI = barr[barrI] & 0xFF;
+ temp |= barrBarrI;
+ }
+ m_ints[iarrJ--] = temp;
+ }
+
+ for (; iarrJ >= 0; iarrJ--)
+ {
+ temp = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ temp <<= 8;
+ int barrBarrI = barr[barrI++] & 0xFF;
+ temp |= barrBarrI;
+ }
+ m_ints[iarrJ] = temp;
+ }
+ }
+
+ public boolean isZero()
+ {
+ long[] a = m_ints;
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] != 0L)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public int getUsedLength()
+ {
+ return getUsedLengthFrom(m_ints.length);
+ }
+
+ public int getUsedLengthFrom(int from)
+ {
+ long[] a = m_ints;
+ from = Math.min(from, a.length);
+
+ if (from < 1)
+ {
+ return 0;
+ }
+
+ // Check if first element will act as sentinel
+ if (a[0] != 0)
+ {
+ while (a[--from] == 0)
+ {
+ }
+ return from + 1;
+ }
+
+ do
+ {
+ if (a[--from] != 0)
+ {
+ return from + 1;
+ }
+ }
+ while (from > 0);
+
+ return 0;
+ }
+
+ public int degree()
+ {
+ int i = m_ints.length;
+ long w;
+ do
+ {
+ if (i == 0)
+ {
+ return 0;
+ }
+ w = m_ints[--i];
+ }
+ while (w == 0);
+
+ return (i << 6) + bitLength(w);
+ }
+
+ private int degreeFrom(int limit)
+ {
+ int i = (limit + 62) >>> 6;
+ long w;
+ do
+ {
+ if (i == 0)
+ {
+ return 0;
+ }
+ w = m_ints[--i];
+ }
+ while (w == 0);
+
+ return (i << 6) + bitLength(w);
+ }
+
+// private int lowestCoefficient()
+// {
+// for (int i = 0; i < m_ints.length; ++i)
+// {
+// long mi = m_ints[i];
+// if (mi != 0)
+// {
+// int j = 0;
+// while ((mi & 0xFFL) == 0)
+// {
+// j += 8;
+// mi >>>= 8;
+// }
+// while ((mi & 1L) == 0)
+// {
+// ++j;
+// mi >>>= 1;
+// }
+// return (i << 6) + j;
+// }
+// }
+// return -1;
+// }
+
+ private static int bitLength(long w)
+ {
+ int u = (int)(w >>> 32), b;
+ if (u == 0)
+ {
+ u = (int)w;
+ b = 0;
+ }
+ else
+ {
+ b = 32;
+ }
+
+ int t = u >>> 16, k;
+ if (t == 0)
+ {
+ t = u >>> 8;
+ k = (t == 0) ? bitLengths[u] : 8 + bitLengths[t];
+ }
+ else
+ {
+ int v = t >>> 8;
+ k = (v == 0) ? 16 + bitLengths[t] : 24 + bitLengths[v];
+ }
+
+ return b + k;
+ }
+
+ private long[] resizedInts(int newLen)
+ {
+ long[] newInts = new long[newLen];
+ System.arraycopy(m_ints, 0, newInts, 0, Math.min(m_ints.length, newLen));
+ return newInts;
+ }
+
+ public BigInteger toBigInteger()
+ {
+ int usedLen = getUsedLength();
+ if (usedLen == 0)
+ {
+ return ECConstants.ZERO;
+ }
+
+ long highestInt = m_ints[usedLen - 1];
+ byte[] temp = new byte[8];
+ int barrI = 0;
+ boolean trailingZeroBytesDone = false;
+ for (int j = 7; j >= 0; j--)
+ {
+ byte thisByte = (byte)(highestInt >>> (8 * j));
+ if (trailingZeroBytesDone || (thisByte != 0))
+ {
+ trailingZeroBytesDone = true;
+ temp[barrI++] = thisByte;
+ }
+ }
+
+ int barrLen = 8 * (usedLen - 1) + barrI;
+ byte[] barr = new byte[barrLen];
+ for (int j = 0; j < barrI; j++)
+ {
+ barr[j] = temp[j];
+ }
+ // Highest value int is done now
+
+ for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
+ {
+ long mi = m_ints[iarrJ];
+ for (int j = 7; j >= 0; j--)
+ {
+ barr[barrI++] = (byte)(mi >>> (8 * j));
+ }
+ }
+ return new BigInteger(1, barr);
+ }
+
+// private static long shiftUp(long[] x, int xOff, int count)
+// {
+// long prev = 0;
+// for (int i = 0; i < count; ++i)
+// {
+// long next = x[xOff + i];
+// x[xOff + i] = (next << 1) | prev;
+// prev = next >>> 63;
+// }
+// return prev;
+// }
+
+ private static long shiftUp(long[] x, int xOff, int count, int shift)
+ {
+ int shiftInv = 64 - shift;
+ long prev = 0;
+ for (int i = 0; i < count; ++i)
+ {
+ long next = x[xOff + i];
+ x[xOff + i] = (next << shift) | prev;
+ prev = next >>> shiftInv;
+ }
+ return prev;
+ }
+
+ private static long shiftUp(long[] x, int xOff, long[] z, int zOff, int count, int shift)
+ {
+ int shiftInv = 64 - shift;
+ long prev = 0;
+ for (int i = 0; i < count; ++i)
+ {
+ long next = x[xOff + i];
+ z[zOff + i] = (next << shift) | prev;
+ prev = next >>> shiftInv;
+ }
+ return prev;
+ }
+
+ public LongArray addOne()
+ {
+ if (m_ints.length == 0)
+ {
+ return new LongArray(new long[]{ 1L });
+ }
+
+ int resultLen = Math.max(1, getUsedLength());
+ long[] ints = resizedInts(resultLen);
+ ints[0] ^= 1L;
+ return new LongArray(ints);
+ }
+
+// private void addShiftedByBits(LongArray other, int bits)
+// {
+// int words = bits >>> 6;
+// int shift = bits & 0x3F;
+//
+// if (shift == 0)
+// {
+// addShiftedByWords(other, words);
+// return;
+// }
+//
+// int otherUsedLen = other.getUsedLength();
+// if (otherUsedLen == 0)
+// {
+// return;
+// }
+//
+// int minLen = otherUsedLen + words + 1;
+// if (minLen > m_ints.length)
+// {
+// m_ints = resizedInts(minLen);
+// }
+//
+// long carry = addShiftedByBits(m_ints, words, other.m_ints, 0, otherUsedLen, shift);
+// m_ints[otherUsedLen + words] ^= carry;
+// }
+
+ private void addShiftedByBitsSafe(LongArray other, int otherDegree, int bits)
+ {
+ int otherLen = (otherDegree + 63) >>> 6;
+
+ int words = bits >>> 6;
+ int shift = bits & 0x3F;
+
+ if (shift == 0)
+ {
+ add(m_ints, words, other.m_ints, 0, otherLen);
+ return;
+ }
+
+ long carry = addShiftedUp(m_ints, words, other.m_ints, 0, otherLen, shift);
+ if (carry != 0L)
+ {
+ m_ints[otherLen + words] ^= carry;
+ }
+ }
+
+ private static long addShiftedUp(long[] x, int xOff, long[] y, int yOff, int count, int shift)
+ {
+ int shiftInv = 64 - shift;
+ long prev = 0;
+ for (int i = 0; i < count; ++i)
+ {
+ long next = y[yOff + i];
+ x[xOff + i] ^= (next << shift) | prev;
+ prev = next >>> shiftInv;
+ }
+ return prev;
+ }
+
+ private static long addShiftedDown(long[] x, int xOff, long[] y, int yOff, int count, int shift)
+ {
+ int shiftInv = 64 - shift;
+ long prev = 0;
+ int i = count;
+ while (--i >= 0)
+ {
+ long next = y[yOff + i];
+ x[xOff + i] ^= (next >>> shift) | prev;
+ prev = next << shiftInv;
+ }
+ return prev;
+ }
+
+ public void addShiftedByWords(LongArray other, int words)
+ {
+ int otherUsedLen = other.getUsedLength();
+ if (otherUsedLen == 0)
+ {
+ return;
+ }
+
+ int minLen = otherUsedLen + words;
+ if (minLen > m_ints.length)
+ {
+ m_ints = resizedInts(minLen);
+ }
+
+ add(m_ints, words, other.m_ints, 0, otherUsedLen);
+ }
+
+ private static void add(long[] x, int xOff, long[] y, int yOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ x[xOff + i] ^= y[yOff + i];
+ }
+ }
+
+ private static void add(long[] x, int xOff, long[] y, int yOff, long[] z, int zOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = x[xOff + i] ^ y[yOff + i];
+ }
+ }
+
+ private static void addBoth(long[] x, int xOff, long[] y1, int y1Off, long[] y2, int y2Off, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ x[xOff + i] ^= y1[y1Off + i] ^ y2[y2Off + i];
+ }
+ }
+
+ private static void distribute(long[] x, int src, int dst1, int dst2, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ long v = x[src + i];
+ x[dst1 + i] ^= v;
+ x[dst2 + i] ^= v;
+ }
+ }
+
+ public int getLength()
+ {
+ return m_ints.length;
+ }
+
+ private static void flipWord(long[] buf, int off, int bit, long word)
+ {
+ int n = off + (bit >>> 6);
+ int shift = bit & 0x3F;
+ if (shift == 0)
+ {
+ buf[n] ^= word;
+ }
+ else
+ {
+ buf[n] ^= word << shift;
+ word >>>= (64 - shift);
+ if (word != 0)
+ {
+ buf[++n] ^= word;
+ }
+ }
+ }
+
+// private static long getWord(long[] buf, int off, int len, int bit)
+// {
+// int n = off + (bit >>> 6);
+// int shift = bit & 0x3F;
+// if (shift == 0)
+// {
+// return buf[n];
+// }
+// long result = buf[n] >>> shift;
+// if (++n < len)
+// {
+// result |= buf[n] << (64 - shift);
+// }
+// return result;
+// }
+
+ public boolean testBitZero()
+ {
+ return m_ints.length > 0 && (m_ints[0] & 1L) != 0;
+ }
+
+ private static boolean testBit(long[] buf, int off, int n)
+ {
+ // theInt = n / 64
+ int theInt = n >>> 6;
+ // theBit = n % 64
+ int theBit = n & 0x3F;
+ long tester = 1L << theBit;
+ return (buf[off + theInt] & tester) != 0;
+ }
+
+ private static void flipBit(long[] buf, int off, int n)
+ {
+ // theInt = n / 64
+ int theInt = n >>> 6;
+ // theBit = n % 64
+ int theBit = n & 0x3F;
+ long flipper = 1L << theBit;
+ buf[off + theInt] ^= flipper;
+ }
+
+// private static void setBit(long[] buf, int off, int n)
+// {
+// // theInt = n / 64
+// int theInt = n >>> 6;
+// // theBit = n % 64
+// int theBit = n & 0x3F;
+// long setter = 1L << theBit;
+// buf[off + theInt] |= setter;
+// }
+//
+// private static void clearBit(long[] buf, int off, int n)
+// {
+// // theInt = n / 64
+// int theInt = n >>> 6;
+// // theBit = n % 64
+// int theBit = n & 0x3F;
+// long setter = 1L << theBit;
+// buf[off + theInt] &= ~setter;
+// }
+
+ private static void multiplyWord(long a, long[] b, int bLen, long[] c, int cOff)
+ {
+ if ((a & 1L) != 0L)
+ {
+ add(c, cOff, b, 0, bLen);
+ }
+ int k = 1;
+ while ((a >>>= 1) != 0)
+ {
+ if ((a & 1L) != 0L)
+ {
+ long carry = addShiftedUp(c, cOff, b, 0, bLen, k);
+ if (carry != 0)
+ {
+ c[cOff + bLen] ^= carry;
+ }
+ }
+ ++k;
+ }
+ }
+
+ public LongArray modMultiplyLD(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a = A.m_ints[0];
+ if (a == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c = new long[cLen];
+ multiplyWord(a, B.m_ints, bLen, c, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab algorithm
+ */
+
+ for (int k = 56; k >= 0; k -= 8)
+ {
+ for (int j = 1; j < aLen; j += 2)
+ {
+ int aVal = (int)(a[j] >>> k);
+ int u = aVal & MASK;
+ int v = (aVal >>> 4) & MASK;
+ addBoth(c, j - 1, T0, ti[u], T1, ti[v], bMax);
+ }
+ shiftUp(c, 0, cLen, 8);
+ }
+
+ for (int k = 56; k >= 0; k -= 8)
+ {
+ for (int j = 0; j < aLen; j += 2)
+ {
+ int aVal = (int)(a[j] >>> k);
+ int u = aVal & MASK;
+ int v = (aVal >>> 4) & MASK;
+ addBoth(c, j, T0, ti[u], T1, ti[v], bMax);
+ }
+ if (k > 0)
+ {
+ shiftUp(c, 0, cLen, 8);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ public LongArray modMultiply(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a = A.m_ints[0];
+ if (a == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c = new long[cLen];
+ multiplyWord(a, B.m_ints, bLen, c, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen << 3];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab (Modified) algorithm
+ */
+
+ for (int aPos = 0; aPos < aLen; ++aPos)
+ {
+ long aVal = a[aPos];
+ int cOff = aPos;
+ for (;;)
+ {
+ int u = (int)aVal & MASK;
+ aVal >>>= 4;
+ int v = (int)aVal & MASK;
+ addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+ if ((aVal >>>= 4) == 0L)
+ {
+ break;
+ }
+ cOff += cLen;
+ }
+ }
+
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ public LongArray modMultiplyAlt(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a = A.m_ints[0];
+ if (a == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c = new long[cLen];
+ multiplyWord(a, B.m_ints, bLen, c, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+ return reduceResult(c, 0, cLen, m, ks);
+ }
+
+ // NOTE: This works, but is slower than width 4 processing
+// if (aLen == 2)
+// {
+// /*
+// * Use common-multiplicand optimization to save ~1/4 of the adds
+// */
+// long a1 = A.m_ints[0], a2 = A.m_ints[1];
+// long aa = a1 & a2; a1 ^= aa; a2 ^= aa;
+//
+// long[] b = B.m_ints;
+// long[] c = new long[cLen];
+// multiplyWord(aa, b, bLen, c, 1);
+// add(c, 0, c, 1, cLen - 1);
+// multiplyWord(a1, b, bLen, c, 0);
+// multiplyWord(a2, b, bLen, c, 1);
+//
+// /*
+// * Reduce the raw answer against the reduction coefficients
+// */
+// return reduceResult(c, 0, cLen, m, ks);
+// }
+
+ /*
+ * Determine the parameters of the interleaved window algorithm: the 'width' in bits to
+ * process together, the number of evaluation 'positions' implied by that width, and the
+ * 'top' position at which the regular window algorithm stops.
+ */
+ int width, positions, top, banks;
+
+ // NOTE: width 4 is the fastest over the entire range of sizes used in current crypto
+// width = 1; positions = 64; top = 64; banks = 4;
+// width = 2; positions = 32; top = 64; banks = 4;
+// width = 3; positions = 21; top = 63; banks = 3;
+ width = 4; positions = 16; top = 64; banks = 8;
+// width = 5; positions = 13; top = 65; banks = 7;
+// width = 7; positions = 9; top = 63; banks = 9;
+// width = 8; positions = 8; top = 64; banks = 8;
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int shifts = top < 64 ? positions : positions - 1;
+ int bMax = (bDeg + shifts + 63) >>> 6;
+
+ int bTotal = bMax * banks, stride = width * banks;
+
+ /*
+ * Create a single temporary buffer, with an offset table to find the positions of things in it
+ */
+ int[] ci = new int[1 << width];
+ int cTotal = aLen;
+ {
+ ci[0] = cTotal;
+ cTotal += bTotal;
+ ci[1] = cTotal;
+ for (int i = 2; i < ci.length; ++i)
+ {
+ cTotal += cLen;
+ ci[i] = cTotal;
+ }
+ cTotal += cLen;
+ }
+ // NOTE: Provide a safe dump for "high zeroes" since we are adding 'bMax' and not 'bLen'
+ ++cTotal;
+
+ long[] c = new long[cTotal];
+
+ // Prepare A in interleaved form, according to the chosen width
+ interleave(A.m_ints, 0, c, 0, aLen, width);
+
+ // Make a working copy of B, since we will be shifting it
+ {
+ int bOff = aLen;
+ System.arraycopy(B.m_ints, 0, c, bOff, bLen);
+ for (int bank = 1; bank < banks; ++bank)
+ {
+ shiftUp(c, aLen, c, bOff += bMax, bMax, bank);
+ }
+ }
+
+ /*
+ * The main loop analyzes the interleaved windows in A, and for each non-zero window
+ * a single word-array XOR is performed to a carefully selected slice of 'c'. The loop is
+ * breadth-first, checking the lowest window in each word, then looping again for the
+ * next higher window position.
+ */
+ int MASK = (1 << width) - 1;
+
+ int k = 0;
+ for (;;)
+ {
+ int aPos = 0;
+ do
+ {
+ long aVal = c[aPos] >>> k;
+ int bank = 0, bOff = aLen;
+ for (;;)
+ {
+ int index = (int)(aVal) & MASK;
+ if (index != 0)
+ {
+ /*
+ * Add to a 'c' buffer based on the bit-pattern of 'index'. Since A is in
+ * interleaved form, the bits represent the current B shifted by 0, 'positions',
+ * 'positions' * 2, ..., 'positions' * ('width' - 1)
+ */
+ add(c, aPos + ci[index], c, bOff, bMax);
+ }
+ if (++bank == banks)
+ {
+ break;
+ }
+ bOff += bMax;
+ aVal >>>= width;
+ }
+ }
+ while (++aPos < aLen);
+
+ if ((k += stride) >= top)
+ {
+ if (k >= 64)
+ {
+ break;
+ }
+
+ /*
+ * Adjustment for window setups with top == 63, the final bit (if any) is processed
+ * as the top-bit of a window
+ */
+ k = 64 - width;
+ MASK &= MASK << (top - k);
+ }
+
+ /*
+ * After each position has been checked for all words of A, B is shifted up 1 place
+ */
+ shiftUp(c, aLen, bTotal, banks);
+ }
+
+ int ciPos = ci.length;
+ while (--ciPos > 1)
+ {
+ if ((ciPos & 1L) == 0L)
+ {
+ /*
+ * For even numbers, shift contents and add to the half-position
+ */
+ addShiftedUp(c, ci[ciPos >>> 1], c, ci[ciPos], cLen, positions);
+ }
+ else
+ {
+ /*
+ * For odd numbers, 'distribute' contents to the result and the next-lowest position
+ */
+ distribute(c, ci[ciPos], ci[ciPos - 1], ci[1], cLen);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+ return reduceResult(c, ci[1], cLen, m, ks);
+ }
+
+ private static LongArray reduceResult(long[] buf, int off, int len, int m, int[] ks)
+ {
+ int rLen = reduceInPlace(buf, off, len, m, ks);
+ return new LongArray(buf, off, rLen);
+ }
+
+// private static void deInterleave(long[] x, int xOff, long[] z, int zOff, int count, int rounds)
+// {
+// for (int i = 0; i < count; ++i)
+// {
+// z[zOff + i] = deInterleave(x[zOff + i], rounds);
+// }
+// }
+//
+// private static long deInterleave(long x, int rounds)
+// {
+// while (--rounds >= 0)
+// {
+// x = deInterleave32(x & DEINTERLEAVE_MASK) | (deInterleave32((x >>> 1) & DEINTERLEAVE_MASK) << 32);
+// }
+// return x;
+// }
+//
+// private static long deInterleave32(long x)
+// {
+// x = (x | (x >>> 1)) & 0x3333333333333333L;
+// x = (x | (x >>> 2)) & 0x0F0F0F0F0F0F0F0FL;
+// x = (x | (x >>> 4)) & 0x00FF00FF00FF00FFL;
+// x = (x | (x >>> 8)) & 0x0000FFFF0000FFFFL;
+// x = (x | (x >>> 16)) & 0x00000000FFFFFFFFL;
+// return x;
+// }
+
+ private static int reduceInPlace(long[] buf, int off, int len, int m, int[] ks)
+ {
+ int mLen = (m + 63) >>> 6;
+ if (len < mLen)
+ {
+ return len;
+ }
+
+ int numBits = Math.min(len << 6, (m << 1) - 1); // TODO use actual degree?
+ int excessBits = (len << 6) - numBits;
+ while (excessBits >= 64)
+ {
+ --len;
+ excessBits -= 64;
+ }
+
+ int kLen = ks.length, kMax = ks[kLen - 1], kNext = kLen > 1 ? ks[kLen - 2] : 0;
+ int wordWiseLimit = Math.max(m, kMax + 64);
+ int vectorableWords = (excessBits + Math.min(numBits - wordWiseLimit, m - kNext)) >> 6;
+ if (vectorableWords > 1)
+ {
+ int vectorWiseWords = len - vectorableWords;
+ reduceVectorWise(buf, off, len, vectorWiseWords, m, ks);
+ while (len > vectorWiseWords)
+ {
+ buf[off + --len] = 0L;
+ }
+ numBits = vectorWiseWords << 6;
+ }
+
+ if (numBits > wordWiseLimit)
+ {
+ reduceWordWise(buf, off, len, wordWiseLimit, m, ks);
+ numBits = wordWiseLimit;
+ }
+
+ if (numBits > m)
+ {
+ reduceBitWise(buf, off, numBits, m, ks);
+ }
+
+ return mLen;
+ }
+
+ private static void reduceBitWise(long[] buf, int off, int bitlength, int m, int[] ks)
+ {
+ while (--bitlength >= m)
+ {
+ if (testBit(buf, off, bitlength))
+ {
+ reduceBit(buf, off, bitlength, m, ks);
+ }
+ }
+ }
+
+ private static void reduceBit(long[] buf, int off, int bit, int m, int[] ks)
+ {
+ flipBit(buf, off, bit);
+ int base = bit - m;
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipBit(buf, off, ks[j] + base);
+ }
+ flipBit(buf, off, base);
+ }
+
+ private static void reduceWordWise(long[] buf, int off, int len, int toBit, int m, int[] ks)
+ {
+ int toPos = toBit >>> 6;
+
+ while (--len > toPos)
+ {
+ long word = buf[off + len];
+ if (word != 0)
+ {
+ buf[off + len] = 0;
+ reduceWord(buf, off, (len << 6), word, m, ks);
+ }
+ }
+
+ int partial = toBit & 0x3F;
+ long word = buf[off + toPos] >>> partial;
+ if (word != 0)
+ {
+ buf[off + toPos] ^= word << partial;
+ reduceWord(buf, off, toBit, word, m, ks);
+ }
+ }
+
+ private static void reduceWord(long[] buf, int off, int bit, long word, int m, int[] ks)
+ {
+ int offset = bit - m;
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipWord(buf, off, offset + ks[j], word);
+ }
+ flipWord(buf, off, offset, word);
+ }
+
+ private static void reduceVectorWise(long[] buf, int off, int len, int words, int m, int[] ks)
+ {
+ /*
+ * NOTE: It's important we go from highest coefficient to lowest, because for the highest
+ * one (only) we allow the ranges to partially overlap, and therefore any changes must take
+ * effect for the subsequent lower coefficients.
+ */
+ int baseBit = (words << 6) - m;
+ int j = ks.length;
+ while (--j >= 0)
+ {
+ flipVector(buf, off, buf, off + words, len - words, baseBit + ks[j]);
+ }
+ flipVector(buf, off, buf, off + words, len - words, baseBit);
+ }
+
+ private static void flipVector(long[] x, int xOff, long[] y, int yOff, int yLen, int bits)
+ {
+ xOff += bits >>> 6;
+ bits &= 0x3F;
+
+ if (bits == 0)
+ {
+ add(x, xOff, y, yOff, yLen);
+ }
+ else
+ {
+ long carry = addShiftedDown(x, xOff + 1, y, yOff, yLen, 64 - bits);
+ x[xOff] ^= carry;
+ }
+ }
+
+ public LongArray modSquare(int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int _2len = len << 1;
+ long[] r = new long[_2len];
+
+ int pos = 0;
+ while (pos < _2len)
+ {
+ long mi = m_ints[pos >>> 1];
+ r[pos++] = interleave2_32to64((int)mi);
+ r[pos++] = interleave2_32to64((int)(mi >>> 32));
+ }
+
+ return new LongArray(r, 0, reduceInPlace(r, 0, r.length, m, ks));
+ }
+
+// private LongArray modSquareN(int n, int m, int[] ks)
+// {
+// int len = getUsedLength();
+// if (len == 0)
+// {
+// return this;
+// }
+//
+// int mLen = (m + 63) >>> 6;
+// long[] r = new long[mLen << 1];
+// System.arraycopy(m_ints, 0, r, 0, len);
+//
+// while (--n >= 0)
+// {
+// squareInPlace(r, len, m, ks);
+// len = reduceInPlace(r, 0, r.length, m, ks);
+// }
+//
+// return new LongArray(r, 0, len);
+// }
+//
+// private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
+// {
+// int pos = xLen << 1;
+// while (--xLen >= 0)
+// {
+// long xVal = x[xLen];
+// x[--pos] = interleave2_32to64((int)(xVal >>> 32));
+// x[--pos] = interleave2_32to64((int)xVal);
+// }
+// }
+
+ private static void interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
+ {
+ switch (width)
+ {
+ case 3:
+ interleave3(x, xOff, z, zOff, count);
+ break;
+ case 5:
+ interleave5(x, xOff, z, zOff, count);
+ break;
+ case 7:
+ interleave7(x, xOff, z, zOff, count);
+ break;
+ default:
+ interleave2_n(x, xOff, z, zOff, count, bitLengths[width] - 1);
+ break;
+ }
+ }
+
+ private static void interleave3(long[] x, int xOff, long[] z, int zOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = interleave3(x[xOff + i]);
+ }
+ }
+
+ private static long interleave3(long x)
+ {
+ long z = x & (1L << 63);
+ return z
+ | interleave3_21to63((int)x & 0x1FFFFF)
+ | interleave3_21to63((int)(x >>> 21) & 0x1FFFFF) << 1
+ | interleave3_21to63((int)(x >>> 42) & 0x1FFFFF) << 2;
+
+// int zPos = 0, wPos = 0, xPos = 0;
+// for (;;)
+// {
+// z |= ((x >>> xPos) & 1L) << zPos;
+// if (++zPos == 63)
+// {
+// String sz2 = Long.toBinaryString(z);
+// return z;
+// }
+// if ((xPos += 21) >= 63)
+// {
+// xPos = ++wPos;
+// }
+// }
+ }
+
+ private static long interleave3_21to63(int x)
+ {
+ int r00 = INTERLEAVE3_TABLE[x & 0x7F];
+ int r21 = INTERLEAVE3_TABLE[(x >>> 7) & 0x7F];
+ int r42 = INTERLEAVE3_TABLE[x >>> 14];
+ return (r42 & 0xFFFFFFFFL) << 42 | (r21 & 0xFFFFFFFFL) << 21 | (r00 & 0xFFFFFFFFL);
+ }
+
+ private static void interleave5(long[] x, int xOff, long[] z, int zOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = interleave5(x[xOff + i]);
+ }
+ }
+
+ private static long interleave5(long x)
+ {
+ return interleave3_13to65((int)x & 0x1FFF)
+ | interleave3_13to65((int)(x >>> 13) & 0x1FFF) << 1
+ | interleave3_13to65((int)(x >>> 26) & 0x1FFF) << 2
+ | interleave3_13to65((int)(x >>> 39) & 0x1FFF) << 3
+ | interleave3_13to65((int)(x >>> 52) & 0x1FFF) << 4;
+
+// long z = 0;
+// int zPos = 0, wPos = 0, xPos = 0;
+// for (;;)
+// {
+// z |= ((x >>> xPos) & 1L) << zPos;
+// if (++zPos == 64)
+// {
+// return z;
+// }
+// if ((xPos += 13) >= 64)
+// {
+// xPos = ++wPos;
+// }
+// }
+ }
+
+ private static long interleave3_13to65(int x)
+ {
+ int r00 = INTERLEAVE5_TABLE[x & 0x7F];
+ int r35 = INTERLEAVE5_TABLE[x >>> 7];
+ return (r35 & 0xFFFFFFFFL) << 35 | (r00 & 0xFFFFFFFFL);
+ }
+
+ private static void interleave7(long[] x, int xOff, long[] z, int zOff, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = interleave7(x[xOff + i]);
+ }
+ }
+
+ private static long interleave7(long x)
+ {
+ long z = x & (1L << 63);
+ return z
+ | INTERLEAVE7_TABLE[(int)x & 0x1FF]
+ | INTERLEAVE7_TABLE[(int)(x >>> 9) & 0x1FF] << 1
+ | INTERLEAVE7_TABLE[(int)(x >>> 18) & 0x1FF] << 2
+ | INTERLEAVE7_TABLE[(int)(x >>> 27) & 0x1FF] << 3
+ | INTERLEAVE7_TABLE[(int)(x >>> 36) & 0x1FF] << 4
+ | INTERLEAVE7_TABLE[(int)(x >>> 45) & 0x1FF] << 5
+ | INTERLEAVE7_TABLE[(int)(x >>> 54) & 0x1FF] << 6;
+
+// int zPos = 0, wPos = 0, xPos = 0;
+// for (;;)
+// {
+// z |= ((x >>> xPos) & 1L) << zPos;
+// if (++zPos == 63)
+// {
+// return z;
+// }
+// if ((xPos += 9) >= 63)
+// {
+// xPos = ++wPos;
+// }
+// }
+ }
+
+ private static void interleave2_n(long[] x, int xOff, long[] z, int zOff, int count, int rounds)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ z[zOff + i] = interleave2_n(x[xOff + i], rounds);
+ }
+ }
+
+ private static long interleave2_n(long x, int rounds)
+ {
+ while (rounds > 1)
+ {
+ rounds -= 2;
+ x = interleave4_16to64((int)x & 0xFFFF)
+ | interleave4_16to64((int)(x >>> 16) & 0xFFFF) << 1
+ | interleave4_16to64((int)(x >>> 32) & 0xFFFF) << 2
+ | interleave4_16to64((int)(x >>> 48) & 0xFFFF) << 3;
+ }
+ if (rounds > 0)
+ {
+ x = interleave2_32to64((int)x) | interleave2_32to64((int)(x >>> 32)) << 1;
+ }
+ return x;
+ }
+
+ private static long interleave4_16to64(int x)
+ {
+ int r00 = INTERLEAVE4_TABLE[x & 0xFF];
+ int r32 = INTERLEAVE4_TABLE[x >>> 8];
+ return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL);
+ }
+
+ private static long interleave2_32to64(int x)
+ {
+ int r00 = INTERLEAVE2_TABLE[x & 0xFF] | INTERLEAVE2_TABLE[(x >>> 8) & 0xFF] << 16;
+ int r32 = INTERLEAVE2_TABLE[(x >>> 16) & 0xFF] | INTERLEAVE2_TABLE[x >>> 24] << 16;
+ return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL);
+ }
+
+// private static LongArray expItohTsujii2(LongArray B, int n, int m, int[] ks)
+// {
+// LongArray t1 = B, t3 = new LongArray(new long[]{ 1L });
+// int scale = 1;
+//
+// int numTerms = n;
+// while (numTerms > 1)
+// {
+// if ((numTerms & 1) != 0)
+// {
+// t3 = t3.modMultiply(t1, m, ks);
+// t1 = t1.modSquareN(scale, m, ks);
+// }
+//
+// LongArray t2 = t1.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+// numTerms >>>= 1; scale <<= 1;
+// }
+//
+// return t3.modMultiply(t1, m, ks);
+// }
+//
+// private static LongArray expItohTsujii23(LongArray B, int n, int m, int[] ks)
+// {
+// LongArray t1 = B, t3 = new LongArray(new long[]{ 1L });
+// int scale = 1;
+//
+// int numTerms = n;
+// while (numTerms > 1)
+// {
+// boolean m03 = numTerms % 3 == 0;
+// boolean m14 = !m03 && (numTerms & 1) != 0;
+//
+// if (m14)
+// {
+// t3 = t3.modMultiply(t1, m, ks);
+// t1 = t1.modSquareN(scale, m, ks);
+// }
+//
+// LongArray t2 = t1.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+//
+// if (m03)
+// {
+// t2 = t2.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+// numTerms /= 3; scale *= 3;
+// }
+// else
+// {
+// numTerms >>>= 1; scale <<= 1;
+// }
+// }
+//
+// return t3.modMultiply(t1, m, ks);
+// }
+//
+// private static LongArray expItohTsujii235(LongArray B, int n, int m, int[] ks)
+// {
+// LongArray t1 = B, t4 = new LongArray(new long[]{ 1L });
+// int scale = 1;
+//
+// int numTerms = n;
+// while (numTerms > 1)
+// {
+// if (numTerms % 5 == 0)
+// {
+//// t1 = expItohTsujii23(t1, 5, m, ks);
+//
+// LongArray t3 = t1;
+// t1 = t1.modSquareN(scale, m, ks);
+//
+// LongArray t2 = t1.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+// t2 = t1.modSquareN(scale << 1, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+//
+// t1 = t1.modMultiply(t3, m, ks);
+//
+// numTerms /= 5; scale *= 5;
+// continue;
+// }
+//
+// boolean m03 = numTerms % 3 == 0;
+// boolean m14 = !m03 && (numTerms & 1) != 0;
+//
+// if (m14)
+// {
+// t4 = t4.modMultiply(t1, m, ks);
+// t1 = t1.modSquareN(scale, m, ks);
+// }
+//
+// LongArray t2 = t1.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+//
+// if (m03)
+// {
+// t2 = t2.modSquareN(scale, m, ks);
+// t1 = t1.modMultiply(t2, m, ks);
+// numTerms /= 3; scale *= 3;
+// }
+// else
+// {
+// numTerms >>>= 1; scale <<= 1;
+// }
+// }
+//
+// return t4.modMultiply(t1, m, ks);
+// }
+
+ public LongArray modInverse(int m, int[] ks)
+ {
+ /*
+ * Fermat's Little Theorem
+ */
+// LongArray A = this;
+// LongArray B = A.modSquare(m, ks);
+// LongArray R0 = B, R1 = B;
+// for (int i = 2; i < m; ++i)
+// {
+// R1 = R1.modSquare(m, ks);
+// R0 = R0.modMultiply(R1, m, ks);
+// }
+//
+// return R0;
+
+ /*
+ * Itoh-Tsujii
+ */
+// LongArray B = modSquare(m, ks);
+// switch (m)
+// {
+// case 409:
+// return expItohTsujii23(B, m - 1, m, ks);
+// case 571:
+// return expItohTsujii235(B, m - 1, m, ks);
+// case 163:
+// case 233:
+// case 283:
+// default:
+// return expItohTsujii2(B, m - 1, m, ks);
+// }
+
+ /*
+ * Inversion in F2m using the extended Euclidean algorithm
+ *
+ * Input: A nonzero polynomial a(z) of degree at most m-1
+ * Output: a(z)^(-1) mod f(z)
+ */
+ int uzDegree = degree();
+ if (uzDegree == 1)
+ {
+ return this;
+ }
+
+ // u(z) := a(z)
+ LongArray uz = (LongArray)clone();
+
+ int t = (m + 63) >>> 6;
+
+ // v(z) := f(z)
+ LongArray vz = new LongArray(t);
+ reduceBit(vz.m_ints, 0, m, m, ks);
+
+ // g1(z) := 1, g2(z) := 0
+ LongArray g1z = new LongArray(t);
+ g1z.m_ints[0] = 1L;
+ LongArray g2z = new LongArray(t);
+
+ int[] uvDeg = new int[]{ uzDegree, m + 1 };
+ LongArray[] uv = new LongArray[]{ uz, vz };
+
+ int[] ggDeg = new int[]{ 1, 0 };
+ LongArray[] gg = new LongArray[]{ g1z, g2z };
+
+ int b = 1;
+ int duv1 = uvDeg[b];
+ int dgg1 = ggDeg[b];
+ int j = duv1 - uvDeg[1 - b];
+
+ for (;;)
+ {
+ if (j < 0)
+ {
+ j = -j;
+ uvDeg[b] = duv1;
+ ggDeg[b] = dgg1;
+ b = 1 - b;
+ duv1 = uvDeg[b];
+ dgg1 = ggDeg[b];
+ }
+
+ uv[b].addShiftedByBitsSafe(uv[1 - b], uvDeg[1 - b], j);
+
+ int duv2 = uv[b].degreeFrom(duv1);
+ if (duv2 == 0)
+ {
+ return gg[1 - b];
+ }
+
+ {
+ int dgg2 = ggDeg[1 - b];
+ gg[b].addShiftedByBitsSafe(gg[1 - b], dgg2, j);
+ dgg2 += j;
+
+ if (dgg2 > dgg1)
+ {
+ dgg1 = dgg2;
+ }
+ else if (dgg2 == dgg1)
+ {
+ dgg1 = gg[b].degreeFrom(dgg1);
+ }
+ }
+
+ j += (duv2 - duv1);
+ duv1 = duv2;
+ }
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof LongArray))
+ {
+ return false;
+ }
+ LongArray other = (LongArray) o;
+ int usedLen = getUsedLength();
+ if (other.getUsedLength() != usedLen)
+ {
+ return false;
+ }
+ for (int i = 0; i < usedLen; i++)
+ {
+ if (m_ints[i] != other.m_ints[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int usedLen = getUsedLength();
+ int hash = 1;
+ for (int i = 0; i < usedLen; i++)
+ {
+ long mi = m_ints[i];
+ hash *= 31;
+ hash ^= (int)mi;
+ hash *= 31;
+ hash ^= (int)(mi >>> 32);
+ }
+ return hash;
+ }
+
+ public Object clone()
+ {
+ return new LongArray(Arrays.clone(m_ints));
+ }
+
+ public String toString()
+ {
+ int i = getUsedLength();
+ if (i == 0)
+ {
+ return "0";
+ }
+
+ StringBuffer sb = new StringBuffer(Long.toBinaryString(m_ints[--i]));
+ while (--i >= 0)
+ {
+ String s = Long.toBinaryString(m_ints[i]);
+
+ // Add leading zeroes, except for highest significant word
+ int len = s.length();
+ if (len < 64)
+ {
+ sb.append(ZEROES.substring(len));
+ }
+
+ sb.append(s);
+ }
+ return sb.toString();
+ }
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java
new file mode 100644
index 0000000..6d5fe92
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/MixedNafR2LMultiplier.java
@@ -0,0 +1,77 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left) using
+ * mixed coordinates.
+ */
+public class MixedNafR2LMultiplier extends AbstractECMultiplier
+{
+ protected int additionCoord, doublingCoord;
+
+ /**
+ * By default, addition will be done in Jacobian coordinates, and doubling will be done in
+ * Modified Jacobian coordinates (independent of the original coordinate system of each point).
+ */
+ public MixedNafR2LMultiplier()
+ {
+ this(ECCurve.COORD_JACOBIAN, ECCurve.COORD_JACOBIAN_MODIFIED);
+ }
+
+ public MixedNafR2LMultiplier(int additionCoord, int doublingCoord)
+ {
+ this.additionCoord = additionCoord;
+ this.doublingCoord = doublingCoord;
+ }
+
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ ECCurve curveOrig = p.getCurve();
+
+ ECCurve curveAdd = configureCurve(curveOrig, additionCoord);
+ ECCurve curveDouble = configureCurve(curveOrig, doublingCoord);
+
+ int[] naf = WNafUtil.generateCompactNaf(k);
+
+ ECPoint Ra = curveAdd.getInfinity();
+ ECPoint Td = curveDouble.importPoint(p);
+
+ int zeroes = 0;
+ for (int i = 0; i < naf.length; ++i)
+ {
+ int ni = naf[i];
+ int digit = ni >> 16;
+ zeroes += ni & 0xFFFF;
+
+ Td = Td.timesPow2(zeroes);
+
+ ECPoint Tj = curveAdd.importPoint(Td);
+ if (digit < 0)
+ {
+ Tj = Tj.negate();
+ }
+
+ Ra = Ra.add(Tj);
+
+ zeroes = 1;
+ }
+
+ return curveOrig.importPoint(Ra);
+ }
+
+ protected ECCurve configureCurve(ECCurve c, int coord)
+ {
+ if (c.getCoordinateSystem() == coord)
+ {
+ return c;
+ }
+
+ if (!c.supportsCoordinateSystem(coord))
+ {
+ throw new IllegalArgumentException("Coordinate system " + coord + " not supported by this curve");
+ }
+
+ return c.configure().setCoordinateSystem(coord).create();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java
new file mode 100644
index 0000000..cd969b5
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/MontgomeryLadderMultiplier.java
@@ -0,0 +1,25 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public class MontgomeryLadderMultiplier extends AbstractECMultiplier
+{
+ /**
+ * Montgomery ladder.
+ */
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ ECPoint[] R = new ECPoint[]{ p.getCurve().getInfinity(), p };
+
+ int n = k.bitLength();
+ int i = n;
+ while (--i >= 0)
+ {
+ int b = k.testBit(i) ? 1 : 0;
+ int bp = 1 - b;
+ R[bp] = R[bp].add(R[b]);
+ R[b] = R[b].twice();
+ }
+ return R[0];
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java
new file mode 100644
index 0000000..91d91d1
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/NafL2RMultiplier.java
@@ -0,0 +1,30 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (left-to-right).
+ */
+public class NafL2RMultiplier extends AbstractECMultiplier
+{
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ int[] naf = WNafUtil.generateCompactNaf(k);
+
+ ECPoint addP = p.normalize(), subP = addP.negate();
+
+ ECPoint R = p.getCurve().getInfinity();
+
+ int i = naf.length;
+ while (--i >= 0)
+ {
+ int ni = naf[i];
+ int digit = ni >> 16, zeroes = ni & 0xFFFF;
+
+ R = R.twicePlus(digit < 0 ? subP : addP);
+ R = R.timesPow2(zeroes);
+ }
+
+ return R;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java
new file mode 100644
index 0000000..aed2336
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/NafR2LMultiplier.java
@@ -0,0 +1,31 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left).
+ */
+public class NafR2LMultiplier extends AbstractECMultiplier
+{
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ int[] naf = WNafUtil.generateCompactNaf(k);
+
+ ECPoint R0 = p.getCurve().getInfinity(), R1 = p;
+
+ int zeroes = 0;
+ for (int i = 0; i < naf.length; ++i)
+ {
+ int ni = naf[i];
+ int digit = ni >> 16;
+ zeroes += ni & 0xFFFF;
+
+ R1 = R1.timesPow2(zeroes);
+ R0 = R0.add(digit < 0 ? R1.negate() : R1);
+
+ zeroes = 1;
+ }
+
+ return R0;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java
index 804dcf7..3849858 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/PreCompInfo.java
@@ -2,9 +2,9 @@ package org.bouncycastle.math.ec;
/**
* Interface for classes storing precomputation data for multiplication
- * algorithms. Used as a Memento (see GOF patterns) for
- * <code>WNafMultiplier</code>.
+ * algorithms. Used as a Memento (see GOF patterns) by e.g.
+ * <code>WNafL2RMultiplier</code>.
*/
-interface PreCompInfo
+public interface PreCompInfo
{
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java
index c1dd548..3601856 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ReferenceMultiplier.java
@@ -2,7 +2,7 @@ package org.bouncycastle.math.ec;
import java.math.BigInteger;
-class ReferenceMultiplier implements ECMultiplier
+public class ReferenceMultiplier extends AbstractECMultiplier
{
/**
* Simple shift-and-add multiplication. Serves as reference implementation
@@ -13,17 +13,24 @@ class ReferenceMultiplier implements ECMultiplier
* @param k The factor by which to multiply.
* @return The result of the point multiplication <code>k * p</code>.
*/
- public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
{
ECPoint q = p.getCurve().getInfinity();
int t = k.bitLength();
- for (int i = 0; i < t; i++)
+ if (t > 0)
{
- if (k.testBit(i))
+ if (k.testBit(0))
{
- q = q.add(p);
+ q = p;
+ }
+ for (int i = 1; i < t; i++)
+ {
+ p = p.twice();
+ if (k.testBit(i))
+ {
+ q = q.add(p);
+ }
}
- p = p.twice();
}
return q;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java b/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java
index af4355f..42d6738 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/Tnaf.java
@@ -392,15 +392,7 @@ class Tnaf
*/
public static ECPoint.F2m tau(ECPoint.F2m p)
{
- if (p.isInfinity())
- {
- return p;
- }
-
- ECFieldElement x = p.getX();
- ECFieldElement y = p.getY();
-
- return new ECPoint.F2m(p.getCurve(), x.square(), y.square(), p.isCompressed());
+ return p.tau();
}
/**
@@ -415,23 +407,17 @@ class Tnaf
*/
public static byte getMu(ECCurve.F2m curve)
{
- BigInteger a = curve.getA().toBigInteger();
- byte mu;
-
- if (a.equals(ECConstants.ZERO))
- {
- mu = -1;
- }
- else if (a.equals(ECConstants.ONE))
+ if (!curve.isKoblitz())
{
- mu = 1;
+ throw new IllegalArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible");
}
- else
+
+ if (curve.getA().isZero())
{
- throw new IllegalArgumentException("No Koblitz curve (ABC), " +
- "TNAF multiplication not possible");
+ return -1;
}
- return mu;
+
+ return 1;
}
/**
@@ -838,7 +824,9 @@ class Tnaf
{
pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]);
}
-
+
+ p.getCurve().normalizeAll(pu);
+
return pu;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java
new file mode 100644
index 0000000..59a9313
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafL2RMultiplier.java
@@ -0,0 +1,101 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+/**
+ * Class implementing the WNAF (Window Non-Adjacent Form) multiplication
+ * algorithm.
+ */
+public class WNafL2RMultiplier extends AbstractECMultiplier
+{
+ /**
+ * Multiplies <code>this</code> by an integer <code>k</code> using the
+ * Window NAF method.
+ * @param k The integer by which <code>this</code> is multiplied.
+ * @return A new <code>ECPoint</code> which equals <code>this</code>
+ * multiplied by <code>k</code>.
+ */
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ // Clamp the window width in the range [2, 16]
+ int width = Math.max(2, Math.min(16, getWindowSize(k.bitLength())));
+
+ WNafPreCompInfo wnafPreCompInfo = WNafUtil.precompute(p, width, true);
+ ECPoint[] preComp = wnafPreCompInfo.getPreComp();
+ ECPoint[] preCompNeg = wnafPreCompInfo.getPreCompNeg();
+
+ int[] wnaf = WNafUtil.generateCompactWindowNaf(width, k);
+
+ ECPoint R = p.getCurve().getInfinity();
+
+ int i = wnaf.length;
+
+ /*
+ * NOTE This code optimizes the first window using the precomputed points to substitute an
+ * addition for 2 or more doublings.
+ */
+ if (i > 1)
+ {
+ int wi = wnaf[--i];
+ int digit = wi >> 16, zeroes = wi & 0xFFFF;
+
+ int n = Math.abs(digit);
+ ECPoint[] table = digit < 0 ? preCompNeg : preComp;
+
+ /*
+ * NOTE: We use this optimization conservatively, since some coordinate systems have
+ * significantly cheaper doubling relative to addition.
+ *
+ * (n << 2) selects precomputed values in the lower half of the table
+ * (n << 3) selects precomputed values in the lower quarter of the table
+ */
+ //if ((n << 2) < (1 << width))
+ if ((n << 3) < (1 << width))
+ {
+ int highest = LongArray.bitLengths[n];
+ int lowBits = n ^ (1 << (highest - 1));
+ int scale = width - highest;
+
+ int i1 = ((1 << (width - 1)) - 1);
+ int i2 = (lowBits << scale) + 1;
+ R = table[i1 >>> 1].add(table[i2 >>> 1]);
+
+ zeroes -= scale;
+
+// System.out.println("Optimized: 2^" + scale + " * " + n + " = " + i1 + " + " + i2);
+ }
+ else
+ {
+ R = table[n >>> 1];
+ }
+
+ R = R.timesPow2(zeroes);
+ }
+
+ while (i > 0)
+ {
+ int wi = wnaf[--i];
+ int digit = wi >> 16, zeroes = wi & 0xFFFF;
+
+ int n = Math.abs(digit);
+ ECPoint[] table = digit < 0 ? preCompNeg : preComp;
+ ECPoint r = table[n >>> 1];
+
+ R = R.twicePlus(r);
+ R = R.timesPow2(zeroes);
+ }
+
+ return R;
+ }
+
+ /**
+ * Determine window width to use for a scalar multiplication of the given size.
+ *
+ * @param bits the bit-length of the scalar to multiply by
+ * @return the window size to use
+ */
+ protected int getWindowSize(int bits)
+ {
+ return WNafUtil.getWindowSize(bits);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafMultiplier.java
deleted file mode 100644
index 10c8ed2..0000000
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafMultiplier.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class implementing the WNAF (Window Non-Adjacent Form) multiplication
- * algorithm.
- */
-class WNafMultiplier implements ECMultiplier
-{
- /**
- * Computes the Window NAF (non-adjacent Form) of an integer.
- * @param width The width <code>w</code> of the Window NAF. The width is
- * defined as the minimal number <code>w</code>, such that for any
- * <code>w</code> consecutive digits in the resulting representation, at
- * most one is non-zero.
- * @param k The integer of which the Window NAF is computed.
- * @return The Window NAF of the given width, such that the following holds:
- * <code>k = &sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
- * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
- * returned <code>byte[]</code>.
- */
- public byte[] windowNaf(byte width, BigInteger k)
- {
- // The window NAF is at most 1 element longer than the binary
- // representation of the integer k. byte can be used instead of short or
- // int unless the window width is larger than 8. For larger width use
- // short or int. However, a width of more than 8 is not efficient for
- // m = log2(q) smaller than 2305 Bits. Note: Values for m larger than
- // 1000 Bits are currently not used in practice.
- byte[] wnaf = new byte[k.bitLength() + 1];
-
- // 2^width as short and BigInteger
- short pow2wB = (short)(1 << width);
- BigInteger pow2wBI = BigInteger.valueOf(pow2wB);
-
- int i = 0;
-
- // The actual length of the WNAF
- int length = 0;
-
- // while k >= 1
- while (k.signum() > 0)
- {
- // if k is odd
- if (k.testBit(0))
- {
- // k mod 2^width
- BigInteger remainder = k.mod(pow2wBI);
-
- // if remainder > 2^(width - 1) - 1
- if (remainder.testBit(width - 1))
- {
- wnaf[i] = (byte)(remainder.intValue() - pow2wB);
- }
- else
- {
- wnaf[i] = (byte)remainder.intValue();
- }
- // wnaf[i] is now in [-2^(width-1), 2^(width-1)-1]
-
- k = k.subtract(BigInteger.valueOf(wnaf[i]));
- length = i;
- }
- else
- {
- wnaf[i] = 0;
- }
-
- // k = k/2
- k = k.shiftRight(1);
- i++;
- }
-
- length++;
-
- // Reduce the WNAF array to its actual length
- byte[] wnafShort = new byte[length];
- System.arraycopy(wnaf, 0, wnafShort, 0, length);
- return wnafShort;
- }
-
- /**
- * Multiplies <code>this</code> by an integer <code>k</code> using the
- * Window NAF method.
- * @param k The integer by which <code>this</code> is multiplied.
- * @return A new <code>ECPoint</code> which equals <code>this</code>
- * multiplied by <code>k</code>.
- */
- public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
- {
- WNafPreCompInfo wnafPreCompInfo;
-
- if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
- {
- wnafPreCompInfo = (WNafPreCompInfo)preCompInfo;
- }
- else
- {
- // Ignore empty PreCompInfo or PreCompInfo of incorrect type
- wnafPreCompInfo = new WNafPreCompInfo();
- }
-
- // floor(log2(k))
- int m = k.bitLength();
-
- // width of the Window NAF
- byte width;
-
- // Required length of precomputation array
- int reqPreCompLen;
-
- // Determine optimal width and corresponding length of precomputation
- // array based on literature values
- if (m < 13)
- {
- width = 2;
- reqPreCompLen = 1;
- }
- else
- {
- if (m < 41)
- {
- width = 3;
- reqPreCompLen = 2;
- }
- else
- {
- if (m < 121)
- {
- width = 4;
- reqPreCompLen = 4;
- }
- else
- {
- if (m < 337)
- {
- width = 5;
- reqPreCompLen = 8;
- }
- else
- {
- if (m < 897)
- {
- width = 6;
- reqPreCompLen = 16;
- }
- else
- {
- if (m < 2305)
- {
- width = 7;
- reqPreCompLen = 32;
- }
- else
- {
- width = 8;
- reqPreCompLen = 127;
- }
- }
- }
- }
- }
- }
-
- // The length of the precomputation array
- int preCompLen = 1;
-
- ECPoint[] preComp = wnafPreCompInfo.getPreComp();
- ECPoint twiceP = wnafPreCompInfo.getTwiceP();
-
- // Check if the precomputed ECPoints already exist
- if (preComp == null)
- {
- // Precomputation must be performed from scratch, create an empty
- // precomputation array of desired length
- preComp = new ECPoint[]{ p };
- }
- else
- {
- // Take the already precomputed ECPoints to start with
- preCompLen = preComp.length;
- }
-
- if (twiceP == null)
- {
- // Compute twice(p)
- twiceP = p.twice();
- }
-
- if (preCompLen < reqPreCompLen)
- {
- // Precomputation array must be made bigger, copy existing preComp
- // array into the larger new preComp array
- ECPoint[] oldPreComp = preComp;
- preComp = new ECPoint[reqPreCompLen];
- System.arraycopy(oldPreComp, 0, preComp, 0, preCompLen);
-
- for (int i = preCompLen; i < reqPreCompLen; i++)
- {
- // Compute the new ECPoints for the precomputation array.
- // The values 1, 3, 5, ..., 2^(width-1)-1 times p are
- // computed
- preComp[i] = twiceP.add(preComp[i - 1]);
- }
- }
-
- // Compute the Window NAF of the desired width
- byte[] wnaf = windowNaf(width, k);
- int l = wnaf.length;
-
- // Apply the Window NAF to p using the precomputed ECPoint values.
- ECPoint q = p.getCurve().getInfinity();
- for (int i = l - 1; i >= 0; i--)
- {
- q = q.twice();
-
- if (wnaf[i] != 0)
- {
- if (wnaf[i] > 0)
- {
- q = q.add(preComp[(wnaf[i] - 1)/2]);
- }
- else
- {
- // wnaf[i] < 0
- q = q.subtract(preComp[(-wnaf[i] - 1)/2]);
- }
- }
- }
-
- // Set PreCompInfo in ECPoint, such that it is available for next
- // multiplication.
- wnafPreCompInfo.setPreComp(preComp);
- wnafPreCompInfo.setTwiceP(twiceP);
- p.setPreCompInfo(wnafPreCompInfo);
- return q;
- }
-
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
index fc0d5fe..d142ab7 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafPreCompInfo.java
@@ -4,21 +4,23 @@ package org.bouncycastle.math.ec;
* Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
* algorithm.
*/
-class WNafPreCompInfo implements PreCompInfo
+public class WNafPreCompInfo implements PreCompInfo
{
/**
- * Array holding the precomputed <code>ECPoint</code>s used for the Window
- * NAF multiplication in <code>
- * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
- * WNafMultiplier.multiply()}</code>.
+ * Array holding the precomputed <code>ECPoint</code>s used for a Window
+ * NAF multiplication.
*/
private ECPoint[] preComp = null;
/**
+ * Array holding the negations of the precomputed <code>ECPoint</code>s used
+ * for a Window NAF multiplication.
+ */
+ private ECPoint[] preCompNeg = null;
+
+ /**
* Holds an <code>ECPoint</code> representing twice(this). Used for the
- * Window NAF multiplication in <code>
- * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
- * WNafMultiplier.multiply()}</code>.
+ * Window NAF multiplication to create or extend the precomputed values.
*/
private ECPoint twiceP = null;
@@ -27,18 +29,28 @@ class WNafPreCompInfo implements PreCompInfo
return preComp;
}
+ protected ECPoint[] getPreCompNeg()
+ {
+ return preCompNeg;
+ }
+
protected void setPreComp(ECPoint[] preComp)
{
this.preComp = preComp;
}
+ protected void setPreCompNeg(ECPoint[] preCompNeg)
+ {
+ this.preCompNeg = preCompNeg;
+ }
+
protected ECPoint getTwiceP()
{
return twiceP;
}
- protected void setTwiceP(ECPoint twiceThis)
+ protected void setTwiceP(ECPoint twiceP)
{
- this.twiceP = twiceThis;
+ this.twiceP = twiceP;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
new file mode 100644
index 0000000..6465d66
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
@@ -0,0 +1,393 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public abstract class WNafUtil
+{
+ private static int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
+
+ public static int[] generateCompactNaf(BigInteger k)
+ {
+ if ((k.bitLength() >>> 16) != 0)
+ {
+ throw new IllegalArgumentException("'k' must have bitlength < 2^16");
+ }
+
+ BigInteger _3k = k.shiftLeft(1).add(k);
+
+ int digits = _3k.bitLength() - 1;
+ int[] naf = new int[(digits + 1) >> 1];
+
+ int length = 0, zeroes = 0;
+ for (int i = 1; i <= digits; ++i)
+ {
+ boolean _3kBit = _3k.testBit(i);
+ boolean kBit = k.testBit(i);
+
+ if (_3kBit == kBit)
+ {
+ ++zeroes;
+ }
+ else
+ {
+ int digit = kBit ? -1 : 1;
+ naf[length++] = (digit << 16) | zeroes;
+ zeroes = 0;
+ }
+ }
+
+ if (naf.length > length)
+ {
+ naf = trim(naf, length);
+ }
+
+ return naf;
+ }
+
+ public static int[] generateCompactWindowNaf(int width, BigInteger k)
+ {
+ if (width == 2)
+ {
+ return generateCompactNaf(k);
+ }
+
+ if (width < 2 || width > 16)
+ {
+ throw new IllegalArgumentException("'width' must be in the range [2, 16]");
+ }
+ if ((k.bitLength() >>> 16) != 0)
+ {
+ throw new IllegalArgumentException("'k' must have bitlength < 2^16");
+ }
+
+ int[] wnaf = new int[k.bitLength() / width + 1];
+
+ // 2^width and a mask and sign bit set accordingly
+ int pow2 = 1 << width;
+ int mask = pow2 - 1;
+ int sign = pow2 >>> 1;
+
+ boolean carry = false;
+ int length = 0, pos = 0;
+
+ while (pos <= k.bitLength())
+ {
+ if (k.testBit(pos) == carry)
+ {
+ ++pos;
+ continue;
+ }
+
+ k = k.shiftRight(pos);
+
+ int digit = k.intValue() & mask;
+ if (carry)
+ {
+ ++digit;
+ }
+
+ carry = (digit & sign) != 0;
+ if (carry)
+ {
+ digit -= pow2;
+ }
+
+ int zeroes = length > 0 ? pos - 1 : pos;
+ wnaf[length++] = (digit << 16) | zeroes;
+ pos = width;
+ }
+
+ // Reduce the WNAF array to its actual length
+ if (wnaf.length > length)
+ {
+ wnaf = trim(wnaf, length);
+ }
+
+ return wnaf;
+ }
+
+ public static byte[] generateJSF(BigInteger g, BigInteger h)
+ {
+ int digits = Math.max(g.bitLength(), h.bitLength()) + 1;
+ byte[] jsf = new byte[digits];
+
+ BigInteger k0 = g, k1 = h;
+ int j = 0, d0 = 0, d1 = 0;
+
+ while (k0.signum() > 0 || k1.signum() > 0 || d0 > 0 || d1 > 0)
+ {
+ int n0 = (k0.intValue() + d0) & 7, n1 = (k1.intValue() + d1) & 7;
+
+ int u0 = n0 & 1;
+ if (u0 != 0)
+ {
+ u0 -= (n0 & 2);
+ if ((n0 + u0) == 4 && (n1 & 3) == 2)
+ {
+ u0 = -u0;
+ }
+ }
+
+ int u1 = n1 & 1;
+ if (u1 != 0)
+ {
+ u1 -= (n1 & 2);
+ if ((n1 + u1) == 4 && (n0 & 3) == 2)
+ {
+ u1 = -u1;
+ }
+ }
+
+ if ((d0 << 1) == 1 + u0)
+ {
+ d0 = 1 - d0;
+ }
+ if ((d1 << 1) == 1 + u1)
+ {
+ d1 = 1 - d1;
+ }
+
+ k0 = k0.shiftRight(1);
+ k1 = k1.shiftRight(1);
+
+ jsf[j++] = (byte)((u0 << 4) | (u1 & 0xF));
+ }
+
+ // Reduce the JSF array to its actual length
+ if (jsf.length > j)
+ {
+ jsf = trim(jsf, j);
+ }
+
+ return jsf;
+ }
+
+ public static byte[] generateNaf(BigInteger k)
+ {
+ BigInteger _3k = k.shiftLeft(1).add(k);
+
+ int digits = _3k.bitLength() - 1;
+ byte[] naf = new byte[digits];
+
+ for (int i = 1; i <= digits; ++i)
+ {
+ boolean _3kBit = _3k.testBit(i);
+ boolean kBit = k.testBit(i);
+
+ naf[i - 1] = (byte)(_3kBit == kBit ? 0 : kBit ? -1 : 1);
+ }
+
+ return naf;
+ }
+
+ /**
+ * Computes the Window NAF (non-adjacent Form) of an integer.
+ * @param width The width <code>w</code> of the Window NAF. The width is
+ * defined as the minimal number <code>w</code>, such that for any
+ * <code>w</code> consecutive digits in the resulting representation, at
+ * most one is non-zero.
+ * @param k The integer of which the Window NAF is computed.
+ * @return The Window NAF of the given width, such that the following holds:
+ * <code>k = &sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
+ * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
+ * returned <code>byte[]</code>.
+ */
+ public static byte[] generateWindowNaf(int width, BigInteger k)
+ {
+ if (width == 2)
+ {
+ return generateNaf(k);
+ }
+
+ if (width < 2 || width > 8)
+ {
+ throw new IllegalArgumentException("'width' must be in the range [2, 8]");
+ }
+
+ byte[] wnaf = new byte[k.bitLength() + 1];
+
+ // 2^width and a mask and sign bit set accordingly
+ int pow2 = 1 << width;
+ int mask = pow2 - 1;
+ int sign = pow2 >>> 1;
+
+ boolean carry = false;
+ int length = 0, pos = 0;
+
+ while (pos <= k.bitLength())
+ {
+ if (k.testBit(pos) == carry)
+ {
+ ++pos;
+ continue;
+ }
+
+ k = k.shiftRight(pos);
+
+ int digit = k.intValue() & mask;
+ if (carry)
+ {
+ ++digit;
+ }
+
+ carry = (digit & sign) != 0;
+ if (carry)
+ {
+ digit -= pow2;
+ }
+
+ length += (length > 0) ? pos - 1 : pos;
+ wnaf[length++] = (byte)digit;
+ pos = width;
+ }
+
+ // Reduce the WNAF array to its actual length
+ if (wnaf.length > length)
+ {
+ wnaf = trim(wnaf, length);
+ }
+
+ return wnaf;
+ }
+
+ public static WNafPreCompInfo getWNafPreCompInfo(PreCompInfo preCompInfo)
+ {
+ if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo))
+ {
+ return (WNafPreCompInfo)preCompInfo;
+ }
+
+ return new WNafPreCompInfo();
+ }
+
+ /**
+ * Determine window width to use for a scalar multiplication of the given size.
+ *
+ * @param bits the bit-length of the scalar to multiply by
+ * @return the window size to use
+ */
+ public static int getWindowSize(int bits)
+ {
+ return getWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS);
+ }
+
+ /**
+ * Determine window width to use for a scalar multiplication of the given size.
+ *
+ * @param bits the bit-length of the scalar to multiply by
+ * @param windowSizeCutoffs a monotonically increasing list of bit sizes at which to increment the window width
+ * @return the window size to use
+ */
+ public static int getWindowSize(int bits, int[] windowSizeCutoffs)
+ {
+ int w = 0;
+ for (; w < windowSizeCutoffs.length; ++w)
+ {
+ if (bits < windowSizeCutoffs[w])
+ {
+ break;
+ }
+ }
+ return w + 2;
+ }
+
+ public static WNafPreCompInfo precompute(ECPoint p, int width, boolean includeNegated)
+ {
+ ECCurve c = p.getCurve();
+ WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p));
+
+ ECPoint[] preComp = wnafPreCompInfo.getPreComp();
+ if (preComp == null)
+ {
+ preComp = new ECPoint[]{ p };
+ }
+
+ int preCompLen = preComp.length;
+ int reqPreCompLen = 1 << Math.max(0, width - 2);
+
+ if (preCompLen < reqPreCompLen)
+ {
+ ECPoint twiceP = wnafPreCompInfo.getTwiceP();
+ if (twiceP == null)
+ {
+ twiceP = preComp[0].twice().normalize();
+ wnafPreCompInfo.setTwiceP(twiceP);
+ }
+
+ preComp = resizeTable(preComp, reqPreCompLen);
+
+ /*
+ * TODO Okeya/Sakurai paper has precomputation trick and "Montgomery's Trick" to speed this up.
+ * Also, co-Z arithmetic could avoid the subsequent normalization too.
+ */
+ for (int i = preCompLen; i < reqPreCompLen; i++)
+ {
+ /*
+ * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ...,
+ * 2^(width-1)-1 times p are computed
+ */
+ preComp[i] = twiceP.add(preComp[i - 1]);
+ }
+
+ /*
+ * Having oft-used operands in affine form makes operations faster.
+ */
+ c.normalizeAll(preComp);
+ }
+
+ wnafPreCompInfo.setPreComp(preComp);
+
+ if (includeNegated)
+ {
+ ECPoint[] preCompNeg = wnafPreCompInfo.getPreCompNeg();
+
+ int pos;
+ if (preCompNeg == null)
+ {
+ pos = 0;
+ preCompNeg = new ECPoint[reqPreCompLen];
+ }
+ else
+ {
+ pos = preCompNeg.length;
+ if (pos < reqPreCompLen)
+ {
+ preCompNeg = resizeTable(preCompNeg, reqPreCompLen);
+ }
+ }
+
+ while (pos < reqPreCompLen)
+ {
+ preCompNeg[pos] = preComp[pos].negate();
+ ++pos;
+ }
+
+ wnafPreCompInfo.setPreCompNeg(preCompNeg);
+ }
+
+ c.setPreCompInfo(p, wnafPreCompInfo);
+
+ return wnafPreCompInfo;
+ }
+
+ private static byte[] trim(byte[] a, int length)
+ {
+ byte[] result = new byte[length];
+ System.arraycopy(a, 0, result, 0, result.length);
+ return result;
+ }
+
+ private static int[] trim(int[] a, int length)
+ {
+ int[] result = new int[length];
+ System.arraycopy(a, 0, result, 0, result.length);
+ return result;
+ }
+
+ private static ECPoint[] resizeTable(ECPoint[] a, int length)
+ {
+ ECPoint[] result = new ECPoint[length];
+ System.arraycopy(a, 0, result, 0, a.length);
+ return result;
+ }
+}
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 2353979..7bd30ec 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WTauNafMultiplier.java
@@ -6,7 +6,7 @@ import java.math.BigInteger;
* Class implementing the WTNAF (Window
* <code>&tau;</code>-adic Non-Adjacent Form) algorithm.
*/
-class WTauNafMultiplier implements ECMultiplier
+public class WTauNafMultiplier extends AbstractECMultiplier
{
/**
* Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
@@ -16,7 +16,7 @@ class WTauNafMultiplier implements ECMultiplier
* @param k The integer by which to multiply <code>k</code>.
* @return <code>p</code> multiplied by <code>k</code>.
*/
- public ECPoint multiply(ECPoint point, BigInteger k, PreCompInfo preCompInfo)
+ protected ECPoint multiplyPositive(ECPoint point, BigInteger k)
{
if (!(point instanceof ECPoint.F2m))
{
@@ -25,8 +25,7 @@ class WTauNafMultiplier implements ECMultiplier
}
ECPoint.F2m p = (ECPoint.F2m)point;
-
- ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
+ ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
int m = curve.getM();
byte a = curve.getA().toBigInteger().byteValue();
byte mu = curve.getMu();
@@ -34,7 +33,7 @@ class WTauNafMultiplier implements ECMultiplier
ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10);
- return multiplyWTnaf(p, rho, preCompInfo, a, mu);
+ return multiplyWTnaf(p, rho, curve.getPreCompInfo(p), a, mu);
}
/**
@@ -88,7 +87,7 @@ class WTauNafMultiplier implements ECMultiplier
if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo))
{
pu = Tnaf.getPreComp(p, a);
- p.setPreCompInfo(new WTauNafPreCompInfo(pu));
+ curve.setPreCompInfo(p, new WTauNafPreCompInfo(pu));
}
else
{
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java
new file mode 100644
index 0000000..b478dc7
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ZSignedDigitL2RMultiplier.java
@@ -0,0 +1,29 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public class ZSignedDigitL2RMultiplier extends AbstractECMultiplier
+{
+ /**
+ * 'Zeroless' Signed Digit Left-to-Right.
+ */
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ ECPoint addP = p.normalize(), subP = addP.negate();
+
+ ECPoint R0 = addP;
+
+ int n = k.bitLength();
+ int s = k.getLowestSetBit();
+
+ int i = n;
+ while (--i > s)
+ {
+ R0 = R0.twicePlus(k.testBit(i) ? addP : subP);
+ }
+
+ R0 = R0.timesPow2(s);
+
+ return R0;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java
new file mode 100644
index 0000000..baa702f
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ZSignedDigitR2LMultiplier.java
@@ -0,0 +1,30 @@
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+public class ZSignedDigitR2LMultiplier extends AbstractECMultiplier
+{
+ /**
+ * 'Zeroless' Signed Digit Right-to-Left.
+ */
+ protected ECPoint multiplyPositive(ECPoint p, BigInteger k)
+ {
+ ECPoint R0 = p.getCurve().getInfinity(), R1 = p;
+
+ int n = k.bitLength();
+ int s = k.getLowestSetBit();
+
+ R1 = R1.timesPow2(s);
+
+ int i = s;
+ while (++i < n)
+ {
+ R0 = R0.add(k.testBit(i) ? R1 : R1.negate());
+ R1 = R1.twice();
+ }
+
+ R0 = R0.add(R1);
+
+ return R0;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/package.html b/bcprov/src/main/java/org/bouncycastle/math/ec/package.html
deleted file mode 100644
index a02605b..0000000
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Math support for Elliptic Curve.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/ocsp/package.html b/bcprov/src/main/java/org/bouncycastle/ocsp/package.html
deleted file mode 100644
index 2498f2e..0000000
--- a/bcprov/src/main/java/org/bouncycastle/ocsp/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-<b>Deprecated</b>: see the bcpkix distribution (org.bouncycastle.cert.ocsp), classes for dealing Online Certificate Status Protocol (OCSP) - RFC 2560.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/asn1/PQCObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/pqc/asn1/PQCObjectIdentifiers.java
index b97a8f3..d93d995 100644
--- a/bcprov/src/main/java/org/bouncycastle/pqc/asn1/PQCObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/pqc/asn1/PQCObjectIdentifiers.java
@@ -2,26 +2,45 @@ package org.bouncycastle.pqc.asn1;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+/**
+ * PQC:
+ * <p>
+ * { iso(1) identifier-organization(3) dod(6) internet(1) private(4) 1 8301 3 1 3 5 3 ... }
+ */
public interface PQCObjectIdentifiers
{
+ /** 1.3.6.1.4.1.8301.3.1.3.5.3.2 */
public static final ASN1ObjectIdentifier rainbow = new ASN1ObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.5.3.2");
- public static final ASN1ObjectIdentifier rainbowWithSha1 = rainbow.branch("1");
+ /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.1 */
+ public static final ASN1ObjectIdentifier rainbowWithSha1 = rainbow.branch("1");
+ /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.2 */
public static final ASN1ObjectIdentifier rainbowWithSha224 = rainbow.branch("2");
+ /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.3 */
public static final ASN1ObjectIdentifier rainbowWithSha256 = rainbow.branch("3");
+ /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.4 */
public static final ASN1ObjectIdentifier rainbowWithSha384 = rainbow.branch("4");
+ /** 1.3.6.1.4.1.8301.3.1.3.5.3.2.5 */
public static final ASN1ObjectIdentifier rainbowWithSha512 = rainbow.branch("5");
+ /** 1.3.6.1.4.1.8301.3.1.3.3 */
public static final ASN1ObjectIdentifier gmss = new ASN1ObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.3");
- public static final ASN1ObjectIdentifier gmssWithSha1 = gmss.branch("1");
+ /** 1.3.6.1.4.1.8301.3.1.3.3.1 */
+ public static final ASN1ObjectIdentifier gmssWithSha1 = gmss.branch("1");
+ /** 1.3.6.1.4.1.8301.3.1.3.3.2 */
public static final ASN1ObjectIdentifier gmssWithSha224 = gmss.branch("2");
+ /** 1.3.6.1.4.1.8301.3.1.3.3.3 */
public static final ASN1ObjectIdentifier gmssWithSha256 = gmss.branch("3");
+ /** 1.3.6.1.4.1.8301.3.1.3.3.4 */
public static final ASN1ObjectIdentifier gmssWithSha384 = gmss.branch("4");
+ /** 1.3.6.1.4.1.8301.3.1.3.3.5 */
public static final ASN1ObjectIdentifier gmssWithSha512 = gmss.branch("5");
- public static final ASN1ObjectIdentifier mcEliece = new ASN1ObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.4.1");
+ /** 1.3.6.1.4.1.8301.3.1.3.4.1 */
+ public static final ASN1ObjectIdentifier mcEliece = new ASN1ObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.4.1");
- public static final ASN1ObjectIdentifier mcElieceCca2 = new ASN1ObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.4.2");
+ /** 1.3.6.1.4.1.8301.3.1.3.4.2 */
+ public static final ASN1ObjectIdentifier mcElieceCca2 = new ASN1ObjectIdentifier("1.3.6.1.4.1.8301.3.1.3.4.2");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/BouncyCastlePQCProvider.java b/bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/BouncyCastlePQCProvider.java
index 51aa026..340f032 100644
--- a/bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/BouncyCastlePQCProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/BouncyCastlePQCProvider.java
@@ -21,7 +21,7 @@ public class BouncyCastlePQCProvider
extends Provider
implements ConfigurableProvider
{
- private static String info = "BouncyCastle Post-Quantum Security Provider v1.48";
+ private static String info = "BouncyCastle Post-Quantum Security Provider v1.50";
public static String PROVIDER_NAME = "BCPQC";
@@ -46,7 +46,7 @@ public class BouncyCastlePQCProvider
*/
public BouncyCastlePQCProvider()
{
- super(PROVIDER_NAME, 1.48, info);
+ super(PROVIDER_NAME, 1.50, info);
AccessController.doPrivileged(new PrivilegedAction()
{
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
index 457320e..3f7677c 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
@@ -11,7 +11,7 @@ public final class Arrays
{
// static class, hide constructor
}
-
+
public static boolean areEqual(
boolean[] a,
boolean[] b)
@@ -199,36 +199,62 @@ public final class Arrays
return true;
}
- public static boolean areEqual(
- BigInteger[] a,
- BigInteger[] b)
+ public static boolean areEqual(Object[] a, Object[] b)
{
if (a == b)
{
return true;
}
-
if (a == null || b == null)
{
return false;
}
-
if (a.length != b.length)
{
return false;
}
-
for (int i = 0; i != a.length; i++)
{
- if (!a[i].equals(b[i]))
+ Object objA = a[i], objB = b[i];
+ if (objA == null)
+ {
+ if (objB != null)
+ {
+ return false;
+ }
+ }
+ else if (!objA.equals(objB))
{
return false;
}
}
-
return true;
}
+ public static boolean contains(short[] a, short n)
+ {
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] == n)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean contains(int[] a, int n)
+ {
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] == n)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
public static void fill(
byte[] array,
byte value)
@@ -391,7 +417,7 @@ public final class Arrays
return hc;
}
- public static int hashCode(BigInteger[] data)
+ public static int hashCode(Object[] data)
{
if (data == null)
{
@@ -423,6 +449,20 @@ public final class Arrays
return copy;
}
+ public static byte[] clone(byte[] data, byte[] existing)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ if ((existing == null) || (existing.length != data.length))
+ {
+ return clone(data);
+ }
+ System.arraycopy(data, 0, existing, 0, existing.length);
+ return existing;
+ }
+
public static byte[][] clone(byte[][] data)
{
if (data == null)
@@ -470,6 +510,33 @@ public final class Arrays
return copy;
}
+ public static long[] clone(long[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ long[] copy = new long[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ public static long[] clone(long[] data, long[] existing)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ if ((existing == null) || (existing.length != data.length))
+ {
+ return clone(data);
+ }
+ System.arraycopy(data, 0, existing, 0, existing.length);
+ return existing;
+ }
+
public static short[] clone(short[] data)
{
if (data == null)
@@ -576,6 +643,17 @@ public final class Arrays
return tmp;
}
+ /**
+ * Make a copy of a range of bytes from the passed in data array. The range can
+ * extend beyond the end of the input array, in which case the return array will
+ * be padded with zeroes.
+ *
+ * @param data the array from which the data is to be copied.
+ * @param from the start index at which the copying should take place.
+ * @param to the final index of the range (exclusive).
+ *
+ * @return a new byte array containing the range given.
+ */
public static byte[] copyOfRange(byte[] data, int from, int to)
{
int newLength = getLength(from, to);
@@ -660,6 +738,34 @@ public final class Arrays
return newLength;
}
+ public static byte[] append(byte[] a, byte b)
+ {
+ if (a == null)
+ {
+ return new byte[]{ b };
+ }
+
+ int length = a.length;
+ byte[] result = new byte[length + 1];
+ System.arraycopy(a, 0, result, 0, length);
+ result[length] = b;
+ return result;
+ }
+
+ public static int[] append(int[] a, int b)
+ {
+ if (a == null)
+ {
+ return new int[]{ b };
+ }
+
+ int length = a.length;
+ int[] result = new int[length + 1];
+ System.arraycopy(a, 0, result, 0, length);
+ result[length] = b;
+ return result;
+ }
+
public static byte[] concatenate(byte[] a, byte[] b)
{
if (a != null && b != null)
@@ -733,4 +839,18 @@ public final class Arrays
return concatenate(b, c, d);
}
}
+
+ public static byte[] prepend(byte[] a, byte b)
+ {
+ if (a == null)
+ {
+ return new byte[]{ b };
+ }
+
+ int length = a.length;
+ byte[] result = new byte[length + 1];
+ System.arraycopy(a, 0, result, 1, length);
+ result[0] = b;
+ return result;
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java b/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java
index e2fe590..f7f7e68 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/BigIntegers.java
@@ -40,43 +40,25 @@ public final class BigIntegers
* @param value value to be converted.
* @return a byte array without a leading zero byte if present in the signed encoding.
*/
- public static byte[] asUnsignedByteArray(
- int length,
- BigInteger value)
+ public static byte[] asUnsignedByteArray(int length, BigInteger value)
{
byte[] bytes = value.toByteArray();
-
- if (bytes[0] == 0)
+ if (bytes.length == length)
{
- if (bytes.length - 1 > length)
- {
- throw new IllegalArgumentException("standard length exceeded for value");
- }
-
- byte[] tmp = new byte[length];
-
- System.arraycopy(bytes, 1, tmp, tmp.length - (bytes.length - 1), bytes.length - 1);
-
- return tmp;
+ return bytes;
}
- else
- {
- if (bytes.length == length)
- {
- return bytes;
- }
-
- if (bytes.length > length)
- {
- throw new IllegalArgumentException("standard length exceeded for value");
- }
- byte[] tmp = new byte[length];
+ int start = bytes[0] == 0 ? 1 : 0;
+ int count = bytes.length - start;
- System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length);
-
- return tmp;
+ if (count > length)
+ {
+ throw new IllegalArgumentException("standard length exceeded for value");
}
+
+ byte[] tmp = new byte[length];
+ System.arraycopy(bytes, start, tmp, tmp.length - count, count);
+ return tmp;
}
/**
@@ -120,4 +102,20 @@ public final class BigIntegers
// fall back to a faster (restricted) method
return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min);
}
+
+ public static BigInteger fromUnsignedByteArray(byte[] buf)
+ {
+ return new BigInteger(1, buf);
+ }
+
+ public static BigInteger fromUnsignedByteArray(byte[] buf, int off, int length)
+ {
+ byte[] mag = buf;
+ if (off != 0 || length != buf.length)
+ {
+ mag = new byte[length];
+ System.arraycopy(buf, off, mag, 0, length);
+ }
+ return new BigInteger(1, mag);
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Shorts.java b/bcprov/src/main/java/org/bouncycastle/util/Shorts.java
new file mode 100644
index 0000000..258e01e
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/util/Shorts.java
@@ -0,0 +1,9 @@
+package org.bouncycastle.util;
+
+public class Shorts
+{
+ public static Short valueOf(short value)
+ {
+ return Short.valueOf(value);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/package.html b/bcprov/src/main/java/org/bouncycastle/util/encoders/package.html
deleted file mode 100644
index 3be222b..0000000
--- a/bcprov/src/main/java/org/bouncycastle/util/encoders/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for producing and reading Base64 and Hex strings.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/BufferingOutputStream.java b/bcprov/src/main/java/org/bouncycastle/util/io/BufferingOutputStream.java
new file mode 100644
index 0000000..9d5fe14
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/util/io/BufferingOutputStream.java
@@ -0,0 +1,108 @@
+package org.bouncycastle.util.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.bouncycastle.util.Arrays;
+
+/**
+ * An output stream that buffers data to be feed into an encapsulated output stream.
+ * <p>
+ * The stream zeroes out the internal buffer on each flush.
+ * </p>
+ */
+public class BufferingOutputStream
+ extends OutputStream
+{
+ private final OutputStream other;
+ private final byte[] buf;
+
+ private int bufOff;
+
+ /**
+ * Create a buffering stream with the default buffer size (4096).
+ *
+ * @param other output stream to be wrapped.
+ */
+ public BufferingOutputStream(OutputStream other)
+ {
+ this.other = other;
+ this.buf = new byte[4096];
+ }
+
+ /**
+ * Create a buffering stream with a specified buffer size.
+ *
+ * @param other output stream to be wrapped.
+ * @param bufferSize size in bytes for internal buffer.
+ */
+ public BufferingOutputStream(OutputStream other, int bufferSize)
+ {
+ this.other = other;
+ this.buf = new byte[bufferSize];
+ }
+
+ public void write(byte[] bytes, int offset, int len)
+ throws IOException
+ {
+ if (len < buf.length - bufOff)
+ {
+ System.arraycopy(bytes, offset, buf, bufOff, len);
+ bufOff += len;
+ }
+ else
+ {
+ int gap = buf.length - bufOff;
+
+ System.arraycopy(bytes, offset, buf, bufOff, gap);
+ bufOff += gap;
+
+ flush();
+
+ offset += gap;
+ len -= gap;
+ while (len >= buf.length)
+ {
+ other.write(bytes, offset, buf.length);
+ offset += buf.length;
+ len -= buf.length;
+ }
+
+ if (len > 0)
+ {
+ System.arraycopy(bytes, offset, buf, bufOff, len);
+ bufOff += len;
+ }
+ }
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ buf[bufOff++] = (byte)b;
+ if (bufOff == buf.length)
+ {
+ flush();
+ }
+ }
+
+ /**
+ * Flush the internal buffer to the encapsulated output stream. Zero the buffer contents when done.
+ *
+ * @throws IOException on error.
+ */
+ public void flush()
+ throws IOException
+ {
+ other.write(buf, 0, bufOff);
+ bufOff = 0;
+ Arrays.fill(buf, (byte)0);
+ }
+
+ public void close()
+ throws IOException
+ {
+ flush();
+ other.close();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509Store.java b/bcprov/src/main/java/org/bouncycastle/x509/X509Store.java
index 1bfc00f..61d921c 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/X509Store.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/X509Store.java
@@ -1,13 +1,16 @@
package org.bouncycastle.x509;
-import org.bouncycastle.util.Selector;
-import org.bouncycastle.util.Store;
-
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.util.Collection;
+import org.bouncycastle.util.Selector;
+import org.bouncycastle.util.Store;
+
+/**
+ * @deprecated use CollectionStore - this class will be removed.
+ */
public class X509Store
implements Store
{
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/examples/package.html b/bcprov/src/main/java/org/bouncycastle/x509/examples/package.html
deleted file mode 100644
index 6262157..0000000
--- a/bcprov/src/main/java/org/bouncycastle/x509/examples/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-<p>
-Examples for X.509 attribute certificates.
-<p>
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/extension/package.html b/bcprov/src/main/java/org/bouncycastle/x509/extension/package.html
deleted file mode 100644
index 8127aa5..0000000
--- a/bcprov/src/main/java/org/bouncycastle/x509/extension/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-<b>Deprecated:</b> see bcpkix distribution (org.bouncycastle.cert), helper classes for dealing with common X.509 extensions.
-</body>
-</html>
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/package.html b/bcprov/src/main/java/org/bouncycastle/x509/package.html
deleted file mode 100644
index be27c55..0000000
--- a/bcprov/src/main/java/org/bouncycastle/x509/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-<p>
-<b>Deprecated:</b> see bcpkix distribution (org.bouncycastle.cert), classes for supporting the generation of X.509 certificates and X.509 attribute certificates.
-<p>
-</body>
-</html>